From 6705d2473c4ddbe1551937973293b33e46b9e9fb Mon Sep 17 00:00:00 2001
From: Matthew Vernon
+pcre2_get_mark
Get a (*MARK) name
+
pcre2_get_match_data_size
+ Get the size of a match data block
@@ -176,6 +179,9 @@ in the library.
pcre2_get_ovector_count
Get the ovector count
+pcre2_maketables
Build character tables in current locale
+
pcre2_maketables_free
+ Free character tables
diff --git a/doc/html/pcre2.html b/doc/html/pcre2.html
index bc588c4..dc2d058 100644
--- a/doc/html/pcre2.html
+++ b/doc/html/pcre2.html
@@ -162,7 +162,7 @@ listing), and the short pages for individual functions, are concatenated in
pcre2-config show PCRE2 installation configuration information
pcre2api details of PCRE2's native C API
pcre2build building PCRE2
- pcre2callout details of the callout feature
+ pcre2callout details of the pattern callout feature
pcre2compat discussion of Perl compatibility
pcre2convert details of pattern conversion functions
pcre2demo a demonstration C program that uses PCRE2
@@ -198,7 +198,7 @@ use my two initials, followed by the two digits 10, at the domain cam.ac.uk.
pcre2_match
Match a compiled pattern to a subject string
(Perl compatible)
-Last updated: 11 July 2018
+Last updated: 17 September 2018
Copyright © 1997-2018 University of Cambridge.
diff --git a/doc/html/pcre2_compile.html b/doc/html/pcre2_compile.html
index d109eeb..f6485f2 100644
--- a/doc/html/pcre2_compile.html
+++ b/doc/html/pcre2_compile.html
@@ -65,6 +65,7 @@ The option bits are:
PCRE2_EXTENDED Ignore white space and # comments
PCRE2_FIRSTLINE Force matching to be before newline
PCRE2_LITERAL Pattern characters are all literal
+ PCRE2_MATCH_INVALID_UTF Enable support for matching invalid UTF
PCRE2_MATCH_UNSET_BACKREF Match unset backreferences
PCRE2_MULTILINE ^ and $ match newlines within data
PCRE2_NEVER_BACKSLASH_C Lock out the use of \C in patterns
@@ -86,7 +87,12 @@ PCRE2 must be built with Unicode support (the default) in order to use
PCRE2_UTF, PCRE2_UCP and related options.
-The yield of the function is a pointer to a private data structure that +Additional options may be set in the compile context via the +pcre2_set_compile_extra_options +function. +
++The yield of this function is a pointer to a private data structure that contains the compiled pattern, or NULL if an error was detected.
diff --git a/doc/html/pcre2_dfa_match.html b/doc/html/pcre2_dfa_match.html index 8702cca..232e2bc 100644 --- a/doc/html/pcre2_dfa_match.html +++ b/doc/html/pcre2_dfa_match.html @@ -51,6 +51,8 @@ depth limits. The length and startoffset values are code units, no characters. The options are:
PCRE2_ANCHORED Match only at the first position + PCRE2_COPY_MATCHED_SUBJECT + On success, make a private subject copy PCRE2_ENDANCHORED Pattern can match only at end of subject PCRE2_NOTBOL Subject is not the beginning of a line PCRE2_NOTEOL Subject is not the end of a line diff --git a/doc/html/pcre2_get_match_data_size.html b/doc/html/pcre2_get_match_data_size.html new file mode 100644 index 0000000..113ecaa --- /dev/null +++ b/doc/html/pcre2_get_match_data_size.html @@ -0,0 +1,39 @@ + + ++There is also an obsolete option called PCRE2_JIT_INVALID_UTF, which has been +superseded by the pcre2_compile() option PCRE2_MATCH_INVALID_UTF. The old +option is deprecated and may be removed in the future. + +pcre2_get_match_data_size specification + + +pcre2_get_match_data_size man page
++Return to the PCRE2 index page. +
++This page is part of the PCRE2 HTML documentation. It was generated +automatically from the original man page. If there is any nonsense in it, +please consult the man page, in case the conversion went wrong. +
+
+SYNOPSIS +
++#include <pcre2.h> +
++PCRE2_SIZE pcre2_get_match_data_size(pcre2_match_data *match_data); +
+
+DESCRIPTION +
++This function returns the size, in bytes, of the match data block that is its +argument. +
++There is a complete description of the PCRE2 native API in the +pcre2api +page and a description of the POSIX API in the +pcre2posix +page. +
+Return to the PCRE2 index page. +
diff --git a/doc/html/pcre2_jit_compile.html b/doc/html/pcre2_jit_compile.html index 15b0138..873d0dd 100644 --- a/doc/html/pcre2_jit_compile.html +++ b/doc/html/pcre2_jit_compile.html @@ -41,9 +41,16 @@ bits: PCRE2_JIT_PARTIAL_SOFT compile code for soft partial matching PCRE2_JIT_PARTIAL_HARD compile code for hard partial matching
The yield of the function is 0 for success, or a negative error code otherwise. In particular, PCRE2_ERROR_JIT_BADOPTION is returned if JIT is not supported or -if an unknown bit is set in options. +if an unknown bit is set in options. The function can also return +PCRE2_ERROR_NOMEMORY if JIT is unable to allocate executable memory for the +compiler, even if it was because of a system security restriction.
There is a complete description of the PCRE2 native API in the diff --git a/doc/html/pcre2_maketables.html b/doc/html/pcre2_maketables.html index 6d240e3..1963654 100644 --- a/doc/html/pcre2_maketables.html +++ b/doc/html/pcre2_maketables.html @@ -19,7 +19,7 @@ SYNOPSIS #include <pcre2.h>
-const unsigned char *pcre2_maketables(pcre2_general_context *gcontext); +const uint8_t *pcre2_maketables(pcre2_general_context *gcontext);
+Return to the PCRE2 index page. +
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h> +
++void pcre2_maketables_free(pcre2_general_context *gcontext, + const uint8_t *tables); +
++This function discards a set of character tables that were created by a call +to +pcre2_maketables(). +
++The gcontext parameter should match what was used in that call to +account for any custom allocators that might be in use; if it is NULL +the system free() is used. +
++There is a complete description of the PCRE2 native API in the +pcre2api +page. +
+Return to the PCRE2 index page. +
diff --git a/doc/html/pcre2_match.html b/doc/html/pcre2_match.html index ced70bb..90f7fcc 100644 --- a/doc/html/pcre2_match.html +++ b/doc/html/pcre2_match.html @@ -55,11 +55,13 @@ A match context is needed only if you want to: Change the backtracking depth limit Set custom memory management specifically for the match -The length and startoffset values are code -units, not characters. The length may be given as PCRE2_ZERO_TERMINATE for a -subject that is terminated by a binary zero code unit. The options are: +The length and startoffset values are code units, not characters. +The length may be given as PCRE2_ZERO_TERMINATED for a subject that is +terminated by a binary zero code unit. The options are:PCRE2_ANCHORED Match only at the first position + PCRE2_COPY_MATCHED_SUBJECT + On success, make a private subject copy PCRE2_ENDANCHORED Pattern can match only at end of subject PCRE2_NOTBOL Subject string is not the beginning of a line PCRE2_NOTEOL Subject string is not the end of a line diff --git a/doc/html/pcre2_match_data_free.html b/doc/html/pcre2_match_data_free.html index 68a4461..6ba6162 100644 --- a/doc/html/pcre2_match_data_free.html +++ b/doc/html/pcre2_match_data_free.html @@ -31,6 +31,11 @@ using the memory freeing function from the general context or compiled pattern with which it was created, or free() if that was not set.+If the PCRE2_COPY_MATCHED_SUBJECT was used for a successful match using this +match data block, the copy of the subject that was remembered with the block is +also freed. +
+There is a complete description of the PCRE2 native API in the pcre2api page and a description of the POSIX API in the diff --git a/doc/html/pcre2_pattern_info.html b/doc/html/pcre2_pattern_info.html index 2e35709..eaaac6c 100644 --- a/doc/html/pcre2_pattern_info.html +++ b/doc/html/pcre2_pattern_info.html @@ -19,7 +19,8 @@ SYNOPSIS #include <pcre2.h>
-int pcre2_pattern_info(const pcre2 *code, uint32_t what, void *where); +int pcre2_pattern_info(const pcre2_code *code, uint32_t what, + void *where);
DESCRIPTION diff --git a/doc/html/pcre2_set_character_tables.html b/doc/html/pcre2_set_character_tables.html index 5a1bd20..43c02ff 100644 --- a/doc/html/pcre2_set_character_tables.html +++ b/doc/html/pcre2_set_character_tables.html @@ -20,7 +20,7 @@ SYNOPSISint pcre2_set_character_tables(pcre2_compile_context *ccontext, - const unsigned char *tables); + const uint8_t *tables);
DESCRIPTION diff --git a/doc/html/pcre2_set_compile_extra_options.html b/doc/html/pcre2_set_compile_extra_options.html index 7374931..c6c11f7 100644 --- a/doc/html/pcre2_set_compile_extra_options.html +++ b/doc/html/pcre2_set_compile_extra_options.html @@ -20,7 +20,7 @@ SYNOPSISint pcre2_set_compile_extra_options(pcre2_compile_context *ccontext, - PCRE2_SIZE extra_options); + uint32_t extra_options);
DESCRIPTION @@ -31,7 +31,9 @@ housed in a compile context. It completely replaces all the bits. The extra options are:PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES Allow \x{df800} to \x{dfff} in UTF-8 and UTF-32 modes + PCRE2_EXTRA_ALT_BSUX Extended alternate \u, \U, and \x handling PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL Treat all invalid escapes as a literal following character + PCRE2_EXTRA_ESCAPED_CR_IS_LF Interpret \r as \n PCRE2_EXTRA_MATCH_LINE Pattern matches whole lines PCRE2_EXTRA_MATCH_WORD Pattern matches "words"diff --git a/doc/html/pcre2_set_substitute_callout.html b/doc/html/pcre2_set_substitute_callout.html new file mode 100644 index 0000000..7ae3a39 --- /dev/null +++ b/doc/html/pcre2_set_substitute_callout.html @@ -0,0 +1,43 @@ + + +pcre2_set_substitute_callout specification + + +pcre2_set_substitute_callout man page
++Return to the PCRE2 index page. +
++This page is part of the PCRE2 HTML documentation. It was generated +automatically from the original man page. If there is any nonsense in it, +please consult the man page, in case the conversion went wrong. +
+
+SYNOPSIS +
++#include <pcre2.h> +
++int pcre2_set_substitute_callout(pcre2_match_context *mcontext, + int (*callout_function)(pcre2_substitute_callout_block *), + void *callout_data); +
+
+DESCRIPTION +
++This function sets the substitute callout fields in a match context (the first +argument). The second argument specifies a callout function, and the third +argument is an opaque data item that is passed to it. The result of this +function is always zero. +
++There is a complete description of the PCRE2 native API in the +pcre2api +page and a description of the POSIX API in the +pcre2posix +page. +
+Return to the PCRE2 index page. +
diff --git a/doc/html/pcre2_substring_nametable_scan.html b/doc/html/pcre2_substring_nametable_scan.html index 5a44ea9..277affa 100644 --- a/doc/html/pcre2_substring_nametable_scan.html +++ b/doc/html/pcre2_substring_nametable_scan.html @@ -27,8 +27,8 @@ DESCRIPTION
This convenience function finds, for a compiled pattern, the first and last -entries for a given name in the table that translates capturing parenthesis -names into numbers. +entries for a given name in the table that translates capture group names into +numbers.
code Compiled regular expression name Name whose entries required diff --git a/doc/html/pcre2api.html b/doc/html/pcre2api.html index 17f9794..82aabee 100644 --- a/doc/html/pcre2api.html +++ b/doc/html/pcre2api.html @@ -49,7 +49,7 @@ please consult the man page, in case the conversion went wrong.
For example, if the pattern /abc/ is matched against "123abc" with an offset -limit less than 3, the result is PCRE2_ERROR_NO_MATCH. A match can never be +limit less than 3, the result is PCRE2_ERROR_NOMATCH. A match can never be found if the startoffset argument of pcre2_match(), pcre2_dfa_match(), or pcre2_substitute() is greater than the offset limit set in the match context. @@ -1282,21 +1303,24 @@ are needed. The pcre2_code_copy_with_tables() provides this facility. Copies of both the code and the tables are made, with the new code pointing to the new tables. The memory for the new tables is automatically freed when pcre2_code_free() is called for the new copy of the compiled code. If -pcre2_code_copy_withy_tables() is called with a NULL argument, it returns +pcre2_code_copy_with_tables() is called with a NULL argument, it returns NULL.
NOTE: When one of the matching functions is called, pointers to the compiled pattern and the subject string are set in the match data block so that they can -be referenced by the substring extraction functions. After running a match, you -must not free a compiled pattern (or a subject string) until after all -operations on the +be referenced by the substring extraction functions after a successful match. +After running a match, you must not free a compiled pattern or a subject string +until after all operations on the match data block -have taken place. +have taken place, unless, in the case of the subject string, you have used the +PCRE2_COPY_MATCHED_SUBJECT option, which is described in the section entitled +"Option bits for pcre2_match()" +below.
The options argument for pcre2_compile() contains various bit -settings that affect the compilation. It should be zero if no options are +settings that affect the compilation. It should be zero if none of them are required. The available options are described below. Some of them (in particular, those that are compatible with Perl, but some others as well) can also be set and unset from within the pattern (see the detailed description in @@ -1311,8 +1335,9 @@ compilation. The PCRE2_ANCHORED, PCRE2_ENDANCHORED, and PCRE2_NO_UTF_CHECK options can be set at the time of matching as well as at compile time.
-Other, less frequently required compile-time parameters (for example, the -newline setting) can be provided in a compile context (as described +Some additional options and less frequently required compile-time parameters +(for example, the newline setting) can be provided in a compile context (as +described above).
@@ -1326,11 +1351,12 @@ and pcre2_compile() returns a non-NULL value.
There are nearly 100 positive error codes that pcre2_compile() may return if it finds an error in the pattern. There are also some negative error codes -that are used for invalid UTF strings. These are the same as given by -pcre2_match() and pcre2_dfa_match(), and are described in the +that are used for invalid UTF strings when validity checking is in force. These +are the same as given by pcre2_match() and pcre2_dfa_match(), and +are described in the pcre2unicode -page. There is no separate documentation for the positive error codes, because -the textual error messages that are obtained by calling the +documentation. There is no separate documentation for the positive error codes, +because the textual error messages that are obtained by calling the pcre2_get_error_message() function (see "Obtaining a textual error message" below) @@ -1365,7 +1391,13 @@ This code fragment shows a typical straightforward call to &errorcode, /* for error code */ &erroffset, /* for error offset */ NULL); /* no compile context */ - + + +
+The following names for option bits are defined in the pcre2.h header file:
@@ -1405,6 +1437,14 @@ hexadecimal digits, in which case the hexadecimal number defines the code point to match. By default, as in Perl, a hexadecimal number is always expected after \x, but it may have zero, one, or two digits (so, for example, \xz matches a binary zero character followed by z). + ++ECMAscript 6 added additional functionality to \u. This can be accessed using +the PCRE2_EXTRA_ALT_BSUX extra option (see "Extra compile options" +below). +Note that this alternative escape handling applies only to patterns. Neither of +these options affects the processing of replacement strings passed to +pcre2_substitute().
PCRE2_ALT_CIRCUMFLEX@@ -1471,10 +1511,10 @@ independent of the setting of PCRE2_DOTALL.PCRE2_DUPNAMES-If this bit is set, names used to identify capturing subpatterns need not be -unique. This can be helpful for certain types of pattern when it is known that -only one instance of the named subpattern can ever be matched. There are more -details of named subpatterns below; see also the +If this bit is set, names used to identify capture groups need not be unique. +This can be helpful for certain types of pattern when it is known that only one +instance of the named group can ever be matched. There are more details of +named capture groups below; see also the pcre2pattern documentation.@@ -1507,11 +1547,11 @@ the end of the subject. If this bit is set, most white space characters in the pattern are totally ignored except when escaped or inside a character class. However, white space is not allowed within sequences such as (?> that introduce various -parenthesized subpatterns, nor within numerical quantifiers such as {1,3}. -Ignorable white space is permitted between an item and a following quantifier -and between a quantifier and a following + that indicates possessiveness. -PCRE2_EXTENDED is equivalent to Perl's /x option, and it can be changed within -a pattern by a (?x) option setting. +parenthesized groups, nor within numerical quantifiers such as {1,3}. Ignorable +white space is permitted between an item and a following quantifier and between +a quantifier and a following + that indicates possessiveness. PCRE2_EXTENDED is +equivalent to Perl's /x option, and it can be changed within a pattern by a +(?x) option setting.Return the value of the first code unit of any matched string for a pattern where PCRE2_INFO_FIRSTCODETYPE returns 1; otherwise return 0. The third -argument should point to an uint32_t variable. In the 8-bit library, the +argument should point to a uint32_t variable. In the 8-bit library, the value is always less than 256. In the 16-bit library the value can be up to 0xffff. In the 32-bit library in UTF-32 mode the value can be up to 0x10ffff, and up to 0xffffffff when not using UTF-32 mode. @@ -2113,17 +2200,17 @@ Return the size (in bytes) of the data frames that are used to remember backtracking positions when the pattern is processed by pcre2_match() without the use of JIT. The third argument should point to a size_t variable. The frame size depends on the number of capturing parentheses in the -pattern. Each additional capturing group adds two PCRE2_SIZE variables. +pattern. Each additional capture group adds two PCRE2_SIZE variables.When PCRE2 is compiled without Unicode support, PCRE2_EXTENDED recognizes as @@ -1580,14 +1620,22 @@ expression engine is not the most efficient way of doing it. If you are doing a lot of literal matching and are worried about efficiency, you should consider using other approaches. The only other main options that are allowed with PCRE2_LITERAL are: PCRE2_ANCHORED, PCRE2_ENDANCHORED, PCRE2_AUTO_CALLOUT, -PCRE2_CASELESS, PCRE2_FIRSTLINE, PCRE2_NO_START_OPTIMIZE, PCRE2_NO_UTF_CHECK, -PCRE2_UTF, and PCRE2_USE_OFFSET_LIMIT. The extra options PCRE2_EXTRA_MATCH_LINE -and PCRE2_EXTRA_MATCH_WORD are also supported. Any other options cause an -error. +PCRE2_CASELESS, PCRE2_FIRSTLINE, PCRE2_MATCH_INVALID_UTF, +PCRE2_NO_START_OPTIMIZE, PCRE2_NO_UTF_CHECK, PCRE2_UTF, and +PCRE2_USE_OFFSET_LIMIT. The extra options PCRE2_EXTRA_MATCH_LINE and +PCRE2_EXTRA_MATCH_WORD are also supported. Any other options cause an error. +
+ PCRE2_MATCH_INVALID_UTF ++This option forces PCRE2_UTF (see below) and also enables support for matching +by pcre2_match() in subject strings that contain invalid UTF sequences. +This facility is not supported for DFA matching. For details, see the +pcre2unicode +documentation.PCRE2_MATCH_UNSET_BACKREF-If this option is set, a backreference to an unset subpattern group matches an +If this option is set, a backreference to an unset capture group matches an empty string (by default this causes the current matching alternative to fail). A pattern such as (\1)(a) succeeds when this option is set (assuming it can find an "a" in the subject), whereas it fails by default, for Perl @@ -1649,7 +1697,7 @@ If this option is set, it disables the use of numbered capturing parentheses in the pattern. Any opening parenthesis that is not followed by ? behaves as if it were followed by ?: but named parentheses can still be used for capturing (and they acquire numbers in the usual way). This is the same as Perl's /n option. -Note that, when this option is set, references to capturing groups +Note that, when this option is set, references to capture groups (backreferences or recursion/subroutine calls) may only refer to named groups, though the reference can be by name or by number.@@ -1668,7 +1716,7 @@ purposes. If this option is set, it disables an optimization that is applied when .* is the first significant item in a top-level branch of a pattern, and all the other branches also start with .* or with \A or \G or ^. The optimization is -automatically disabled for .* if it is inside an atomic group or a capturing +automatically disabled for .* if it is inside an atomic group or a capture group that is the subject of a backreference, or if the pattern contains (*PRUNE) or (*SKIP). When the optimization is not disabled, such a pattern is automatically anchored if PCRE2_DOTALL is set for all the .* items and @@ -1718,17 +1766,22 @@ subject string does not happen. The first match attempt is run starting from the overall result is "no match".-The "magic number" is placed at the start of each compiled pattern as an simple +The "magic number" is placed at the start of each compiled pattern as a simple check against passing an arbitrary memory pointer. Here is a typical call of pcre2_pattern_info(), to obtain the length of the compiled pattern:-There are also other start-up optimizations. For example, a minimum length for -the subject may be recorded. Consider the pattern +As another start-up optimization makes use of a minimum length for a matching +subject, which is recorded when possible. Consider the pattern
- (*MARK:A)(X|Y) + (*MARK:1)B(*MARK:2)(X|Y)-The minimum length for a match is one character. If the subject is "ABC", there -will be attempts to match "ABC", "BC", and "C". An attempt to match an empty -string at the end of the subject does not take place, because PCRE2 knows that -the subject is now too short, and so the (*MARK) is never encountered. In this -case, the optimization does not affect the overall match result, which is still -"no match", but it does affect the auxiliary information that is returned. +The minimum length for a match is two characters. If the subject is "XXBB", the +"starting character" optimization skips "XX", then tries to match "BB", which +is long enough. In the process, (*MARK:2) is encountered and remembered. When +the match attempt fails, the next "B" is found, but there is only one character +left, so there are no more attempts, and "no match" is returned with the "last +mark seen" set to "2". If NO_START_OPTIMIZE is set, however, matches are tried +at every possible starting position, including at the end of the subject, where +(*MARK:1) is encountered, but there is no "B", so the "last mark seen" that is +returned is "1". In this case, the optimizations do not affect the overall +match result, which is still "no match", but they do affect the auxiliary +information that is returned.PCRE2_NO_UTF_CHECK@@ -1811,9 +1864,8 @@ characters with code points greater than 127. Extra compile options
-Unlike the main compile-time options, the extra options are not saved with the -compiled pattern. The option bits that can be set in a compile context by -calling the pcre2_set_compile_extra_options() function are as follows: +The option bits that can be set in a compile context by calling the +pcre2_set_compile_extra_options() function are as follows:
PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES@@ -1838,6 +1890,14 @@ If the extra option PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is set, surrogate code point values in UTF-8 and UTF-32 patterns no longer provoke errors and are incorporated in the compiled pattern. However, they can only match subject characters if the matching function is called with PCRE2_NO_UTF_CHECK set. ++ PCRE2_EXTRA_ALT_BSUX ++The original option PCRE2_ALT_BSUX causes PCRE2 to process \U, \u, and \x in +the way that ECMAscript (aka JavaScript) does. Additional functionality was +defined by ECMAscript 6; setting PCRE2_EXTRA_ALT_BSUX has the effect of +PCRE2_ALT_BSUX, but in addition it recognizes \u{hhh..} as a hexadecimal +character code, where hhh.. is any number of hexadecimal digits.PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL@@ -1851,11 +1911,22 @@ always causes an error in Perl.If the PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL extra option is passed to -pcre2_compile(), all unrecognized or erroneous escape sequences are +pcre2_compile(), all unrecognized or malformed escape sequences are treated as single-character escapes. For example, \j is a literal "j" and \x{2z} is treated as the literal string "x{2z}". Setting this option means -that typos in patterns may go undetected and have unexpected results. This is a -dangerous option. Use with care. +that typos in patterns may go undetected and have unexpected results. Also note +that a sequence such as [\N{] is interpreted as a malformed attempt at +[\N{...}] and so is treated as [N{] whereas [\N] gives an error because an +unqualified \N is a valid escape sequence but is not supported in a character +class. To reiterate: this is a dangerous option. Use with great care. +
+ PCRE2_EXTRA_ESCAPED_CR_IS_LF ++There are some legacy applications where the escape sequence \r in a pattern +is expected to match a newline. If this option is set, \r in a pattern is +converted to \n so that it matches a LF (linefeed) instead of a CR (carriage +return) character. The option does not affect a literal CR in the pattern, nor +does it affect CR specified as an explicit code point such as \x{0D}.PCRE2_EXTRA_MATCH_LINE@@ -1915,13 +1986,20 @@ Most (but not all) patterns can be optimized by the JIT compiler.
LOCALE SUPPORT
+const uint8_t *pcre2_maketables(pcre2_general_context *gcontext); +
+
+
+void pcre2_maketables_free(pcre2_general_context *gcontext, + const uint8_t *tables); +PCRE2 handles caseless matching, and determines whether characters are letters, digits, or whatever, by reference to a set of tables, indexed by character code -point. This applies only to characters whose code points are less than 256. By -default, higher-valued code points never match escapes such as \w or \d. -However, if PCRE2 is built with Unicode support, all characters can be tested -with \p and \P, or, alternatively, the PCRE2_UCP option can be set when a -pattern is compiled; this causes \w and friends to use Unicode property +point. However, this applies only to characters whose code points are less than +256. By default, higher-valued code points never match escapes such as \w or +\d. When PCRE2 is built with Unicode support (the default), all characters can +be tested with \p and \P, or, alternatively, the PCRE2_UCP option can be set +when a pattern is compiled; this causes \w and friends to use Unicode property support instead of the built-in tables.
@@ -1930,24 +2008,28 @@ with code points greater than 128, you should either use Unicode support, or use locales, but not try to mix the two.
-PCRE2 contains an internal set of character tables that are used by default. +PCRE2 contains a built-in set of character tables that are used by default. These are sufficient for many applications. Normally, the internal tables recognize only ASCII characters. However, when PCRE2 is built, it is possible to cause the internal tables to be rebuilt in the default "C" locale of the local system, which may cause them to be different.
-The internal tables can be overridden by tables supplied by the application +The built-in tables can be overridden by tables supplied by the application that calls PCRE2. These may be created in a different locale from the default. As more and more applications change to using Unicode, the need for this locale support is expected to die away.
External tables are built by calling the pcre2_maketables() function, in -the relevant locale. The result can be passed to pcre2_compile() as often -as necessary, by creating a compile context and calling -pcre2_set_character_tables() to set the tables pointer therein. For -example, to build and use tables that are appropriate for the French locale +the relevant locale. The only argument to this function is a general context, +which can be used to pass a custom memory allocator. If the argument is NULL, +the system malloc() is used. The result can be passed to +pcre2_compile() as often as necessary, by creating a compile context and +calling pcre2_set_character_tables() to set the tables pointer therein. +
++For example, to build and use tables that are appropriate for the French locale (where accented characters with values greater than 128 are treated as letters), the following code could be used:
@@ -1958,9 +2040,7 @@ letters), the following code could be used: re = pcre2_compile(..., ccontext);The locale name "fr_FR" is used on Linux and other Unix-like systems; if you -are using Windows, the name for the French locale is "french". It is the -caller's responsibility to ensure that the memory containing the tables remains -available for as long as it is needed. +are using Windows, the name for the French locale is "french".The pointer that is passed (via the compile context) to pcre2_compile() @@ -1968,6 +2048,13 @@ is saved with the compiled pattern, and the same tables are used by pcre2_match() and pcre_dfa_match(). Thus, for any single pattern, compilation and matching both happen in the same locale, but different patterns can be processed in different locales. +
++It is the caller's responsibility to ensure that the memory containing the +tables remains available while they are still in use. When they are no longer +needed, you can discard them using pcre2_maketables_free(), which should +pass as its first parameter the same global context that was used to create the +tables.
INFORMATION ABOUT A COMPILED PATTERN
@@ -1990,7 +2077,7 @@ the following negative numbers: PCRE2_ERROR_BADOPTION the value of what was invalid PCRE2_ERROR_UNSET the requested field is not set
@@ -2036,7 +2123,7 @@ When .* is the first significant item, anchoring is possible only when all the following are true:Return information about the first code unit of any matched string, for a -non-anchored pattern. The third argument should point to an uint32_t +non-anchored pattern. The third argument should point to a uint32_t variable. If there is a fixed first value, for example, the letter "c" from a pattern such as (cat|cow|coyote), 1 is returned, and the value can be retrieved using PCRE2_INFO_FIRSTCODEUNIT. If there is no fixed first value, but it is @@ -2102,7 +2189,7 @@ is returned..* is not in an atomic group - .* is not in a capturing group that is the subject of a backreference + .* is not in a capture group that is the subject of a backreference PCRE2_DOTALL is in force for .* Neither (*PRUNE) nor (*SKIP) appears in the pattern PCRE2_NO_DOTSTAR_ANCHOR is not set @@ -2047,12 +2134,12 @@ options returned for PCRE2_INFO_ALLOPTIONS. PCRE2_INFO_BACKREFMAXReturn the number of the highest backreference in the pattern. The third -argument should point to an uint32_t variable. Named subpatterns acquire -numbers as well as names, and these count towards the highest backreference. -Backreferences such as \4 or \g{12} match the captured characters of the -given group, but in addition, the check that a capturing group is set in a -conditional subpattern such as (?(3)a|b) is also a backreference. Zero is -returned if there are no backreferences. +argument should point to a uint32_t variable. Named capture groups +acquire numbers as well as names, and these count towards the highest +backreference. Backreferences such as \4 or \g{12} match the captured +characters of the given group, but in addition, the check that a capture +group is set in a conditional group such as (?(3)a|b) is also a backreference. +Zero is returned if there are no backreferences.PCRE2_INFO_BSR@@ -2063,9 +2150,9 @@ that \R matches only CR, LF, or CRLF.PCRE2_INFO_CAPTURECOUNT-Return the highest capturing subpattern number in the pattern. In patterns -where (?| is not used, this is also the total number of capturing subpatterns. -The third argument should point to an uint32_t variable. +Return the highest capture group number in the pattern. In patterns where (?| +is not used, this is also the total number of capture groups. The third +argument should point to a uint32_t variable.PCRE2_INFO_DEPTHLIMIT@@ -2090,7 +2177,7 @@ returned. Otherwise NULL is returned. The third argument should point to a PCRE2_INFO_FIRSTCODETYPEPCRE2_INFO_HASBACKSLASHCReturn 1 if the pattern contains any instances of \C, otherwise 0. The third -argument should point to an uint32_t variable. +argument should point to a uint32_t variable.PCRE2_INFO_HASCRORLFReturn 1 if the pattern contains any explicit matches for CR or LF characters, -otherwise 0. The third argument should point to an uint32_t variable. An +otherwise 0. The third argument should point to a uint32_t variable. An explicit match is either a literal CR or LF character, or \r or \n or one of the equivalent hexadecimal or octal escape sequences.@@ -2139,7 +2226,7 @@ defaulted by the caller of the match function. PCRE2_INFO_JCHANGEDReturn 1 if the (?J) or (?-J) option setting is used in the pattern, otherwise -0. The third argument should point to an uint32_t variable. (?J) and +0. The third argument should point to a uint32_t variable. (?J) and (?-J) set and unset the local PCRE2_DUPNAMES option, respectively.PCRE2_INFO_JITSIZE @@ -2151,7 +2238,7 @@ return zero. The third argument should point to a size_t variable. PCRE2_INFO_LASTCODETYPEReturns 1 if there is a rightmost literal code unit that must exist in any -matched string, other than at its start. The third argument should point to an +matched string, other than at its start. The third argument should point to a uint32_t variable. If there is no such value, 0 is returned. When 1 is returned, the code unit value itself can be retrieved using PCRE2_INFO_LASTCODEUNIT. For anchored patterns, a last literal value is @@ -2164,12 +2251,12 @@ PCRE2_INFO_LASTCODEUNIT), but for /^a\dz\d/ the returned value is 0. Return the value of the rightmost literal code unit that must exist in any matched string, other than at its start, for a pattern where PCRE2_INFO_LASTCODETYPE returns 1. Otherwise, return 0. The third argument -should point to an uint32_t variable. +should point to a uint32_t variable.PCRE2_INFO_MATCHEMPTYReturn 1 if the pattern might match an empty string, otherwise 0. The third -argument should point to an uint32_t variable. When a pattern contains +argument should point to a uint32_t variable. When a pattern contains recursive subroutine calls it is not always possible to determine whether or not it can match an empty string. PCRE2 takes a cautious approach and returns 1 in such cases. @@ -2185,26 +2272,34 @@ defaulted by the caller of the match function.PCRE2_INFO_MAXLOOKBEHIND-Return the number of characters (not code units) in the longest lookbehind -assertion in the pattern. The third argument should point to a uint32_t -integer. This information is useful when doing multi-segment matching using the -partial matching facilities. Note that the simple assertions \b and \B -require a one-character lookbehind. \A also registers a one-character -lookbehind, though it does not actually inspect the previous character. This is -to ensure that at least one character from the old segment is retained when a -new segment is processed. Otherwise, if there are no lookbehinds in the -pattern, \A might match incorrectly at the start of a second or subsequent -segment. +A lookbehind assertion moves back a certain number of characters (not code +units) when it starts to process each of its branches. This request returns the +largest of these backward moves. The third argument should point to a uint32_t +integer. The simple assertions \b and \B require a one-character lookbehind +and cause PCRE2_INFO_MAXLOOKBEHIND to return 1 in the absence of anything +longer. \A also registers a one-character lookbehind, though it does not +actually inspect the previous character. + ++Note that this information is useful for multi-segment matching only +if the pattern contains no nested lookbehinds. For example, the pattern +(?<=a(?<=ba)c) returns a maximum lookbehind of 2, but when it is processed, the +first lookbehind moves back by two characters, matches one character, then the +nested lookbehind also moves back by two characters. This puts the matching +point three characters earlier than it was at the start. +PCRE2_INFO_MAXLOOKBEHIND is really only useful as a debugging tool. See the +pcre2partial +documentation for a discussion of multi-segment matching.
PCRE2_INFO_MINLENGTHIf a minimum length for matching subject strings was computed, its value is -returned. Otherwise the returned value is 0. The value is a number of -characters, which in UTF mode may be different from the number of code units. -The third argument should point to an uint32_t variable. The value is a -lower bound to the length of any matching string. There may not be any strings -of that length that do actually match, but every string that does match is at -least that long. +returned. Otherwise the returned value is 0. This value is not computed when +PCRE2_NO_START_OPTIMIZE is set. The value is a number of characters, which in +UTF mode may be different from the number of code units. The third argument +should point to a uint32_t variable. The value is a lower bound to the +length of any matching string. There may not be any strings of that length that +do actually match, but every string that does match is at least that long.PCRE2_INFO_NAMECOUNT PCRE2_INFO_NAMEENTRYSIZE @@ -2237,20 +2332,20 @@ the parenthesis number. The rest of the entry is the corresponding name, zero terminated.This error is returned when pcre2_match() detects a recursion loop within the pattern. Specifically, it means that either the whole pattern or a -subpattern has been called recursively for the second time at the same position -in the subject string. Some simple patterns that might do this are detected and -faulted at compile time, but more complicated cases, in particular mutual -recursions between two different subpatterns, cannot be detected until matching -is attempted. +capture group has been called recursively for the second time at the same +position in the subject string. Some simple patterns that might do this are +detected and faulted at compile time, but more complicated cases, in particular +mutual recursions between two different groups, cannot be detected until +matching is attempted.-The names are in alphabetical order. If (?| is used to create multiple groups -with the same number, as described in the -section on duplicate subpattern numbers +The names are in alphabetical order. If (?| is used to create multiple capture +groups with the same number, as described in the +section on duplicate group numbers in the pcre2pattern page, the groups may be given the same name, but there is only one entry in the table. Different names for groups of the same number are not permitted.
-Duplicate names for subpatterns with different numbers are permitted, but only -if PCRE2_DUPNAMES is set. They appear in the table in the order in which they -were found in the pattern. In the absence of (?| this is the order of +Duplicate names for capture groups with different numbers are permitted, but +only if PCRE2_DUPNAMES is set. They appear in the table in the order in which +they were found in the pattern. In the absence of (?| this is the order of increasing number; when (?| is used this is not necessarily the case because -later subpatterns may have lower numbers. +later capture groups may have lower numbers.
As a simple example of the name/number table, consider the following pattern @@ -2259,16 +2354,16 @@ space - including newlines - is ignored):
(?<date> (?<year>(\d\d)?\d\d) - (?<month>\d\d) - (?<day>\d\d) )-There are four named subpatterns, so the table has four entries, and each entry -in the table is eight bytes long. The table is as follows, with non-printing -bytes shows in hexadecimal, and undefined bytes shown as ??: +There are four named capture groups, so the table has four entries, and each +entry in the table is eight bytes long. The table is as follows, with +non-printing bytes shows in hexadecimal, and undefined bytes shown as ??:00 01 d a t e 00 ?? 00 05 d a y 00 ?? ?? 00 04 m o n t h 00 00 02 y e a r 00 ??-When writing code to extract data from named subpatterns using the +When writing code to extract data from named capture groups using the name-to-number map, remember that the length of the entries is likely to be different for each compiled pattern.@@ -2393,9 +2488,13 @@ on the error, and is detailed below.When PCRE2_UTF is set at compile time, the validity of the subject as a UTF -string is checked by default when pcre2_match() is subsequently called. -If a non-zero starting offset is given, the check is applied only to that part -of the subject that could be inspected during matching, and there is a check -that the starting offset points to the first code unit of a character or to the -end of the subject. If there are no lookbehind assertions in the pattern, the -check starts at the starting offset. Otherwise, it starts at the length of the -longest lookbehind before the starting offset, or at the start of the subject -if there are not that many characters before the starting offset. Note that the -sequences \b and \B are one-character lookbehinds. +string is checked unless PCRE2_NO_UTF_CHECK is passed to pcre2_match() or +PCRE2_MATCH_INVALID_UTF was passed to pcre2_compile(). The latter special +case is discussed in detail in the +pcre2unicode +documentation. + +When one of the matching functions is called, pointers to the compiled pattern and the subject string are set in the match data block so that they can be -referenced by the extraction functions. After running a match, you must not -free a compiled pattern or a subject string until after all operations on the -match data block (for that match) have taken place. +referenced by the extraction functions after a successful match. After running +a match, you must not free a compiled pattern or a subject string until after +all operations on the match data block (for that match) have taken place, +unless, in the case of the subject string, you have used the +PCRE2_COPY_MATCHED_SUBJECT option, which is described in the section entitled +"Option bits for pcre2_match()" +below.
When a match data block itself is no longer needed, it should be freed by @@ -2507,10 +2606,10 @@ Option bits for pcre2_match()
The unused bits of the options argument for pcre2_match() must be -zero. The only bits that may be set are PCRE2_ANCHORED, PCRE2_ENDANCHORED, -PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART, -PCRE2_NO_JIT, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, and PCRE2_PARTIAL_SOFT. -Their action is described below. +zero. The only bits that may be set are PCRE2_ANCHORED, +PCRE2_COPY_MATCHED_SUBJECT, PCRE2_ENDANCHORED, PCRE2_NOTBOL, PCRE2_NOTEOL, +PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_JIT, PCRE2_NO_UTF_CHECK, +PCRE2_PARTIAL_HARD, and PCRE2_PARTIAL_SOFT. Their action is described below.
Setting PCRE2_ANCHORED or PCRE2_ENDANCHORED at match time is not supported by @@ -2525,6 +2624,22 @@ matching position. If a pattern was compiled with PCRE2_ANCHORED, or turned out to be anchored by virtue of its contents, it cannot be made unachored at matching time. Note that setting the option at match time disables JIT matching. +
+ PCRE2_COPY_MATCHED_SUBJECT ++By default, a pointer to the subject is remembered in the match data block so +that, after a successful match, it can be referenced by the substring +extraction functions. This means that the subject's memory must not be freed +until all such operations are complete. For some applications where the +lifetime of the subject string is not guaranteed, it may be necessary to make a +copy of the subject string, but it is wasteful to do this unless the match is +successful. After a successful match, if PCRE2_COPY_MATCHED_SUBJECT is set, the +subject is copied and the new pointer is remembered in the match data block +instead of the original subject pointer. The memory allocator that was used for +the match block itself is used. The copy is automatically freed when +pcre2_match_data_free() is called to free the match data block. It is also +automatically freed if the match data block is re-used for another match +operation.PCRE2_ENDANCHORED@@ -2580,15 +2695,22 @@ of JIT; it forces matching to be done by the interpreter. PCRE2_NO_UTF_CHECK+In the default case, if a non-zero starting offset is given, the check is +applied only to that part of the subject that could be inspected during +matching, and there is a check that the starting offset points to the first +code unit of a character or to the end of the subject. If there are no +lookbehind assertions in the pattern, the check starts at the starting offset. +Otherwise, it starts at the length of the longest lookbehind before the +starting offset, or at the start of the subject if there are not that many +characters before the starting offset. Note that the sequences \b and \B are +one-character lookbehinds.
The check is carried out before any other processing takes place, and a @@ -2601,31 +2723,37 @@ and UTF-32 strings in the pcre2unicode -page. +documentation.
-If you know that your subject is valid, and you want to skip these checks for +If you know that your subject is valid, and you want to skip this check for performance reasons, you can set the PCRE2_NO_UTF_CHECK option when calling pcre2_match(). You might want to do this for the second and subsequent -calls to pcre2_match() if you are making repeated calls to find other +calls to pcre2_match() if you are making repeated calls to find multiple matches in the same subject string.
-Warning: When PCRE2_NO_UTF_CHECK is set, the effect of passing an invalid +Warning: Unless PCRE2_MATCH_INVALID_UTF was set at compile time, when +PCRE2_NO_UTF_CHECK is set at match time the effect of passing an invalid string as a subject, or an invalid value of startoffset, is undefined. -Your program may crash or loop indefinitely. +Your program may crash or loop indefinitely or give wrong results.
PCRE2_PARTIAL_HARD PCRE2_PARTIAL_SOFTThese options turn on the partial matching feature. A partial match occurs if the end of the subject string is reached successfully, but there are not enough -subject characters to complete the match. If this happens when -PCRE2_PARTIAL_SOFT (but not PCRE2_PARTIAL_HARD) is set, matching continues by -testing any remaining alternatives. Only if no complete match can be found is -PCRE2_ERROR_PARTIAL returned instead of PCRE2_ERROR_NOMATCH. In other words, -PCRE2_PARTIAL_SOFT specifies that the caller is prepared to handle a partial -match, but only if no complete match can be found. +subject characters to complete the match. In addition, either at least one +character must have been inspected or the pattern must contain a lookbehind, or +the pattern must be one that could match an empty string. + ++If this situation arises when PCRE2_PARTIAL_SOFT (but not PCRE2_PARTIAL_HARD) +is set, matching continues by testing any remaining alternatives. Only if no +complete match can be found is PCRE2_ERROR_PARTIAL returned instead of +PCRE2_ERROR_NOMATCH. In other words, PCRE2_PARTIAL_SOFT specifies that the +caller is prepared to handle a partial match, but only if no complete match can +be found.
If PCRE2_PARTIAL_HARD is set, it overrides PCRE2_PARTIAL_SOFT. In this case, if @@ -2691,12 +2819,12 @@ valid newline sequence and explicit \r or \n escapes appear in the pattern. In general, a pattern matches a certain portion of the subject, and in addition, further substrings from the subject may be picked out by parenthesized parts of the pattern. Following the usage in Jeffrey Friedl's -book, this is called "capturing" in what follows, and the phrase "capturing -subpattern" or "capturing group" is used for a fragment of a pattern that picks -out a substring. PCRE2 supports several other kinds of parenthesized subpattern -that do not cause substrings to be captured. The pcre2_pattern_info() -function can be used to find out how many capturing subpatterns there are in a -compiled pattern. +book, this is called "capturing" in what follows, and the phrase "capture +group" (Perl terminology) is used for a fragment of a pattern that picks out a +substring. PCRE2 supports several other kinds of parenthesized group that do +not cause substrings to be captured. The pcre2_pattern_info() function +can be used to find out how many capture groups there are in a compiled +pattern.
You can use auxiliary functions for accessing captured substrings @@ -2745,9 +2873,8 @@ For example, if the pattern (?=ab\K) is matched against "ab", the start and end offset values for the match are 2 and 0.
-If a capturing subpattern group is matched repeatedly within a single match -operation, it is the last portion of the subject that it matched that is -returned. +If a capture group is matched repeatedly within a single match operation, it is +the last portion of the subject that it matched that is returned.
If the ovector is too small to hold all the captured substring offsets, as much @@ -2756,21 +2883,20 @@ substrings are not of interest, pcre2_match() may be called with a match data block whose ovector is of minimum length (that is, one pair).
-It is possible for capturing subpattern number n+1 to match some part of -the subject when subpattern n has not been used at all. For example, if -the string "abc" is matched against the pattern (a|(z))(bc) the return from the -function is 4, and subpatterns 1 and 3 are matched, but 2 is not. When this -happens, both values in the offset pairs corresponding to unused subpatterns -are set to PCRE2_UNSET. +It is possible for capture group number n+1 to match some part of the +subject when group n has not been used at all. For example, if the string +"abc" is matched against the pattern (a|(z))(bc) the return from the function +is 4, and groups 1 and 3 are matched, but 2 is not. When this happens, both +values in the offset pairs corresponding to unused groups are set to +PCRE2_UNSET.
-Offset values that correspond to unused subpatterns at the end of the -expression are also set to PCRE2_UNSET. For example, if the string "abc" is -matched against the pattern (abc)(x(yz)?)? subpatterns 2 and 3 are not matched. -The return from the function is 2, because the highest used capturing -subpattern number is 1. The offsets for for the second and third capturing -subpatterns (assuming the vector is large enough, of course) are set to -PCRE2_UNSET. +Offset values that correspond to unused groups at the end of the expression are +also set to PCRE2_UNSET. For example, if the string "abc" is matched against +the pattern (abc)(x(yz)?)? groups 2 and 3 are not matched. The return from the +function is 2, because the highest used capture group number is 1. The offsets +for for the second and third capture groupss (assuming the vector is large +enough, of course) are set to PCRE2_UNSET.
Elements in the ovector that do not correspond to capturing parentheses in the @@ -2794,22 +2920,23 @@ undefined.
After a successful match, a partial match (PCRE2_ERROR_PARTIAL), or a failure -to match (PCRE2_ERROR_NOMATCH), a (*MARK), (*PRUNE), or (*THEN) name may be -available. The function pcre2_get_mark() can be called to access this -name. The same function applies to all three verbs. It returns a pointer to the -zero-terminated name, which is within the compiled pattern. If no name is +to match (PCRE2_ERROR_NOMATCH), a mark name may be available. The function +pcre2_get_mark() can be called to access this name, which can be +specified in the pattern by any of the backtracking control verbs, not just +(*MARK). The same function applies to all the verbs. It returns a pointer to +the zero-terminated name, which is within the compiled pattern. If no name is available, NULL is returned. The length of the name (excluding the terminating zero) is stored in the code unit that precedes the name. You should use this length instead of relying on the terminating zero if the name might contain a binary zero.
-After a successful match, the name that is returned is the last (*MARK), -(*PRUNE), or (*THEN) name encountered on the matching path through the pattern. -Instances of (*PRUNE) and (*THEN) without names are ignored. Thus, for example, -if the matching path contains (*MARK:A)(*PRUNE), the name "A" is returned. -After a "no match" or a partial match, the last encountered name is returned. -For example, consider this pattern: +After a successful match, the name that is returned is the last mark name +encountered on the matching path through the pattern. Instances of backtracking +verbs without names do not count. Thus, for example, if the matching path +contains (*MARK:A)(*PRUNE), the name "A" is returned. After a "no match" or a +partial match, the last encountered name is returned. For example, consider +this pattern:
^(*MARK:A)((*MARK:B)a|b)c@@ -2824,7 +2951,7 @@ is removed from the pattern above, there is an initial check for the presence of "c" in the subject before running the matching engine. This check fails for "bx", causing a match failure without seeing any marks. You can disable the start-of-match optimizations by setting the PCRE2_NO_START_OPTIMIZE option for -pcre2_compile() or starting the pattern with (*NO_START_OPT). +pcre2_compile() or by starting the pattern with (*NO_START_OPT).After a successful match, a partial match, or one of the invalid UTF errors @@ -2930,7 +3057,8 @@ The backtracking match limit was reached. If a pattern contains many nested backtracking points, heap memory is used to remember them. This error is given when the memory allocation function (default or custom) fails. Note that a different error, PCRE2_ERROR_HEAPLIMIT, is given -if the amount of memory needed exceeds the heap limit. +if the amount of memory needed exceeds the heap limit. PCRE2_ERROR_NOMEMORY is +also returned if PCRE2_COPY_MATCHED_SUBJECT is set and memory allocation fails.
PCRE2_ERROR_NULL@@ -2941,11 +3069,11 @@ as NULL.
OBTAINING A TEXTUAL ERROR MESSAGE
@@ -3022,7 +3150,7 @@ The pcre2_substring_copy_bynumber() function copies a captured substring into a supplied buffer, whereas pcre2_substring_get_bynumber() copies it into new memory, obtained using the same memory allocation function that was used for the match data block. The first two arguments of these functions are a -pointer to the match data block and a capturing group number. +pointer to the match data block and a capture group number.
The final arguments of pcre2_substring_copy_bynumber() are a pointer to @@ -3098,9 +3226,9 @@ calling pcre2_substring_list_free().
If this function encounters a substring that is unset, which can happen when -capturing subpattern number n+1 matches some part of the subject, but -subpattern n has not been used at all, it returns an empty string. This -can be distinguished from a genuine zero-length substring by inspecting the +capture group number n+1 matches some part of the subject, but group +n has not been used at all, it returns an empty string. This can be +distinguished from a genuine zero-length substring by inspecting the appropriate offset in the ovector, which contain PCRE2_UNSET for unset substrings, or by calling pcre2_substring_length_bynumber().
@@ -3130,21 +3258,21 @@ For example, for this pattern:(a+)b(?<xxx>\d+)...-the number of the subpattern called "xxx" is 2. If the name is known to be +the number of the capture group called "xxx" is 2. If the name is known to be unique (PCRE2_DUPNAMES was not set), you can find the number from the name by calling pcre2_substring_number_from_name(). The first argument is the compiled pattern, and the second is the name. The yield of the function is the -subpattern number, PCRE2_ERROR_NOSUBSTRING if there is no subpattern of that -name, or PCRE2_ERROR_NOUNIQUESUBSTRING if there is more than one subpattern of -that name. Given the number, you can extract the substring directly from the -ovector, or use one of the "bynumber" functions described above. +group number, PCRE2_ERROR_NOSUBSTRING if there is no group with that name, or +PCRE2_ERROR_NOUNIQUESUBSTRING if there is more than one group with that name. +Given the number, you can extract the substring directly from the ovector, or +use one of the "bynumber" functions described above.For convenience, there are also "byname" functions that correspond to the "bynumber" functions, the only difference being that the second argument is a name instead of a number. If PCRE2_DUPNAMES is set and there are duplicate names, these functions scan all the groups with the given name, and return the -first named string that is set. +captured substring from the first named group that is set.
If there are no groups with the given name, PCRE2_ERROR_NOSUBSTRING is @@ -3155,34 +3283,38 @@ set, PCRE2_ERROR_UNSET is returned.
Warning: If the pattern uses the (?| feature to set up multiple -subpatterns with the same number, as described in the -section on duplicate subpattern numbers +capture groups with the same number, as described in the +section on duplicate group numbers in the pcre2pattern -page, you cannot use names to distinguish the different subpatterns, because +page, you cannot use names to distinguish the different capture groups, because names are not included in the compiled code. The matching process uses only -numbers. For this reason, the use of different names for subpatterns of the +numbers. For this reason, the use of different names for groups with the same number causes an error at compile time. -
+
CREATING A NEW STRING WITH SUBSTITUTIONS
int pcre2_substitute(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length, PCRE2_SIZE startoffset, uint32_t options, pcre2_match_data *match_data, pcre2_match_context *mcontext, PCRE2_SPTR replacement, - PCRE2_SIZE rlength, PCRE2_UCHAR *\fIoutputbuffer\zfP, + PCRE2_SIZE rlength, PCRE2_UCHAR *outputbuffer, PCRE2_SIZE *outlengthptr);
This function calls pcre2_match() and then makes a copy of the subject -string in outputbuffer, replacing the part that was matched with the -replacement string, whose length is supplied in rlength. This can -be given as PCRE2_ZERO_TERMINATED for a zero-terminated string. Matches in -which a \K item in a lookahead in the pattern causes the match to end before -it starts are not supported, and give rise to an error return. For global -replacements, matches in which \K in a lookbehind causes the match to start -earlier than the point that was reached in the previous iteration are also not -supported. +string in outputbuffer, replacing one or more parts that were matched +with the replacement string, whose length is supplied in rlength. +This can be given as PCRE2_ZERO_TERMINATED for a zero-terminated string. +The default is to perform just one replacement, but there is an option that +requests multiple replacements (see PCRE2_SUBSTITUTE_GLOBAL below for details). +
++Matches in which a \K item in a lookahead in the pattern causes the match to +end before it starts are not supported, and give rise to an error return. For +global replacements, matches in which \K in a lookbehind causes the match to +start earlier than the point that was reached in the previous iteration are +also not supported.
The first seven arguments of pcre2_substitute() are the same as for @@ -3194,9 +3326,9 @@ allocate memory for the compiled code.
If an external match_data block is provided, its contents afterwards -are those set by the final call to pcre2_match(), which will have -ended in a matching error. The contents of the ovector within the match data -block may or may not have been changed. +are those set by the final call to pcre2_match(). For global changes, +this will have ended in a matching error. The contents of the ovector within +the match data block may or may not have been changed.
The outlengthptr argument must point to a variable that contains the @@ -3220,12 +3352,12 @@ length is in code units, not bytes. In the replacement string, which is interpreted as a UTF string in UTF mode, and is checked for UTF validity unless the PCRE2_NO_UTF_CHECK option is set, a dollar character is an escape character that can specify the insertion of -characters from capturing groups or (*MARK), (*PRUNE), or (*THEN) items in the -pattern. The following forms are always recognized: +characters from capture groups or names from (*MARK) or other control verbs +in the pattern. The following forms are always recognized:
$$ insert a dollar character $<n> or ${<n>} insert the contents of group <n> - $*MARK or ${*MARK} insert a (*MARK), (*PRUNE), or (*THEN) name + $*MARK or ${*MARK} insert a control verb nameEither a group number or a group name can be given for <n>. Curly brackets are required only if the following character would be interpreted as part of the @@ -3234,11 +3366,11 @@ For example, if the pattern a(b)c is matched with "=abc=" and the replacement string "+$1$0$1+", the result is "=+babcb+=".-$*MARK inserts the name from the last encountered (*MARK), (*PRUNE), or (*THEN) -on the matching path that has a name. (*MARK) must always include a name, but -(*PRUNE) and (*THEN) need not. For example, in the case of (*MARK:A)(*PRUNE) -the name inserted is "A", but for (*MARK:A)(*PRUNE:B) the relevant name is "B". -This facility can be used to perform simple simultaneous substitutions, as this +$*MARK inserts the name from the last encountered backtracking control verb on +the matching path that has a name. (*MARK) must always include a name, but the +other verbs need not. For example, in the case of (*MARK:A)(*PRUNE) the name +inserted is "A", but for (*MARK:A)(*PRUNE:B) the relevant name is "B". This +facility can be used to perform simple simultaneous substitutions, as this pcre2test example shows:
/(*MARK:pear)apple|(*MARK:orange)lemon/g,replace=${*MARK} @@ -3289,13 +3421,13 @@ efficient to allocate a large buffer and free the excess afterwards, instead of using PCRE2_SUBSTITUTE_OVERFLOW_LENGTH.-PCRE2_SUBSTITUTE_UNKNOWN_UNSET causes references to capturing groups that do +PCRE2_SUBSTITUTE_UNKNOWN_UNSET causes references to capture groups that do not appear in the pattern to be treated as unset groups. This option should be used with care, because it means that a typo in a group name or number no longer causes the PCRE2_ERROR_NOSUBSTRING error.
-PCRE2_SUBSTITUTE_UNSET_EMPTY causes unset capturing groups (including unknown +PCRE2_SUBSTITUTE_UNSET_EMPTY causes unset capture groups (including unknown groups when PCRE2_SUBSTITUTE_UNKNOWN_UNSET is set) to be treated as empty strings when inserted as described above. If this option is not set, an attempt to insert an unset group causes the PCRE2_ERROR_UNSET error. This option does @@ -3323,16 +3455,18 @@ terminating a \Q quoted sequence) reverts to no case forcing. The sequences \u and \l force the next character (if it is a letter) to upper or lower case, respectively, and then the state automatically reverts to no case forcing. Case forcing applies to all inserted characters, including those from -captured groups and letters within \Q...\E quoted sequences. +capture groups and letters within \Q...\E quoted sequences.
Note that case forcing sequences such as \U...\E do not nest. For example, the result of processing "\Uaa\LBB\Ecc\E" is "AAbbcc"; the final \E has no -effect. +effect. Note also that the PCRE2_ALT_BSUX and PCRE2_EXTRA_ALT_BSUX options do +not apply to replacement strings.
The second effect of setting PCRE2_SUBSTITUTE_EXTENDED is to add more -flexibility to group substitution. The syntax is similar to that used by Bash: +flexibility to capture group substitution. The syntax is similar to that used +by Bash:
${<n>:-<string>} ${<n>:+<string1>:<string2>} @@ -3360,9 +3494,9 @@ substitutions. However, PCRE2_SUBSTITUTE_UNKNOWN_UNSET does cause unknown groups in the extended syntax forms to be treated as unset.-If successful, pcre2_substitute() returns the number of replacements that -were made. This may be zero if no matches were found, and is never greater than -1 unless PCRE2_SUBSTITUTE_GLOBAL is set. +If successful, pcre2_substitute() returns the number of successful +matches. This may be zero if no matches were found, and is never greater than 1 +unless PCRE2_SUBSTITUTE_GLOBAL is set.
In the event of an error, a negative error code is returned. Except for @@ -3399,20 +3533,84 @@ obtained by calling the pcre2_get_error_message() function (see "Obtaining a textual error message" above).
-
DUPLICATE SUBPATTERN NAMES
+
+Substitution callouts +
++int pcre2_set_substitute_callout(pcre2_match_context *mcontext, + int (*callout_function)(pcre2_substitute_callout_block *, void *), + void *callout_data); +
+
+
+The pcre2_set_substitution_callout() function can be used to specify a +callout function for pcre2_substitute(). This information is passed in +a match context. The callout function is called after each substitution has +been processed, but it can cause the replacement not to happen. The callout +function is not called for simulated substitutions that happen as a result of +the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option. ++The first argument of the callout function is a pointer to a substitute callout +block structure, which contains the following fields, not necessarily in this +order: +
+ uint32_t version; + uint32_t subscount; + PCRE2_SPTR input; + PCRE2_SPTR output; + PCRE2_SIZE *ovector; + uint32_t oveccount; + PCRE2_SIZE output_offsets[2]; ++The version field contains the version number of the block format. The +current version is 0. The version number will increase in future if more fields +are added, but the intention is never to remove any of the existing fields. + ++The subscount field is the number of the current match. It is 1 for the +first callout, 2 for the second, and so on. The input and output +pointers are copies of the values passed to pcre2_substitute(). +
++The ovector field points to the ovector, which contains the result of the +most recent match. The oveccount field contains the number of pairs that +are set in the ovector, and is always greater than zero. +
++The output_offsets vector contains the offsets of the replacement in the +output string. This has already been processed for dollar and (if requested) +backslash substitutions as described above. +
++The second argument of the callout function is the value passed as +callout_data when the function was registered. The value returned by the +callout function is interpreted as follows: +
++If the value is zero, the replacement is accepted, and, if +PCRE2_SUBSTITUTE_GLOBAL is set, processing continues with a search for the next +match. If the value is not zero, the current replacement is not accepted. If +the value is greater than zero, processing continues when +PCRE2_SUBSTITUTE_GLOBAL is set. Otherwise (the value is less than zero or +PCRE2_SUBSTITUTE_GLOBAL is not set), the the rest of the input is copied to the +output and the call to pcre2_substitute() exits, returning the number of +matches so far. +
+
DUPLICATE CAPTURE GROUP NAMES
int pcre2_substring_nametable_scan(const pcre2_code *code, PCRE2_SPTR name, PCRE2_SPTR *first, PCRE2_SPTR *last);
-When a pattern is compiled with the PCRE2_DUPNAMES option, names for -subpatterns are not required to be unique. Duplicate names are always allowed -for subpatterns with the same number, created by using the (?| feature. Indeed, -if such subpatterns are named, they are required to use the same names. +When a pattern is compiled with the PCRE2_DUPNAMES option, names for capture +groups are not required to be unique. Duplicate names are always allowed for +groups with the same number, created by using the (?| feature. Indeed, if such +groups are named, they are required to use the same names.
-Normally, patterns with duplicate names are such that in any one match, only -one of the named subpatterns participates. An example is shown in the +Normally, patterns that use duplicate names are such that in any one match, +only one of each set of identically-named groups participates. An example is +shown in the pcre2pattern documentation.
@@ -3517,11 +3715,12 @@ Option bits for pcre_dfa_match()
The unused bits of the options argument for pcre2_dfa_match() must -be zero. The only bits that may be set are PCRE2_ANCHORED, PCRE2_ENDANCHORED, -PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART, -PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, PCRE2_PARTIAL_SOFT, PCRE2_DFA_SHORTEST, -and PCRE2_DFA_RESTART. All but the last four of these are exactly the same as -for pcre2_match(), so their description is not repeated here. +be zero. The only bits that may be set are PCRE2_ANCHORED, +PCRE2_COPY_MATCHED_SUBJECT, PCRE2_ENDANCHORED, PCRE2_NOTBOL, PCRE2_NOTEOL, +PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, +PCRE2_PARTIAL_SOFT, PCRE2_DFA_SHORTEST, and PCRE2_DFA_RESTART. All but the last +four of these are exactly the same as for pcre2_match(), so their +description is not repeated here.
PCRE2_PARTIAL_HARD PCRE2_PARTIAL_SOFT @@ -3583,9 +3782,8 @@ the three matched strings are On success, the yield of the function is a number greater than zero, which is the number of matched substrings. The offsets of the substrings are returned in the ovector, and can be extracted by number in the same way as for -pcre2_match(), but the numbers bear no relation to any capturing groups -that may exist in the pattern, because DFA matching does not support group -capture. +pcre2_match(), but the numbers bear no relation to any capture groups +that may exist in the pattern, because DFA matching does not support capturing.This return is given if pcre2_dfa_match() encounters a condition item that uses a backreference for the condition, or a test for recursion in a -specific group. These are not supported. +specific capture group. These are not supported. +Calls to the convenience functions that extract substrings by name @@ -3627,7 +3825,13 @@ a backreference.
+ PCRE2_ERROR_DFA_UINVALID_UTF ++This return is given if pcre2_dfa_match() is called for a pattern that +was compiled with PCRE2_MATCH_INVALID_UTF. This is not supported for DFA +matching.PCRE2_ERROR_DFA_WSSIZE@@ -3636,9 +3840,9 @@ This return is given if pcre2_dfa_match() runs out of space in thePCRE2_ERROR_DFA_RECURSE-When a recursive subpattern is processed, the matching function calls itself -recursively, using private memory for the ovector and workspace. This -error is given if the internal ovector is not large enough. This should be +When a recursion or subroutine call is processed, the matching function calls +itself recursively, using private memory for the ovector and workspace. +This error is given if the internal ovector is not large enough. This should be extremely rare, as a vector of size 1000 is used.PCRE2_ERROR_DFA_BADRESTART @@ -3665,9 +3869,9 @@ Cambridge, England.
REVISION
-Last updated: 07 September 2018 +Last updated: 02 September 2019
-Copyright © 1997-2018 University of Cambridge. +Copyright © 1997-2019 University of Cambridge.
Return to the PCRE2 index page. diff --git a/doc/html/pcre2build.html b/doc/html/pcre2build.html index e31b604..13d9da2 100644 --- a/doc/html/pcre2build.html +++ b/doc/html/pcre2build.html @@ -33,11 +33,12 @@ please consult the man page, in case the conversion went wrong.
@@ -375,12 +376,15 @@ environment.
-By default, on non-Windows systems, pcre2grep supports the use of -callouts with string arguments within the patterns it is matching, in order to -run external scripts. For details, see the +By default pcre2grep supports the use of callouts with string arguments +within the patterns it is matching. There are two kinds: one that generates +output using local code, and another that calls an external program or script. +If --disable-pcre2grep-callout-fork is added to the configure command, +only the first kind of callout is supported; if --disable-pcre2grep-callout is +used, all callouts are completely ignored. For more details of pcre2grep +callouts, see the pcre2grep -documentation. This support can be disabled by adding ---disable-pcre2grep-callout to the configure command. +documentation.
@@ -523,7 +527,21 @@ This cleans all coverage data including the generated coverage report. For more information about code coverage, see the gcov and lcov documentation.
-+The C99 standard defines formatting modifiers z and t for size_t and +ptrdiff_t values, respectively. By default, PCRE2 uses these modifiers in +environments other than Microsoft Visual Studio when __STDC_VERSION__ is +defined and has a value greater than or equal to 199901L (indicating C99). +However, there is at least one environment that claims to be C99 but does not +support these modifiers. If +
+ --disable-percent-zt ++is specified, no use is made of the z or t modifiers. Instead or %td or %zu, +%lu is used, with a cast for size_t values. + +
There is a special option for use by people who want to run fuzzing tests on PCRE2: @@ -547,7 +565,7 @@ arguments: if an argument starts with "=" the rest of it is a literal input string. Otherwise, it is assumed to be a file name, and the contents of the file are the test string.
-In versions of PCRE2 prior to 10.30, there were two ways of handling backtracking in the pcre2_match() function. The default was to use the @@ -559,11 +577,11 @@ was set, memory on the heap was used. From release 10.30 onwards this has changed (the stack is no longer used) and this option now does nothing except give a warning.
-pcre2api(3), pcre2-config(3).
-
Philip Hazel
@@ -572,11 +590,11 @@ University Computing Service
Cambridge, England.
-Last updated: 26 April 2018
+Last updated: 03 March 2019
-Copyright © 1997-2018 University of Cambridge.
+Copyright © 1997-2019 University of Cambridge.
Return to the PCRE2 index page. diff --git a/doc/html/pcre2callout.html b/doc/html/pcre2callout.html index 9b6ae6f..65db933 100644 --- a/doc/html/pcre2callout.html +++ b/doc/html/pcre2callout.html @@ -44,6 +44,14 @@ a match context (see pcre2_set_callout() in the documentation).
+When using the pcre2_substitute() function, an additional callout feature +is available. This does a callout after each change to the subject string and +is described in the +pcre2api +documentation; the rest of this document is concerned with callouts during +pattern matching. +
+Within a regular expression, (?C<arg>) indicates a point at which the external function is to be called. Different callout points can be identified by putting a number less than 256 after the letter C. The default value is zero. @@ -143,7 +151,7 @@ branch, automatic anchoring occurs if all branches are anchorable.
This optimization is disabled, however, if .* is in an atomic group or if there -is a backreference to the capturing group in which it appears. It is also +is a backreference to the capture group in which it appears. It is also disabled if the pattern contains (*PRUNE) or (*SKIP). However, the presence of callouts does not affect it.
@@ -346,8 +354,8 @@ callout before an assertion such as (?=ab) the length is 3. For an an alternation bar or a closing parenthesis, the length is one, unless a closing parenthesis is followed by a quantifier, in which case its length is included. (This changed in release 10.23. In earlier releases, before an opening -parenthesis the length was that of the entire subpattern, and before an -alternation bar or a closing parenthesis the length was zero.) +parenthesis the length was that of the entire group, and before an alternation +bar or a closing parenthesis the length was zero.)The pattern_position and next_item_length fields are intended to @@ -463,9 +471,9 @@ Cambridge, England.
-Last updated: 26 April 2018
+Last updated: 03 February 2019
-Copyright © 1997-2018 University of Cambridge.
+Copyright © 1997-2019 University of Cambridge.
Return to the PCRE2 index page. diff --git a/doc/html/pcre2compat.html b/doc/html/pcre2compat.html index f593204..0c72a9a 100644 --- a/doc/html/pcre2compat.html +++ b/doc/html/pcre2compat.html @@ -36,10 +36,9 @@ assertion just once). Perl allows some repeat quantifiers on other assertions, for example, \b* (but not \b{3}), but these do not seem to have any use.
-3. Capturing subpatterns that occur inside negative lookaround assertions are -counted, but their entries in the offsets vector are set only when a negative -assertion is a condition that has a matching branch (that is, the condition is -false). +3. Capture groups that occur inside negative lookaround assertions are counted, +but their entries in the offsets vector are set only when a negative assertion +is a condition that has a matching branch (that is, the condition is false).
4. The following Perl escape sequences are not supported: \F, \l, \L, \u, @@ -48,8 +47,9 @@ non-newline character, and \N{U+dd..}, matching a Unicode code point, are supported. The escapes that modify the case of following letters are implemented by Perl's general string-handling and are not part of its pattern matching engine. If any of these are encountered by PCRE2, an error is -generated by default. However, if the PCRE2_ALT_BSUX option is set, \U and \u -are interpreted as ECMAScript interprets them. +generated by default. However, if either of the PCRE2_ALT_BSUX or +PCRE2_EXTRA_ALT_BSUX options is set, \U and \u are interpreted as ECMAScript +interprets them.
5. The Perl escape sequences \p, \P, and \X are supported only if PCRE2 is @@ -94,13 +94,13 @@ to PCRE2 release 10.23, but from release 10.30 this changed, and backtracking into subroutine calls is now supported, as in Perl.
-9. If any of the backtracking control verbs are used in a subpattern that is -called as a subroutine (whether or not recursively), their effect is confined -to that subpattern; it does not extend to the surrounding pattern. This is not -always the case in Perl. In particular, if (*THEN) is present in a group that -is called as a subroutine, its action is limited to that group, even if the -group does not contain any | characters. Note that such subpatterns are -processed as anchored at the point where they are tested. +9. If any of the backtracking control verbs are used in a group that is called +as a subroutine (whether or not recursively), their effect is confined to that +group; it does not extend to the surrounding pattern. This is not always the +case in Perl. In particular, if (*THEN) is present in a group that is called as +a subroutine, its action is limited to that group, even if the group does not +contain any | characters. Note that such groups are processed as anchored +at the point where they are tested.
10. If a pattern contains more than one backtracking control verb, the first @@ -120,22 +120,21 @@ the pattern /^(a(b)?)+$/ in Perl leaves $2 unset, but in PCRE2 it is set to "b".
-13. PCRE2's handling of duplicate subpattern numbers and duplicate subpattern -names is not as general as Perl's. This is a consequence of the fact the PCRE2 -works internally just with numbers, using an external table to translate -between numbers and names. In particular, a pattern such as (?|(?<a>A)|(?<b>B), -where the two capturing parentheses have the same number but different names, -is not supported, and causes an error at compile time. If it were allowed, it -would not be possible to distinguish which parentheses matched, because both -names map to capturing subpattern number 1. To avoid this confusing situation, -an error is given at compile time. +13. PCRE2's handling of duplicate capture group numbers and names is not as +general as Perl's. This is a consequence of the fact the PCRE2 works internally +just with numbers, using an external table to translate between numbers and +names. In particular, a pattern such as (?|(?<a>A)|(?<b>B), where the two +capture groups have the same number but different names, is not supported, and +causes an error at compile time. If it were allowed, it would not be possible +to distinguish which group matched, because both names map to capture group +number 1. To avoid this confusing situation, an error is given at compile time.
14. Perl used to recognize comments in some places that PCRE2 does not, for -example, between the ( and ? at the start of a subpattern. If the /x modifier -is set, Perl allowed white space between ( and ? though the latest Perls give -an error (for a while it was just deprecated). There may still be some cases -where Perl behaves differently. +example, between the ( and ? at the start of a group. If the /x modifier is +set, Perl allowed white space between ( and ? though the latest Perls give an +error (for a while it was just deprecated). There may still be some cases where +Perl behaves differently.
15. Perl, when in warning mode, gives warnings for character classes such as
@@ -206,6 +205,11 @@ different way and is not Perl-compatible.
(l) PCRE2 recognizes some special sequences such as (*CR) or (*NO_JIT) at
the start of a pattern that set overall options that cannot be changed within
the pattern.
+
+
+(m) PCRE2 supports non-atomic positive lookaround assertions. This is an
+extension to the lookaround facilities. The default, Perl-compatible
+lookarounds are atomic.
18. The Perl /a modifier restricts /d numbers to pure ascii, and the /aa
@@ -235,9 +239,9 @@ Cambridge, England.
REVISION
-Last updated: 28 July 2018
+Last updated: 13 July 2019
-Copyright © 1997-2018 University of Cambridge.
+Copyright © 1997-2019 University of Cambridge.
Return to the PCRE2 index page. diff --git a/doc/html/pcre2demo.html b/doc/html/pcre2demo.html index 72754d3..08b2190 100644 --- a/doc/html/pcre2demo.html +++ b/doc/html/pcre2demo.html @@ -104,12 +104,11 @@ uint32_t newline; PCRE2_SIZE erroroffset; PCRE2_SIZE *ovector; +PCRE2_SIZE subject_length; -size_t subject_length; pcre2_match_data *match_data; - /************************************************************************** * First, sort out the command line. There is only one possible option at * * the moment, "-g" to request repeated matching to find all occurrences, * @@ -138,12 +137,14 @@ if (argc - i != 2) return 1; } -/* As pattern and subject are char arguments, they can be straightforwardly -cast to PCRE2_SPTR as we are working in 8-bit code units. */ +/* Pattern and subject are char arguments, so they can be straightforwardly +cast to PCRE2_SPTR because we are working in 8-bit code units. The subject +length is cast to PCRE2_SIZE for completeness, though PCRE2_SIZE is in fact +defined to be size_t. */ pattern = (PCRE2_SPTR)argv[i]; subject = (PCRE2_SPTR)argv[i+1]; -subject_length = strlen((char *)subject); +subject_length = (PCRE2_SIZE)strlen((char *)subject); /************************************************************************* @@ -172,17 +173,22 @@ if (re == NULL) /************************************************************************* -* If the compilation succeeded, we call PCRE again, in order to do a * +* If the compilation succeeded, we call PCRE2 again, in order to do a * * pattern match against the subject string. This does just ONE match. If * * further matching is needed, it will be done below. Before running the * -* match we must set up a match_data block for holding the result. * +* match we must set up a match_data block for holding the result. Using * +* pcre2_match_data_create_from_pattern() ensures that the block is * +* exactly the right size for the number of capturing parentheses in the * +* pattern. If you need to know the actual size of a match_data block as * +* a number of bytes, you can find it like this: * +* * +* PCRE2_SIZE match_data_size = pcre2_get_match_data_size(match_data); * *************************************************************************/ -/* Using this function ensures that the block is exactly the right size for -the number of capturing parentheses in the pattern. */ - match_data = pcre2_match_data_create_from_pattern(re, NULL); +/* Now run the match. */ + rc = pcre2_match( re, /* the compiled pattern */ subject, /* the subject string */ @@ -205,7 +211,7 @@ if (rc < 0) default: printf("Matching error %d\n", rc); break; } pcre2_match_data_free(match_data); /* Release memory used for the match */ - pcre2_code_free(re); /* data and the compiled pattern. */ + pcre2_code_free(re); /* data and the compiled pattern. */ return 1; } @@ -249,7 +255,7 @@ application you might want to do things other than print them. */ for (i = 0; i < rc; i++) { PCRE2_SPTR substring_start = subject + ovector[2*i]; - size_t substring_length = ovector[2*i+1] - ovector[2*i]; + PCRE2_SIZE substring_length = ovector[2*i+1] - ovector[2*i]; printf("%2d: %.*s\n", i, (int)substring_length, (char *)substring_start); } diff --git a/doc/html/pcre2grep.html b/doc/html/pcre2grep.html index 272b87d..f5b72f3 100644 --- a/doc/html/pcre2grep.html +++ b/doc/html/pcre2grep.html @@ -685,20 +685,32 @@ otherwise empty line. This option is mutually exclusive with --output,
-onumber, --only-matching=number
Show only the part of the line that matched the capturing parentheses of the
-given number. Up to 32 capturing parentheses are supported, and -o0 is
-equivalent to -o without a number. Because these options can be given
-without an argument (see above), if an argument is present, it must be given in
-the same shell item, for example, -o3 or --only-matching=2. The comments given
-for the non-argument case above also apply to this option. If the specified
-capturing parentheses do not exist in the pattern, or were not set in the
-match, nothing is output unless the file name or line number are being output.
+given number. Up to 50 capturing parentheses are supported by default. This
+limit can be changed via the --om-capture option. A pattern may contain
+any number of capturing parentheses, but only those whose number is within the
+limit can be accessed by -o. An error occurs if the number specified by
+-o is greater than the limit.
+
+
+-o0 is the same as -o without a number. Because these options can be
+given without an argument (see above), if an argument is present, it must be
+given in the same shell item, for example, -o3 or --only-matching=2. The
+comments given for the non-argument case above also apply to this option. If
+the specified capturing parentheses do not exist in the pattern, or were not
+set in the match, nothing is output unless the file name or line number are
+being output.
If this option is given multiple times, multiple substrings are output for each
match, in the order the options are given, and all on one line. For example,
-o3 -o1 -o3 causes the substrings matched by capturing parentheses 3 and 1 and
then 3 again to be output. By default, there is no separator (but see the next
-option).
+but one option).
+
+--om-capture=number +Set the number of capturing parentheses that can be accessed by -o. The +default is 50.
--om-separator=text @@ -741,13 +753,22 @@ ignored when used with -L (list files without matches), because the grand total would always be zero.
--u, --utf-8 +-u, --utf Operate in UTF-8 mode. This option is available only if PCRE2 has been compiled with UTF-8 support. All patterns (including those for any --exclude and --include options) and all subject lines that are scanned must be valid strings of UTF-8 characters.
+-U, --utf-allow-invalid +As --utf, but in addition subject lines may contain invalid UTF-8 code +unit sequences. These can never form part of any pattern match. This facility +allows valid UTF-8 strings to be sought in executable or other binary files. +For more details about matching in non-valid UTF-8 strings, see the +pcre2unicode(3) +documentation. +
+-V, --version Write the version numbers of pcre2grep and the PCRE2 library to the standard output and then exit. Anything else on the command line is @@ -806,9 +827,9 @@ as in the GNU grep program. Any long option of the form --file-offsets, --heap-limit, --include-dir, --line-offsets, --locale, --match-limit, -M, --multiline, -N, --newline, --om-separator, ---output, -u, and --utf-8 options are specific to -pcre2grep, as is the use of the --only-matching option with a -capturing parentheses number. +--output, -u, --utf, -U, and --utf-allow-invalid +options are specific to pcre2grep, as is the use of the +--only-matching option with a capturing parentheses number.
Although most of the common options work the same way, a few are different in @@ -853,10 +874,12 @@ character. Otherwise pcre2grep will assume that it has no data.
pcre2grep has, by default, support for calling external programs or scripts or echoing specific strings during matching by making use of PCRE2's -callout facility. However, this support can be disabled when pcre2grep is -built. You can find out whether your binary has support for callouts by running -it with the --help option. If the support is not enabled, all callouts in -patterns are ignored by pcre2grep. +callout facility. However, this support can be completely or partially disabled +when pcre2grep is built. You can find out whether your binary has support +for callouts by running it with the --help option. If callout support is +completely disabled, all callouts in patterns are ignored by pcre2grep. +If the facility is partially disabled, calling external programs is not +supported, and callouts that request it are ignored.
A callout in a PCRE2 pattern is of the form (?C<arg>) where the argument is
@@ -869,6 +892,12 @@ only callouts with string arguments are useful.
Calling external programs or scripts
+This facility can be independently disabled when pcre2grep is built. It +is supported for Windows, where a call to _spawnvp() is used, for VMS, +where lib$spawn() is used, and for any other Unix-like environment where +fork() and execv() are available. +
+
If the callout string does not start with a pipe (vertical bar) character, it
is parsed into a list of substrings separated by pipe characters. The first
substring must be an executable name, with the following substrings specifying
@@ -897,7 +926,7 @@ a single dollar and $| is replaced by a pipe character. Here is an example:
Arg1: [1] [234] [4] Arg2: |1| ()
12345
-The parameters for the execv() system call that is used to run the
+The parameters for the system call that is used to run the
program or script are zero-terminated strings. This means that binary zero
characters in the callout argument will cause premature termination of their
substrings, and therefore should not be present. Any syntax errors in the
@@ -910,14 +939,15 @@ matcher backtracks in the normal way.
Echoing a specific string
-If the callout string starts with a pipe (vertical bar) character, the rest of -the string is written to the output, having been passed through the same escape -processing as text from the --output option. This provides a simple echoing -facility that avoids calling an external program or script. No terminator is -added to the string, so if you want a newline, you must include it explicitly. -Matching continues normally after the string is output. If you want to see only -the callout output but not any output from an actual match, you should end the -relevant pattern with (*FAIL). +This facility is always available, provided that callouts were not completely +disabled when pcre2grep was built. If the callout string starts with a +pipe (vertical bar) character, the rest of the string is written to the output, +having been passed through the same escape processing as text from the --output +option. This provides a simple echoing facility that avoids calling an external +program or script. No terminator is added to the string, so if you want a +newline, you must include it explicitly. Matching continues normally after the +string is output. If you want to see only the callout output but not any output +from an actual match, you should end the relevant pattern with (*FAIL).
@@ -962,9 +992,9 @@ Cambridge, England.
-Last updated: 24 February 2018
+Last updated: 15 June 2019
-Copyright © 1997-2018 University of Cambridge.
+Copyright © 1997-2019 University of Cambridge.
Return to the PCRE2 index page. diff --git a/doc/html/pcre2jit.html b/doc/html/pcre2jit.html index fa007e0..47b588e 100644 --- a/doc/html/pcre2jit.html +++ b/doc/html/pcre2jit.html @@ -16,16 +16,17 @@ please consult the man page, in case the conversion went wrong.
@@ -144,12 +145,39 @@ support is not available, or the pattern was not processed by pcre2_jit_compile(), or the JIT compiler was not able to handle the pattern.
-+When a pattern is compiled with the PCRE2_UTF option, subject strings are +normally expected to be a valid sequence of UTF code units. By default, this is +checked at the start of matching and an error is generated if invalid UTF is +detected. The PCRE2_NO_UTF_CHECK option can be passed to pcre2_match() to +skip the check (for improved performance) if you are sure that a subject string +is valid. If this option is used with an invalid string, the result is +undefined. +
++However, a way of running matches on strings that may contain invalid UTF +sequences is available. Calling pcre2_compile() with the +PCRE2_MATCH_INVALID_UTF option has two effects: it tells the interpreter in +pcre2_match() to support invalid UTF, and, if pcre2_jit_compile() +is called, the compiled JIT code also supports invalid UTF. Details of how this +support works, in both the JIT and the interpretive cases, is given in the +pcre2unicode +documentation. +
++There is also an obsolete option for pcre2_jit_compile() called +PCRE2_JIT_INVALID_UTF, which currently exists only for backward compatibility. +It is superseded by the pcre2_compile() option PCRE2_MATCH_INVALID_UTF +and should no longer be used. It may be removed in future. +
+The pcre2_match() options that are supported for JIT matching are -PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART, -PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, and PCRE2_PARTIAL_SOFT. The -PCRE2_ANCHORED option is not supported at match time. +PCRE2_COPY_MATCHED_SUBJECT, PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY, +PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, and +PCRE2_PARTIAL_SOFT. The PCRE2_ANCHORED and PCRE2_ENDANCHORED options are not +supported at match time.
If the PCRE2_NO_JIT option is passed to pcre2_match() it disables the @@ -160,7 +188,7 @@ The only unsupported pattern items are \C (match a single data unit) when running in a UTF mode, and a callout immediately before an assertion condition in a conditional group.
-When a pattern is matched using JIT matching, the return values are the same as those given by the interpretive pcre2_match() code, with the addition @@ -176,7 +204,7 @@ circumstance when JIT is not used, but the details of exactly what is counted are not the same. The PCRE2_ERROR_DEPTHLIMIT error code is never returned when JIT matching is used.
-When the compiled JIT code runs, it needs a block of memory to use as a stack. By default, it uses 32KiB on the machine stack. However, some large or @@ -269,7 +297,7 @@ non-default JIT stacks might operate: All the functions described in this section do nothing if JIT is not available.
-
(1) Why do we need JIT stacks?
@@ -348,7 +376,7 @@ stack handling?
No, thanks to Windows. If POSIX threads were used everywhere, we could throw
out this complicated API.
void pcre2_jit_free_unused_memory(pcre2_general_context *gcontext);
@@ -360,7 +388,7 @@ all possible memory. You can cause this to happen by calling pcre2_jit_free_unused_memory(). Its argument is a general context, for custom memory management, or NULL for standard memory management. -This is a single-threaded example that specifies a JIT stack without using a callback. A real program should include error checking after all the function @@ -389,7 +417,7 @@ calls.
-Because the API described above falls back to interpreted matching when JIT is not available, it is convenient for programs that are written for general use @@ -402,10 +430,13 @@ processed by pcre2_jit_compile()).
The fast path function is called pcre2_jit_match(), and it takes exactly -the same arguments as pcre2_match(). The return values are also the same, -plus PCRE2_ERROR_JIT_BADOPTION if a matching mode (partial or complete) is -requested that was not compiled. Unsupported option bits (for example, -PCRE2_ANCHORED) are ignored, as is the PCRE2_NO_JIT option. +the same arguments as pcre2_match(). However, the subject string must be +specified with a length; PCRE2_ZERO_TERMINATED is not supported. Unsupported +option bits (for example, PCRE2_ANCHORED, PCRE2_ENDANCHORED and +PCRE2_COPY_MATCHED_SUBJECT) are ignored, as is the PCRE2_NO_JIT option. The +return values are also the same as for pcre2_match(), plus +PCRE2_ERROR_JIT_BADOPTION if a matching mode (partial or complete) is requested +that was not compiled.
When you call pcre2_match(), as well as testing for invalid options, a @@ -419,11 +450,11 @@ invalid data is passed, the result is undefined. Bypassing the sanity checks and the pcre2_match() wrapping can give speedups of more than 10%.
-pcre2api(3)
-
Philip Hazel (FAQ by Zoltan Herczeg)
@@ -432,11 +463,11 @@ University Computing Service
Cambridge, England.
-Last updated: 28 June 2018
+Last updated: 23 May 2019
-Copyright © 1997-2018 University of Cambridge.
+Copyright © 1997-2019 University of Cambridge.
Return to the PCRE2 index page. diff --git a/doc/html/pcre2limits.html b/doc/html/pcre2limits.html index d90cdc3..c8bc01b 100644 --- a/doc/html/pcre2limits.html +++ b/doc/html/pcre2limits.html @@ -50,17 +50,17 @@ All values in repeating quantifiers must be less than 65536. The maximum length of a lookbehind assertion is 65535 characters.
-There is no limit to the number of parenthesized subpatterns, but there can be -no more than 65535 capturing subpatterns. There is, however, a limit to the -depth of nesting of parenthesized subpatterns of all kinds. This is imposed in -order to limit the amount of system stack used at compile time. The default -limit can be specified when PCRE2 is built; if not, the default is set to 250. -An application can change this limit by calling pcre2_set_parens_nest_limit() -to set the limit in a compile context. +There is no limit to the number of parenthesized groups, but there can be no +more than 65535 capture groups, and there is a limit to the depth of nesting of +parenthesized subpatterns of all kinds. This is imposed in order to limit the +amount of system stack used at compile time. The default limit can be specified +when PCRE2 is built; if not, the default is set to 250. An application can +change this limit by calling pcre2_set_parens_nest_limit() to set the limit in +a compile context.
-The maximum length of name for a named subpattern is 32 code units, and the -maximum number of named subpatterns is 10000. +The maximum length of name for a named capture group is 32 code units, and the +maximum number of such groups is 10000.
The maximum length of a name in a (*MARK), (*PRUNE), (*SKIP), or (*THEN) verb
@@ -86,9 +86,9 @@ Cambridge, England.
REVISION
-Last updated: 30 March 2017
+Last updated: 02 February 2019
-Copyright © 1997-2017 University of Cambridge.
+Copyright © 1997-2019 University of Cambridge.
Return to the PCRE2 index page. diff --git a/doc/html/pcre2matching.html b/doc/html/pcre2matching.html index 602f3b2..4b71c8f 100644 --- a/doc/html/pcre2matching.html +++ b/doc/html/pcre2matching.html @@ -134,7 +134,8 @@ do want multiple matches in such cases, either use an ungreedy repeat
There are a number of features of PCRE2 regular expressions that are not -supported by the alternative matching algorithm. They are as follows: +supported or behave differently in the alternative matching function. Those +that are not supported cause an error if encountered.
1. Because the algorithm finds all possible matches, the greedy or ungreedy @@ -159,31 +160,38 @@ do this. This means that no captured substrings are available.
3. Because no substrings are captured, backreferences within the pattern are -not supported, and cause errors if encountered. +not supported.
4. For the same reason, conditional expressions that use a backreference as the condition or test for a specific group recursion are not supported.
-5. Because many paths through the tree may be active, the \K escape sequence, +5. Again for the same reason, script runs are not supported. +
++6. Because many paths through the tree may be active, the \K escape sequence, which resets the start of the match when encountered (but may be on some paths -and not on others), is not supported. It causes an error if encountered. +and not on others), is not supported.
-6. Callouts are supported, but the value of the capture_top field is +7. Callouts are supported, but the value of the capture_top field is always 1, and the value of the capture_last field is always 0.
-7. The \C escape sequence, which (in the standard algorithm) always matches a +8. The \C escape sequence, which (in the standard algorithm) always matches a single code unit, even in a UTF mode, is not supported in these modes, because the alternative algorithm moves through the subject string one character (not code unit) at a time, for all active paths through the tree.
-8. Except for (*FAIL), the backtracking control verbs such as (*PRUNE) are not +9. Except for (*FAIL), the backtracking control verbs such as (*PRUNE) are not supported. (*FAIL) is supported, and behaves like a failing negative assertion.
++10. The PCRE2_MATCH_INVALID_UTF option for pcre2_compile() is not +supported by pcre2_dfa_match(). +
Using the alternative matching algorithm provides the following advantages: @@ -215,7 +223,8 @@ because it has to search for all possible matches, but is also because it is less susceptible to optimization.
-2. Capturing parentheses and backreferences are not supported. +2. Capturing parentheses, backreferences, script runs, and matching within +invalid UTF string are not supported.
3. Although atomic groups are supported, their use does not provide the @@ -232,9 +241,9 @@ Cambridge, England.
-Last updated: 29 September 2014
+Last updated: 23 May 2019
-Copyright © 1997-2014 University of Cambridge.
+Copyright © 1997-2019 University of Cambridge.
Return to the PCRE2 index page.
diff --git a/doc/html/pcre2partial.html b/doc/html/pcre2partial.html
index 4e156b8..438c52c 100644
--- a/doc/html/pcre2partial.html
+++ b/doc/html/pcre2partial.html
@@ -14,78 +14,123 @@ please consult the man page, in case the conversion went wrong.
-In normal use of PCRE2, if the subject string that is passed to a matching -function matches as far as it goes, but is too short to match the entire -pattern, PCRE2_ERROR_NOMATCH is returned. There are circumstances where it -might be helpful to distinguish this case from other cases in which there is no -match. +In normal use of PCRE2, if there is a match up to the end of a subject string, +but more characters are needed to match the entire pattern, PCRE2_ERROR_NOMATCH +is returned, just like any other failing match. There are circumstances where +it might be helpful to distinguish this "partial match" case.
-Consider, for example, an application where a human is required to type in data -for a field with specific formatting requirements. An example might be a date -in the form ddmmmyy, defined by this pattern: -
- ^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$ --If the application sees the user's keystrokes one by one, and can check that -what has been typed so far is potentially valid, it is able to raise an error -as soon as a mistake is made, by beeping and not reflecting the character that -has been typed, for example. This immediate feedback is likely to be a better -user interface than a check that is delayed until the entire string has been -entered. Partial matching can also be useful when the subject string is very -long and is not all available at once. +One example is an application where the subject string is very long, and not +all available at once. The requirement here is to be able to do the matching +segment by segment, but special action is needed when a matched substring spans +the boundary between two segments.
-PCRE2 supports partial matching by means of the PCRE2_PARTIAL_SOFT and -PCRE2_PARTIAL_HARD options, which can be set when calling a matching function. -The difference between the two options is whether or not a partial match is -preferred to an alternative complete match, though the details differ between -the two types of matching function. If both options are set, PCRE2_PARTIAL_HARD -takes precedence. +Another example is checking a user input string as it is typed, to ensure that +it conforms to a required format. Invalid characters can be immediately +diagnosed and rejected, giving instant feedback.
-If you want to use partial matching with just-in-time optimized code, you must -call pcre2_jit_compile() with one or both of these options: +Partial matching is a PCRE2-specific feature; it is not Perl-compatible. It is +requested by setting one of the PCRE2_PARTIAL_HARD or PCRE2_PARTIAL_SOFT +options when calling a matching function. The difference between the two +options is whether or not a partial match is preferred to an alternative +complete match, though the details differ between the two types of matching +function. If both options are set, PCRE2_PARTIAL_HARD takes precedence. +
++If you want to use partial matching with just-in-time optimized code, as well +as setting a partial match option for the matching function, you must also call +pcre2_jit_compile() with one or both of these options:
- PCRE2_JIT_PARTIAL_SOFT PCRE2_JIT_PARTIAL_HARD + PCRE2_JIT_PARTIAL_SOFTPCRE2_JIT_COMPLETE should also be set if you are going to run non-partial -matches on the same pattern. If the appropriate JIT mode has not been compiled, -interpretive matching code is used. +matches on the same pattern. Separate code is compiled for each mode. If the +appropriate JIT mode has not been compiled, interpretive matching code is used.
Setting a partial matching option disables two of PCRE2's standard -optimizations. PCRE2 remembers the last literal code unit in a pattern, and -abandons matching immediately if it is not present in the subject string. This -optimization cannot be used for a subject string that might match only -partially. PCRE2 also knows the minimum length of a matching string, and does +optimization hints. PCRE2 remembers the last literal code unit in a pattern, +and abandons matching immediately if it is not present in the subject string. +This optimization cannot be used for a subject string that might match only +partially. PCRE2 also remembers a minimum length of a matching string, and does not bother to run the matching function on shorter strings. This optimization is also disabled for partial matching.
-+A possible partial match occurs during matching when the end of the subject +string is reached successfully, but either more characters are needed to +complete the match, or the addition of more characters might change what is +matched. +
-A partial match occurs during a call to pcre2_match() when the end of the -subject string is reached successfully, but matching cannot continue because -more characters are needed. However, at least one character in the subject must -have been inspected. This character need not form part of the final matched -string; lookbehind assertions and the \K escape sequence provide ways of -inspecting characters before the start of a matched string. The requirement for -inspecting at least one character exists because an empty string can always be -matched; without such a restriction there would always be a partial match of an -empty string at the end of the subject. +Example 1: if the pattern is /abc/ and the subject is "ab", more characters are +definitely needed to complete a match. In this case both hard and soft matching +options yield a partial match. +
++Example 2: if the pattern is /ab+/ and the subject is "ab", a complete match +can be found, but the addition of more characters might change what is +matched. In this case, only PCRE2_PARTIAL_HARD returns a partial match; +PCRE2_PARTIAL_SOFT returns the complete match. +
++On reaching the end of the subject, when PCRE2_PARTIAL_HARD is set, if the next +pattern item is \z, \Z, \b, \B, or $ there is always a partial match. +Otherwise, for both options, the next pattern item must be one that inspects a +character, and at least one of the following must be true: +
++(1) At least one character has already been inspected. An inspected character +need not form part of the final matched string; lookbehind assertions and the +\K escape sequence provide ways of inspecting characters before the start of a +matched string. +
++(2) The pattern contains one or more lookbehind assertions. This condition +exists in case there is a lookbehind that inspects characters before the start +of the match. +
++(3) There is a special case when the whole pattern can match an empty string. +When the starting point is at the end of the subject, the empty string match is +a possibility, and if PCRE2_PARTIAL_SOFT is set and neither of the above +conditions is true, it is returned. However, because adding more characters +might result in a non-empty match, PCRE2_PARTIAL_HARD returns a partial match, +which in this case means "there is going to be a match at this point, but until +some more characters are added, we do not know if it will be an empty string or +something longer". +
++When a partial matching option is set, the result of calling +pcre2_match() can be one of the following: +
++A successful match +A complete match has been found, starting and ending within this subject. +
++PCRE2_ERROR_NOMATCH +No match can start anywhere in this subject. +
++PCRE2_ERROR_PARTIAL +Adding more characters may result in a complete match that uses one or more +characters from the end of this subject.
When a partial match is returned, the first two elements in the ovector point @@ -103,54 +148,42 @@ these characters are needed for a subsequent re-match with additional characters.
-What happens when a partial match is identified depends on which of the two -partial matching options are set. -
--If PCRE2_PARTIAL_SOFT is set when pcre2_match() identifies a partial -match, the partial match is remembered, but matching continues as normal, and -other alternatives in the pattern are tried. If no complete match can be found, -PCRE2_ERROR_PARTIAL is returned instead of PCRE2_ERROR_NOMATCH. -
--This option is "soft" because it prefers a complete match over a partial match. -All the various matching items in a pattern behave as if the subject string is -potentially complete. For example, \z, \Z, and $ match at the end of the -subject, as normal, and for \b and \B the end of the subject is treated as a -non-alphanumeric. -
-If there is more than one partial match, the first one that was found provides the data that is returned. Consider this pattern:
/123\w+X|dogY/-If this is matched against the subject string "abc123dog", both -alternatives fail to match, but the end of the subject is reached during -matching, so PCRE2_ERROR_PARTIAL is returned. The offsets are set to 3 and 9, -identifying "123dog" as the first partial match that was found. (In this -example, there are two partial matches, because "dog" on its own partially -matches the second alternative.) +If this is matched against the subject string "abc123dog", both alternatives +fail to match, but the end of the subject is reached during matching, so +PCRE2_ERROR_PARTIAL is returned. The offsets are set to 3 and 9, identifying +"123dog" as the first partial match. (In this example, there are two partial +matches, because "dog" on its own partially matches the second alternative.)
-If PCRE2_PARTIAL_HARD is set for pcre2_match(), PCRE2_ERROR_PARTIAL is -returned as soon as a partial match is found, without continuing to search for -possible complete matches. This option is "hard" because it prefers an earlier -partial match over a later complete match. For this reason, the assumption is -made that the end of the supplied subject string may not be the true end of the -available data, and so, if \z, \Z, \b, \B, or $ are encountered at the end -of the subject, the result is PCRE2_ERROR_PARTIAL, provided that at least one -character in the subject has been inspected. +What happens when a partial match is identified depends on which of the two +partial matching options is set. +
++If PCRE2_PARTIAL_HARD is set, PCRE2_ERROR_PARTIAL is returned as soon as a +partial match is found, without continuing to search for possible complete +matches. This option is "hard" because it prefers an earlier partial match over +a later complete match. For this reason, the assumption is made that the end of +the supplied subject string is not the true end of the available data, which is +why \z, \Z, \b, \B, and $ always give a partial match. +
++If PCRE2_PARTIAL_SOFT is set, the partial match is remembered, but matching +continues as normal, and other alternatives in the pattern are tried. If no +complete match can be found, PCRE2_ERROR_PARTIAL is returned instead of +PCRE2_ERROR_NOMATCH. This option is "soft" because it prefers a complete match +over a partial match. All the various matching items in a pattern behave as if +the subject string is potentially complete; \z, \Z, and $ match at the end of +the subject, as normal, and for \b and \B the end of the subject is treated +as a non-alphanumeric.
-The difference between the two partial matching options can be illustrated by a pattern such as: @@ -175,245 +208,167 @@ to follow this explanation by thinking of the two patterns like this: The second pattern will never match "dogsbody", because it will always find the shorter match first.
--The DFA functions move along the subject string character by character, without -backtracking, searching for all possible matches simultaneously. If the end of -the subject is reached before the end of the pattern, there is the possibility -of a partial match, again provided that at least one character has been -inspected. -
--When PCRE2_PARTIAL_SOFT is set, PCRE2_ERROR_PARTIAL is returned only if there -have been no complete matches. Otherwise, the complete matches are returned. -However, if PCRE2_PARTIAL_HARD is set, a partial match takes precedence over -any complete matches. The portion of the string that was matched when the -longest partial match was found is set as the first matching string. -
--Because the DFA functions always search for all possible matches, and there is -no difference between greedy and ungreedy repetition, their behaviour is -different from the standard functions when PCRE2_PARTIAL_HARD is set. Consider -the string "dog" matched against the ungreedy pattern shown above: -
- /dog(sbody)??/ --Whereas the standard function stops as soon as it finds the complete match for -"dog", the DFA function also finds the partial match for "dogsbody", and so -returns that when PCRE2_PARTIAL_HARD is set. - -
-If a pattern ends with one of sequences \b or \B, which test for word -boundaries, partial matching with PCRE2_PARTIAL_SOFT can give counter-intuitive -results. Consider this pattern: -
- /\bcat\b/ --This matches "cat", provided there is a word boundary at either end. If the -subject string is "the cat", the comparison of the final "t" with a following -character cannot take place, so a partial match is found. However, normal -matching carries on, and \b matches at the end of the subject when the last -character is a letter, so a complete match is found. The result, therefore, is -not PCRE2_ERROR_PARTIAL. Using PCRE2_PARTIAL_HARD in this case does yield -PCRE2_ERROR_PARTIAL, because then the partial match takes precedence. - -
-If the partial_soft (or ps) modifier is present on a -pcre2test data line, the PCRE2_PARTIAL_SOFT option is used for the match. -Here is a run of pcre2test that uses the date example quoted above: +The pcre2test data modifiers partial_hard (or ph) and +partial_soft (or ps) set PCRE2_PARTIAL_HARD and PCRE2_PARTIAL_SOFT, +respectively, when calling pcre2_match(). Here is a run of +pcre2test using a pattern that matches the whole subject in the form of a +date:
re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
- data> 25jun04\=ps
- 0: 25jun04
- 1: jun
- data> 25dec3\=ps
+ data> 25dec3\=ph
Partial match: 23dec3
- data> 3ju\=ps
+ data> 3ju\=ph
Partial match: 3ju
- data> 3juj\=ps
- No match
- data> j\=ps
+ data> 3juj\=ph
No match
-The first data string is matched completely, so pcre2test shows the
-matched substrings. The remaining four strings do not match the complete
-pattern, but the first two are partial matches. Similar output is obtained
-if DFA matching is used.
-
--If the partial_hard (or ph) modifier is present on a -pcre2test data line, the PCRE2_PARTIAL_HARD option is set for the match. -
--When a partial match has been found using a DFA matching function, it is -possible to continue the match by providing additional subject data and calling -the function again with the same compiled regular expression, this time setting -the PCRE2_DFA_RESTART option. You must pass the same working space as before, -because this is where details of the previous partial match are stored. Here is -an example using pcre2test: +This example gives the same results for both hard and soft partial matching +options. Here is an example where there is a difference:
re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
- data> 23ja\=dfa,ps
- Partial match: 23ja
- data> n05\=dfa,dfa_restart
- 0: n05
+ data> 25jun04\=ps
+ 0: 25jun04
+ 1: jun
+ data> 25jun04\=ph
+ Partial match: 25jun04
-The first call has "23ja" as the subject, and requests partial matching; the
-second call has "n05" as the subject for the continued (restarted) match.
-Notice that when the match is complete, only the last part is shown; PCRE2 does
-not retain the previously partially-matched string. It is up to the calling
-program to do that if it needs to.
-
--That means that, for an unanchored pattern, if a continued match fails, it is -not possible to try again at a new starting point. All this facility is capable -of doing is continuing with the previous match attempt. In the previous -example, if the second set of data is "ug23" the result is no match, even -though there would be a match for "aug23" if the entire string were given at -once. Depending on the application, this may or may not be what you want. -The only way to allow for starting again at the next character is to retain the -matched part of the subject and try a new complete match. +With PCRE2_PARTIAL_SOFT, the subject is matched completely. For +PCRE2_PARTIAL_HARD, however, the subject is assumed not to be complete, so +there is only a partial match.
+-You can set the PCRE2_PARTIAL_SOFT or PCRE2_PARTIAL_HARD options with -PCRE2_DFA_RESTART to continue partial matching over multiple segments. This -facility can be used to pass very long subject strings to the DFA matching -functions. +PCRE was not originally designed with multi-segment matching in mind. However, +over time, features (including partial matching) that make multi-segment +matching possible have been added. A very long string can be searched segment +by segment by calling pcre2_match() repeatedly, with the aim of achieving +the same results that would happen if the entire string was available for +searching all the time. Normally, the strings that are being sought are much +shorter than each individual segment, and are in the middle of very long +strings, so the pattern is normally not anchored.
--Unlike the DFA function, it is not possible to restart the previous match with -a new segment of data when using pcre2_match(). Instead, new data must be -added to the previous subject string, and the entire match re-run, starting -from the point where the partial match occurred. Earlier data can be discarded. +Special logic must be implemented to handle a matched substring that spans a +segment boundary. PCRE2_PARTIAL_HARD should be used, because it returns a +partial match at the end of a segment whenever there is the possibility of +changing the match by adding more characters. The PCRE2_NOTBOL option should +also be set for all but the first segment.
-It is best to use PCRE2_PARTIAL_HARD in this situation, because it does not -treat the end of a segment as the end of the subject when matching \z, \Z, -\b, \B, and $. Consider an unanchored pattern that matches dates: +When a partial match occurs, the next segment must be added to the current +subject and the match re-run, using the startoffset argument of +pcre2_match() to begin at the point where the partial match started. +For example:
re> /\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d/
- data> The date is 23ja\=ph
+ data> ...the date is 23ja\=ph
Partial match: 23ja
+ data> ...the date is 23jan19 and on that day...\=offset=15
+ 0: 23jan19
+ 1: jan
-At this stage, an application could discard the text preceding "23ja", add on
-text from the next segment, and call the matching function again. Unlike the
-DFA matching function, the entire matching string must always be available,
-and the complete matching process occurs for each call, so more memory and more
-processing time is needed.
-
--Certain types of pattern may give problems with multi-segment matching, -whichever matching function is used. +Note the use of the offset modifier to start the new match where the +partial match was found. In this example, the next segment was added to the one +in which the partial match was found. This is the most straightforward +approach, typically using a memory buffer that is twice the size of each +segment. After a partial match, the first half of the buffer is discarded, the +second half is moved to the start of the buffer, and a new segment is added +before repeating the match as in the example above. After a no match, the +entire buffer can be discarded. +
++If there are memory constraints, you may want to discard text that precedes a +partial match before adding the next segment. Unfortunately, this is not at +present straightforward. In cases such as the above, where the pattern does not +contain any lookbehinds, it is sufficient to retain only the partially matched +substring. However, if the pattern contains a lookbehind assertion, characters +that precede the start of the partial match may have been inspected during the +matching process. When pcre2test displays a partial match, it indicates +these characters with '<' if the allusedtext modifier is set: +
+ re> "(?<=123)abc" + data> xx123ab\=ph,allusedtext + Partial match: 123ab + <<< ++However, the \fPallusedtext\fP modifier is not available for JIT matching, +because JIT matching does not record the first (or last) consulted characters. +For this reason, this information is not available via the API. It is therefore +not possible in general to obtain the exact number of characters that must be +retained in order to get the right match result. If you cannot retain the +entire segment, you must find some heuristic way of choosing.
-1. If the pattern contains a test for the beginning of a line, you need to pass -the PCRE2_NOTBOL option when the subject string for any call does start at the -beginning of a line. There is also a PCRE2_NOTEOL option, but in practice when -doing multi-segment matching you should be using PCRE2_PARTIAL_HARD, which -includes the effect of PCRE2_NOTEOL. +If you know the approximate length of the matching substrings, you can use that +to decide how much text to retain. The only lookbehind information that is +currently available via the API is the length of the longest individual +lookbehind in a pattern, but this can be misleading if there are nested +lookbehinds. The value returned by calling pcre2_pattern_info() with the +PCRE2_INFO_MAXLOOKBEHIND option is the maximum number of characters (not code +units) that any individual lookbehind moves back when it is processed. A +pattern such as "(?<=(?<!b)a)" has a maximum lookbehind value of one, but +inspects two characters before its starting point.
-2. If a pattern contains a lookbehind assertion, characters that precede the -start of the partial match may have been inspected during the matching process. -When using pcre2_match(), sufficient characters must be retained for the -next match attempt. You can ensure that enough characters are retained by doing -the following: +In a non-UTF or a 32-bit case, moving back is just a subtraction, but in +UTF-8 or UTF-16 you have to count characters while moving back through the code +units.
+-Before doing any matching, find the length of the longest lookbehind in the -pattern by calling pcre2_pattern_info() with the PCRE2_INFO_MAXLOOKBEHIND -option. Note that the resulting count is in characters, not code units. After a -partial match, moving back from the ovector[0] offset in the subject by the -number of characters given for the maximum lookbehind gets you to the earliest -character that must be retained. In a non-UTF or a 32-bit situation, moving -back is just a subtraction, but in UTF-8 or UTF-16 you have to count characters -while moving back through the code units. +The DFA function moves along the subject string character by character, without +backtracking, searching for all possible matches simultaneously. If the end of +the subject is reached before the end of the pattern, there is the possibility +of a partial match.
-Characters before the point you have now reached can be discarded, and after -the next segment has been added to what is retained, you should run the next -match with the startoffset argument set so that the match begins at the -same point as before. +When PCRE2_PARTIAL_SOFT is set, PCRE2_ERROR_PARTIAL is returned only if there +have been no complete matches. Otherwise, the complete matches are returned. +If PCRE2_PARTIAL_HARD is set, a partial match takes precedence over any +complete matches. The portion of the string that was matched when the longest +partial match was found is set as the first matching string.
-For example, if the pattern "(?<=123)abc" is partially matched against the -string "xx123ab", the ovector offsets are 5 and 7 ("ab"). The maximum -lookbehind count is 3, so all characters before offset 2 can be discarded. The -value of startoffset for the next match should be 3. When pcre2test -displays a partial match, it indicates the lookbehind characters with '<' -characters: +Because the DFA function always searches for all possible matches, and there is +no difference between greedy and ungreedy repetition, its behaviour is +different from the pcre2_match(). Consider the string "dog" matched +against this ungreedy pattern:
- re> "(?<=123)abc" - data> xx123ab\=ph - Partial match: 123ab - <<< -+ /dog(sbody)??/ + +Whereas the standard function stops as soon as it finds the complete match for +"dog", the DFA function also finds the partial match for "dogsbody", and so +returns that when PCRE2_PARTIAL_HARD is set. +
-3. Because a partial match must always contain at least one character, what -might be considered a partial match of an empty string actually gives a "no -match" result. For example: -
- re> /c(?<=abc)x/ - data> ab\=ps - No match --If the next segment begins "cx", a match should be found, but this will only -happen if characters from the previous segment are retained. For this reason, a -"no match" result should be interpreted as "partial match of an empty string" -when the pattern contains lookbehinds. - -
-4. Matching a subject string that is split into multiple segments may not -always produce exactly the same result as matching over one single long string, -especially when PCRE2_PARTIAL_SOFT is used. The section "Partial Matching and -Word Boundaries" above describes an issue that arises if the pattern ends with -\b or \B. Another kind of difference may occur when there are multiple -matching possibilities, because (for PCRE2_PARTIAL_SOFT) a partial match result -is given only when there are no completed matches. This means that as soon as -the shortest match has been found, continuation to a new subject segment is no -longer possible. Consider this pcre2test example: -
- re> /dog(sbody)?/ - data> dogsb\=ps - 0: dog - data> do\=ps,dfa - Partial match: do - data> gsb\=ps,dfa,dfa_restart - 0: g - data> dogsbody\=dfa - 0: dogsbody - 1: dog --The first data line passes the string "dogsb" to a standard matching function, -setting the PCRE2_PARTIAL_SOFT option. Although the string is a partial match -for "dogsbody", the result is not PCRE2_ERROR_PARTIAL, because the shorter -string "dog" is a complete match. Similarly, when the subject is presented to -a DFA matching function in several parts ("do" and "gsb" being the first two) -the match stops when "dog" has been found, and it is not possible to continue. -On the other hand, if "dogsbody" is presented as a single string, a DFA -matching function finds both matches. - -
-Because of these problems, it is best to use PCRE2_PARTIAL_HARD when matching -multi-segment data. The example above then behaves differently: +When a partial match has been found using the DFA matching function, it is +possible to continue the match by providing additional subject data and calling +the function again with the same compiled regular expression, this time setting +the PCRE2_DFA_RESTART option. You must pass the same working space as before, +because this is where details of the previous partial match are stored. You can +set the PCRE2_PARTIAL_SOFT or PCRE2_PARTIAL_HARD options with PCRE2_DFA_RESTART +to continue partial matching over multiple segments. Here is an example using +pcre2test:
- re> /dog(sbody)?/ - data> dogsb\=ph - Partial match: dogsb - data> do\=ps,dfa - Partial match: do - data> gsb\=ph,dfa,dfa_restart - Partial match: gsb + re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/ + data> 23ja\=dfa,ps + Partial match: 23ja + data> n05\=dfa,dfa_restart + 0: n05-5. Patterns that contain alternatives at the top level which do not all start -with the same pattern item may not work as expected when PCRE2_DFA_RESTART is -used. For example, consider this pattern: +The first call has "23ja" as the subject, and requests partial matching; the +second call has "n05" as the subject for the continued (restarted) match. +Notice that when the match is complete, only the last part is shown; PCRE2 does +not retain the previously partially-matched string. It is up to the calling +program to do that if it needs to. This means that, for an unanchored pattern, +if a continued match fails, it is not possible to try again at a new starting +point. All this facility is capable of doing is continuing with the previous +match attempt. For example, consider this pattern:
1234|3789@@ -422,30 +377,18 @@ alternative is found at offset 3. There is no partial match for the second alternative, because such a match does not start at the same point in the subject string. Attempting to continue with the string "7890" does not yield a match because only those alternatives that match at one point in the subject -are remembered. The problem arises because the start of the second alternative -matches within the first alternative. There is no problem with anchored -patterns or patterns such as: -
- 1234|ABCD --where no string can be a partial match for both alternatives. This is not a -problem if a standard matching function is used, because the entire match has -to be rerun each time: -
- re> /1234|3789/ - data> ABC123\=ph - Partial match: 123 - data> 1237890 - 0: 3789 --Of course, instead of using PCRE2_DFA_RESTART, the same technique of re-running -the entire match can also be used with the DFA matching function. Another -possibility is to work with two buffers. If a partial match at offset n -in the first buffer is followed by "no match" when PCRE2_DFA_RESTART is used on -the second buffer, you can then try a new match starting at offset n+1 in -the first buffer. +are remembered. Depending on the application, this may or may not be what you +want. + +
+If you do want to allow for starting again at the next character, one way of +doing it is to retain some or all of the segment and try a new complete match, +as described for pcre2_match() above. Another possibility is to work with +two buffers. If a partial match at offset n in the first buffer is +followed by "no match" when PCRE2_DFA_RESTART is used on the second buffer, you +can then try a new match starting at offset n+1 in the first buffer.
-
Philip Hazel
@@ -454,11 +397,11 @@ University Computing Service
Cambridge, England.
-Last updated: 22 December 2014
+Last updated: 04 September 2019
-Copyright © 1997-2014 University of Cambridge.
+Copyright © 1997-2019 University of Cambridge.
Return to the PCRE2 index page. diff --git a/doc/html/pcre2pattern.html b/doc/html/pcre2pattern.html index e43e98e..0aa2191 100644 --- a/doc/html/pcre2pattern.html +++ b/doc/html/pcre2pattern.html @@ -26,23 +26,25 @@ please consult the man page, in case the conversion went wrong.
@@ -62,13 +64,13 @@ by O'Reilly, covers regular expressions in great detail. This description of PCRE2's regular expressions is intended as reference material.
-This document discusses the patterns that are supported by PCRE2 when its main -matching function, pcre2_match(), is used. PCRE2 also has an alternative -matching function, pcre2_dfa_match(), which matches using a different -algorithm that is not Perl-compatible. Some of the features discussed below are -not available when DFA matching is used. The advantages and disadvantages of -the alternative function, and how it differs from the normal function, are -discussed in the +This document discusses the regular expression patterns that are supported by +PCRE2 when its main matching function, pcre2_match(), is used. PCRE2 also +has an alternative matching function, pcre2_dfa_match(), which matches +using a different algorithm that is not Perl-compatible. Some of the features +discussed below are not available when DFA matching is used. The advantages and +disadvantages of the alternative function, and how it differs from the normal +function, are discussed in the pcre2matching page.
@@ -90,10 +92,11 @@ single code units, or as multiple UTF-8 or UTF-16 code units. UTF-32 can be specified for the 32-bit library, in which case it constrains the character values to valid Unicode code points. To process UTF strings, PCRE2 must be built to include Unicode support (which is the default). When using UTF strings -you must either call the compiling function with the PCRE2_UTF option, or the -pattern must start with the special sequence (*UTF), which is equivalent to -setting the relevant option. How setting a UTF mode affects pattern matching is -mentioned in several places below. There is also a summary of features in the +you must either call the compiling function with one or both of the PCRE2_UTF +or PCRE2_MATCH_INVALID_UTF options, or the pattern must start with the special +sequence (*UTF), which is equivalent to setting the relevant PCRE2_UTF. How +setting a UTF mode affects pattern matching is mentioned in several places +below. There is also a summary of features in the pcre2unicode page. @@ -182,8 +185,8 @@ also an explicit memory limit that can be set.These facilities are provided to catch runaway matches that are provoked by -patterns with huge matching trees (a typical example is a pattern with nested -unlimited repeats applied to a long string that does not match). When one of +patterns with huge matching trees. A common example is a pattern with nested +unlimited repeats applied to a long string that does not match. When one of these limits is reached, pcre2_match() gives an error return. The limits can also be set by items at the start of the pattern of the form
@@ -289,10 +292,10 @@ caseless matching is specified (the PCRE2_CASELESS option), letters are matched independently of case.Part of a pattern that is in square brackets is called a "character class". In @@ -322,7 +322,7 @@ a character class the only metacharacters are: \ general escape character ^ negate the class, but only if the first character - indicates character range - [ POSIX character class (only if followed by POSIX syntax) + [ POSIX character class (if followed by POSIX syntax) ] terminates the character class The following sections describe the use of each of the metacharacters. @@ -330,7 +330,7 @@ The following sections describe the use of each of the metacharacters.-The power of regular expressions comes from the ability to include alternatives -and repetitions in the pattern. These are encoded in the pattern by the use of -metacharacters, which do not stand for themselves but instead are -interpreted in some special way. +The power of regular expressions comes from the ability to include wild cards, +character classes, alternatives, and repetitions in the pattern. These are +encoded in the pattern by the use of metacharacters, which do not stand +for themselves but instead are interpreted in some special way.
There are two different sets of metacharacters: those that are recognized @@ -306,14 +309,11 @@ are as follows: . match any character except newline (by default) [ start character class definition | start of alternative branch - ( start subpattern - ) end subpattern - ? extends the meaning of ( - also 0 or 1 quantifier - also quantifier minimizer + ( start group or control verb + ) end group or control verb * 0 or more quantifier - + 1 or more quantifier - also "possessive quantifier" + + 1 or more quantifier; also "possessive quantifier" + ? 0 or 1 quantifier; also quantifier minimizer { start min/max quantifier
The backslash character has several uses. Firstly, if it is followed by a -character that is not a number or a letter, it takes away any special meaning +character that is not a digit or a letter, it takes away any special meaning that character may have. This use of backslash as an escape character applies both inside and outside character classes.
@@ -342,7 +342,7 @@ precede a non-alphanumeric with backslash to specify that it stands for itself. In particular, if you want to match a backslash, you write \\.-In a UTF mode, only ASCII numbers and letters have any special meaning after a +In a UTF mode, only ASCII digits and letters have any special meaning after a backslash. All other characters (in particular, those whose code points are greater than 127) are treated as literals.
@@ -354,13 +354,13 @@ escaping backslash can be used to include a white space or # character as part of the pattern.-If you want to remove the special meaning from a sequence of characters, you -can do so by putting them between \Q and \E. This is different from Perl in -that $ and @ are handled as literals in \Q...\E sequences in PCRE2, whereas -in Perl, $ and @ cause variable interpolation. Also, Perl does "double-quotish -backslash interpolation" on any backslashes between \Q and \E which, its -documentation says, "may lead to confusing results". PCRE2 treats a backslash -between \Q and \E just like any other character. Note the following examples: +If you want to treat all characters in a sequence as literals, you can do so by +putting them between \Q and \E. This is different from Perl in that $ and @ +are handled as literals in \Q...\E sequences in PCRE2, whereas in Perl, $ and +@ cause variable interpolation. Also, Perl does "double-quotish backslash +interpolation" on any backslashes between \Q and \E which, its documentation +says, "may lead to confusing results". PCRE2 treats a backslash between \Q and +\E just like any other character. Note the following examples:
Pattern PCRE2 matches Perl matches @@ -385,15 +385,15 @@ A second use of backslash provides a way of encoding non-printing characters in patterns in a visible manner. There is no restriction on the appearance of non-printing characters in a pattern, but when a pattern is being prepared by text editing, it is often easier to use one of the following escape sequences -than the binary character it represents. In an ASCII or Unicode environment, -these escapes are as follows: +instead of the binary character it represents. In an ASCII or Unicode +environment, these escapes are as follows:is another pattern that matches "foo" preceded by three digits and any three characters that are not "999". + +\a alarm, that is, the BEL character (hex 07) \cx "control-x", where x is any printable ASCII character \e escape (hex 1B) \f form feed (hex 0C) \n linefeed (hex 0A) - \r carriage return (hex 0D) + \r carriage return (hex 0D) (but see below) \t tab (hex 09) \0dd character with octal code 0dd \ddd character with octal code ddd, or backreference @@ -401,13 +401,46 @@ these escapes are as follows: \xhh character with hex code hh \x{hhh..} character with hex code hhh.. \N{U+hhh..} character with Unicode hex code point hhh.. - \uhhhh character with hex code hhhh (when PCRE2_ALT_BSUX is set)-The \N{U+hhh..} escape sequence is recognized only when the PCRE2_UTF option -is set, that is, when PCRE2 is operating in a Unicode mode. Perl also uses -\N{name} to specify characters by Unicode name; PCRE2 does not support this. -Note that when \N is not followed by an opening brace (curly bracket) it has -an entirely different meaning, matching any character that is not a newline. +By default, after \x that is not followed by {, from zero to two hexadecimal +digits are read (letters can be in upper or lower case). Any number of +hexadecimal digits may appear between \x{ and }. If a character other than a +hexadecimal digit appears between \x{ and }, or if there is no terminating }, +an error occurs. + ++Characters whose code points are less than 256 can be defined by either of the +two syntaxes for \x or by an octal sequence. There is no difference in the way +they are handled. For example, \xdc is exactly the same as \x{dc} or \334. +However, using the braced versions does make such sequences easier to read. +
++Support is available for some ECMAScript (aka JavaScript) escape sequences via +two compile-time options. If PCRE2_ALT_BSUX is set, the sequence \x followed +by { is not recognized. Only if \x is followed by two hexadecimal digits is it +recognized as a character escape. Otherwise it is interpreted as a literal "x" +character. In this mode, support for code points greater than 256 is provided +by \u, which must be followed by four hexadecimal digits; otherwise it is +interpreted as a literal "u" character. +
++PCRE2_EXTRA_ALT_BSUX has the same effect as PCRE2_ALT_BSUX and, in addition, +\u{hhh..} is recognized as the character specified by hexadecimal code point. +There may be any number of hexadecimal digits. This syntax is from ECMAScript +6. +
++The \N{U+hhh..} escape sequence is recognized only when PCRE2 is operating in +UTF mode. Perl also uses \N{name} to specify characters by Unicode name; PCRE2 +does not support this. Note that when \N is not followed by an opening brace +(curly bracket) it has an entirely different meaning, matching any character +that is not a newline. +
++There are some legacy applications where the escape sequence \r is expected to +match a newline. If the PCRE2_EXTRA_ESCAPED_CR_IS_LF option is set, \r in a +pattern is converted to \n so that it matches a LF (linefeed) instead of a CR +(carriage return) character.
The precise effect of \cx on ASCII characters is as follows: if x is a lower @@ -468,12 +501,12 @@ and Perl has changed over time, causing PCRE2 also to change.
Outside a character class, PCRE2 reads the digit and any following digits as a decimal number. If the number is less than 10, begins with the digit 8 or 9, or -if there are at least that many previous capturing left parentheses in the -expression, the entire sequence is taken as a backreference. A -description of how this works is given +if there are at least that many previous capture groups in the expression, the +entire sequence is taken as a backreference. A description of how this +works is given later, following the discussion of -parenthesized subpatterns. +parenthesized groups. Otherwise, up to three octal digits are read to form a character code.
@@ -483,7 +516,7 @@ backslash, using them to generate a data character. Any subsequent digits stand for themselves. For example, outside a character class:
\040 is another way of writing an ASCII space - \40 is the same, provided there are fewer than 40 previous capturing subpatterns + \40 is the same, provided there are fewer than 40 previous capture groups \7 is always a backreference \11 might be a backreference, or another way of writing a tab \011 is always a tab @@ -496,26 +529,6 @@ Note that octal values of 100 or greater that are specified using this syntax must not be introduced by a leading zero, because no more than three octal digits are ever read. --Those that are not part of an identified script are lumped together as -"Common". The current list of scripts is: +Unassigned characters (and in non-UTF 32-bit mode, characters with code points +greater than 0x10FFFF) are assigned the "Unknown" script. Others that are not +part of an identified script are lumped together as "Common". The current list +of scripts is:-By default, after \x that is not followed by {, from zero to two hexadecimal -digits are read (letters can be in upper or lower case). Any number of -hexadecimal digits may appear between \x{ and }. If a character other than -a hexadecimal digit appears between \x{ and }, or if there is no terminating -}, an error occurs. -
--If the PCRE2_ALT_BSUX option is set, the interpretation of \x is as just -described only when it is followed by two hexadecimal digits. Otherwise, it -matches a literal "x" character. In this mode, support for code points greater -than 256 is provided by \u, which must be followed by four hexadecimal digits; -otherwise it matches a literal "u" character. -
--Characters whose value is less than 256 can be defined by either of the two -syntaxes for \x (or by \u in PCRE2_ALT_BSUX mode). There is no difference in -the way they are handled. For example, \xdc is exactly the same as \x{dc} (or -\u00dc in PCRE2_ALT_BSUX mode). -
Constraints on character values
@@ -554,9 +567,10 @@ Unsupported escape sequencesIn Perl, the sequences \F, \l, \L, \u, and \U are recognized by its string handler and used to modify the case of following characters. By default, PCRE2 -does not support these escape sequences. However, if the PCRE2_ALT_BSUX option -is set, \U matches a "U" character, and \u can be used to define a character -by code point, as described above. +does not support these escape sequences in patterns. However, if either of the +PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX options is set, \U matches a "U" +character, and \u can be used to define a character by code point, as +described above.
Absolute and relative backreferences @@ -567,7 +581,7 @@ in braces, is an absolute or relative backreference. A named backreference can be coded as \g{name}. Backreferences are discussed later, following the discussion of -parenthesized subpatterns. +parenthesized groups.
Absolute and relative subroutine calls @@ -575,11 +589,11 @@ Absolute and relative subroutine callsFor compatibility with Oniguruma, the non-Perl syntax \g followed by a name or a number enclosed either in angle brackets or single quotes, is an alternative -syntax for referencing a subpattern as a "subroutine". Details are discussed +syntax for referencing a capture group as a subroutine. Details are discussed later. Note that \g{...} (Perl syntax) and \g<...> (Oniguruma syntax) are not synonymous. The former is a backreference; the latter is a -subroutine +subroutine call.
@@ -746,21 +760,22 @@ Unicode character properties
When PCRE2 is built with Unicode support (the default), three additional escape -sequences that match characters with specific properties are available. In -8-bit non-UTF-8 mode, these sequences are of course limited to testing -characters whose code points are less than 256, but they do work in this mode. -In 32-bit non-UTF mode, code points greater than 0x10ffff (the Unicode limit) -may be encountered. These are all treated as being in the Common script and -with an unassigned type. The extra escape sequences are: +sequences that match characters with specific properties are available. They +can be used in any mode, though in 8-bit and 16-bit non-UTF modes these +sequences are of course limited to testing characters whose code points are +less than U+0100 and U+10000, respectively. In 32-bit non-UTF mode, code points +greater than 0x10ffff (the Unicode limit) may be encountered. These are all +treated as being in the Unknown script and with an unassigned type. The extra +escape sequences are:
\p{xx} a character with the xx property \P{xx} a character without the xx property \X a Unicode extended grapheme cluster-The property names represented by xx above are limited to the Unicode -script names, the general category properties, "Any", which matches any -character (including newline), and some special PCRE2 properties (described -in the +The property names represented by xx above are case-sensitive. There is +support for Unicode script names, Unicode general category properties, "Any", +which matches any character (including newline), and some special PCRE2 +properties (described in the next section). Other Perl properties such as "InMusicalSymbols" are not supported by PCRE2. Note that \P{Any} does not match any characters, so always causes a match @@ -774,8 +789,10 @@ example: \p{Greek} \P{Han}Adlam, @@ -812,6 +829,7 @@ Dogra, Duployan, Egyptian_Hieroglyphs, Elbasan, +Elymaic, Ethiopic, Georgian, Glagolitic, @@ -869,10 +887,12 @@ Mro, Multani, Myanmar, Nabataean, +Nandinagari, New_Tai_Lue, Newa, Nko, Nushu, +Nyakeng_Puachue_Hmong, Ogham, Ol_Chiki, Old_Hungarian, @@ -922,7 +942,9 @@ Tibetan, Tifinagh, Tirhuta, Ugaritic, +Unknown, Vai, +Wancho, Warang_Citi, Yi, Zanabazar_Square. @@ -993,12 +1015,14 @@ the Lu, Ll, or Lt property, in other words, a letter that is not classified as a modifier or "other".
-The Cs (Surrogate) property applies only to characters in the range U+D800 to -U+DFFF. Such characters are not valid in Unicode strings and so -cannot be tested by PCRE2, unless UTF validity checking has been turned off -(see the discussion of PCRE2_NO_UTF_CHECK in the +The Cs (Surrogate) property applies only to characters whose code points are in +the range U+D800 to U+DFFF. These characters are no different to any other +character when PCRE2 is not in UTF mode (using the 16-bit or 32-bit library). +However, they are not valid in Unicode strings and so cannot be tested by PCRE2 +in UTF mode, unless UTF validity checking has been turned off (see the +discussion of PCRE2_NO_UTF_CHECK in the pcre2api -page). Perl does not support the Cs property. +page).
The long synonyms for property names that Perl supports (such as \p{Letter}) @@ -1128,7 +1152,7 @@ a lookbehind assertion However, in this case, the part of the subject before the real match does not have to be of fixed length, as lookbehind assertions do. The use of \K does not interfere with the setting of -captured substrings. +captured substrings. For example, when the pattern
(foo)\Kbar @@ -1156,7 +1180,7 @@ Simple assertions The final use of backslash is for certain simple assertions. An assertion specifies a condition that has to be met at a particular point in a match, without consuming any characters from the subject string. The use of -subpatterns for more complicated assertions is described +groups for more complicated assertions is described below. The backslashed assertions are:fails, because it matches the entire string owing to the greediness of the .* -item. - -@@ -1176,12 +1200,12 @@ character. If any other of these assertions appears in a character class, an A word boundary is a position in the subject string where the current character and the previous character do not both match \w or \W (i.e. one matches \w and the other matches \W), or the start or end of the string if the -first or last character matches \w, respectively. In a UTF mode, the meanings -of \w and \W can be changed by setting the PCRE2_UCP option. When this is -done, it also affects \b and \B. Neither PCRE2 nor Perl has a separate "start -of word" or "end of word" metasequence. However, whatever follows \b normally -determines which it is. For example, the fragment \ba matches "a" at the start -of a word. +first or last character matches \w, respectively. When PCRE2 is built with +Unicode support, the meanings of \w and \W can be changed by setting the +PCRE2_UCP option. When this is done, it also affects \b and \B. Neither PCRE2 +nor Perl has a separate "start of word" or "end of word" metasequence. However, +whatever follows \b normally determines which it is. For example, the fragment +\ba matches "a" at the start of a word.In this example, a group that starts with (?| resets the capturing parentheses numbers in each alternative (see -"Duplicate Subpattern Numbers" +"Duplicate Group Numbers" below). The assertions at the start of each branch check the next UTF-8 character for values whose encoding uses 1, 2, 3, or 4 bytes, respectively. The character's individual bytes are then captured by the appropriate number of @@ -1622,10 +1646,10 @@ the pattern matches either "gilbert" or "sullivan". Any number of alternatives may appear, and an empty alternative is permitted (matching the empty string). The matching process tries each alternative in turn, from left to right, and the first one -that succeeds is used. If the alternatives are within a subpattern -(defined below), +that succeeds is used. If the alternatives are within a group +(defined below), "succeeds" means matching the rest of the main pattern as well as the -alternative in the subpattern. +alternative in the group.The \A, \Z, and \z assertions differ from the traditional circumflex and @@ -1342,7 +1366,7 @@ with \C in UTF-8 or UTF-16 mode means that the rest of the string may start with a malformed UTF character. This has undefined results, because PCRE2 assumes that it is matching character by character in a valid UTF string (by default it checks the subject string's validity at the start of processing -unless the PCRE2_NO_UTF_CHECK option is used). +unless the PCRE2_NO_UTF_CHECK or PCRE2_MATCH_INVALID_UTF option is used).
An application can lock out the use of \C by setting the @@ -1376,7 +1400,7 @@ could be used with a UTF-8 string (ignore white space and line breaks):
INTERNAL OPTION SETTING
@@ -1668,16 +1692,16 @@ respectively. However, these are not unset by (?^).
When one of these option changes occurs at top level (that is, not inside -subpattern parentheses), the change applies to the remainder of the pattern -that follows. An option change within a subpattern (see below for a description -of subpatterns) affects only that part of the subpattern that follows it, so +group parentheses), the change applies to the remainder of the pattern +that follows. An option change within a group (see below for a description +of groups) affects only that part of the group that follows it, so
(a(?i)b)cmatches abc and aBc and no other strings (assuming PCRE2_CASELESS is not used). By this means, options can be made to have different settings in different parts of the pattern. Any changes made in one alternative do carry on -into subsequent branches within the same subpattern. For example, +into subsequent branches within the same group. For example,(a(?i)b|c)@@ -1688,7 +1712,7 @@ behaviour otherwise.As a convenient shorthand, if any option settings are required at the start of -a non-capturing subpattern (see the next section), the option letters may +a non-capturing group (see the next section), the option letters may appear between the "?" and the ":". Thus the two patterns
(?i:saturday|sunday) @@ -1697,21 +1721,22 @@ appear between the "?" and the ":". Thus the two patterns match exactly the same set of strings.-It is possible to construct infinite loops by following a subpattern that can -match no characters with a quantifier that has no upper limit, for example: +It is possible to construct infinite loops by following a group that can match +no characters with a quantifier that has no upper limit, for example:-Note: There are other PCRE2-specific options that can be set by the -application when the compiling function is called. The pattern can contain -special leading sequences such as (*CRLF) to override what the application has -set or what has been defaulted. Details are given in the section entitled +Note: There are other PCRE2-specific options, applying to the whole +pattern, which can be set by the application when the compiling function is +called. In addition, the pattern can contain special leading sequences such as +(*CRLF) to override what the application has set or what has been defaulted. +Details are given in the section entitled "Newline sequences" above. There are also the (*UTF) and (*UCP) leading sequences that can be used to set UTF and Unicode property modes; they are equivalent to setting the PCRE2_UTF and PCRE2_UCP options, respectively. However, the application can set the PCRE2_NEVER_UTF and PCRE2_NEVER_UCP options, which lock out the use of the (*UTF) and (*UCP) sequences. -
-
SUBPATTERNS
+ +
GROUPS
-Subpatterns are delimited by parentheses (round brackets), which can be nested. -Turning part of a pattern into a subpattern does two things: +Groups are delimited by parentheses (round brackets), which can be nested. +Turning part of a pattern into a group does two things:
1. It localizes a set of alternatives. For example, the pattern @@ -1722,16 +1747,16 @@ matches "cataract", "caterpillar", or "cat". Without the parentheses, it would match "cataract", "erpillar" or an empty string.
-2. It sets up the subpattern as a capturing subpattern. This means that, when -the whole pattern matches, the portion of the subject string that matched the -subpattern is passed back to the caller, separately from the portion that -matched the whole pattern. (This applies only to the traditional matching -function; the DFA matching function does not support capturing.) +2. It creates a "capture group". This means that, when the whole pattern +matches, the portion of the subject string that matched the group is passed +back to the caller, separately from the portion that matched the whole pattern. +(This applies only to the traditional matching function; the DFA matching +function does not support capturing.)Opening parentheses are counted from left to right (starting from 1) to obtain -numbers for the capturing subpatterns. For example, if the string "the red -king" is matched against the pattern +numbers for capture groups. For example, if the string "the red king" is +matched against the pattern
the ((red|white) (king|queen))@@ -1740,36 +1765,35 @@ the captured substrings are "red king", "red", and "king", and are numbered 1,The fact that plain parentheses fulfil two functions is not always helpful. -There are often times when a grouping subpattern is required without a -capturing requirement. If an opening parenthesis is followed by a question mark -and a colon, the subpattern does not do any capturing, and is not counted when -computing the number of any subsequent capturing subpatterns. For example, if -the string "the white queen" is matched against the pattern +There are often times when grouping is required without capturing. If an +opening parenthesis is followed by a question mark and a colon, the group +does not do any capturing, and is not counted when computing the number of any +subsequent capture groups. For example, if the string "the white queen" +is matched against the pattern
the ((?:red|white) (king|queen))the captured substrings are "white queen" and "queen", and are numbered 1 and -2. The maximum number of capturing subpatterns is 65535. +2. The maximum number of capture groups is 65535.As a convenient shorthand, if any option settings are required at the start of -a non-capturing subpattern, the option letters may appear between the "?" and -the ":". Thus the two patterns +a non-capturing group, the option letters may appear between the "?" and the +":". Thus the two patterns
(?i:saturday|sunday) (?:(?i)saturday|sunday)match exactly the same set of strings. Because alternative branches are tried -from left to right, and options are not reset until the end of the subpattern -is reached, an option setting in one branch does affect subsequent branches, so +from left to right, and options are not reset until the end of the group is +reached, an option setting in one branch does affect subsequent branches, so the above patterns match "SUNDAY" as well as "Saturday". - -
DUPLICATE SUBPATTERN NUMBERS
+ +
DUPLICATE GROUP NUMBERS
-Perl 5.10 introduced a feature whereby each alternative in a subpattern uses -the same numbers for its capturing parentheses. Such a subpattern starts with -(?| and is itself a non-capturing subpattern. For example, consider this -pattern: +Perl 5.10 introduced a feature whereby each alternative in a group uses the +same numbers for its capturing parentheses. Such a group starts with (?| and is +itself a non-capturing group. For example, consider this pattern:
(?|(Sat)ur|(Sun))day@@ -1779,7 +1803,7 @@ at captured substring number one, whichever alternative matched. This construct is useful when you want to capture part, but not all, of one of a number of alternatives. Inside a (?| group, parentheses are numbered as usual, but the number is reset at the start of each branch. The numbers of any capturing -parentheses that follow the subpattern start after the highest number used in +parentheses that follow the whole group start after the highest number used in any branch. The following example is taken from the Perl documentation. The numbers underneath show in which buffer the captured content will be stored.@@ -1787,13 +1811,12 @@ numbers underneath show in which buffer the captured content will be stored. / ( a ) (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x # 1 2 2 3 2 3 4-A backreference to a numbered subpattern uses the most recent value that is -set for that number by any subpattern. The following pattern matches "abcabc" -or "defdef": +A backreference to a capture group uses the most recent value that is set for +the group. The following pattern matches "abcabc" or "defdef":/(?|(abc)|(def))\1/-In contrast, a subroutine call to a numbered subpattern always refers to the +In contrast, a subroutine call to a capture group always refers to the first one in the pattern with the given number. The following pattern matches "abcabc" or "defabc":@@ -1805,29 +1828,35 @@ of computing an absolute group number.The general repetition quantifier specifies a minimum and maximum number of permitted matches, by giving the two numbers in curly brackets (braces), separated by a comma. The numbers must be less than 65536, and the first must -be less than or equal to the second. For example: +be less than or equal to the second. For example,If a condition test -for a subpattern's having matched refers to a non-unique number, the test is -true if any of the subpatterns of that number have matched. +for a group's having matched refers to a non-unique number, the test is +true if any group with that number has matched.
An alternative approach to using this "branch reset" feature is to use -duplicate named subpatterns, as described in the next section. +duplicate named groups, as described in the next section.
-
NAMED SUBPATTERNS
+
NAMED CAPTURE GROUPS
-Identifying capturing parentheses by number is simple, but it can be very hard -to keep track of the numbers in complicated patterns. Furthermore, if an -expression is modified, the numbers may change. To help with this difficulty, -PCRE2 supports the naming of capturing subpatterns. This feature was not added -to Perl until release 5.10. Python had the feature earlier, and PCRE1 -introduced it at release 4.0, using the Python syntax. PCRE2 supports both the -Perl and the Python syntax. +Identifying capture groups by number is simple, but it can be very hard to keep +track of the numbers in complicated patterns. Furthermore, if an expression is +modified, the numbers may change. To help with this difficulty, PCRE2 supports +the naming of capture groups. This feature was not added to Perl until release +5.10. Python had the feature earlier, and PCRE1 introduced it at release 4.0, +using the Python syntax. PCRE2 supports both the Perl and the Python syntax.
-In PCRE2, a capturing subpattern can be named in one of three ways: -(?<name>...) or (?'name'...) as in Perl, or (?P<name>...) as in Python. Names -consist of up to 32 alphanumeric characters and underscores, but must start -with a non-digit. References to capturing parentheses from other parts of the -pattern, such as +In PCRE2, a capture group can be named in one of three ways: (?<name>...) or +(?'name'...) as in Perl, or (?P<name>...) as in Python. Names may be up to 32 +code units long. When PCRE2_UTF is not set, they may contain only ASCII +alphanumeric characters and underscores, but must start with a non-digit. When +PCRE2_UTF is set, the syntax of group names is extended to allow any Unicode +letter or Unicode decimal digit. In other words, group names must match one of +these patterns: +
+ ^[_A-Za-z][_A-Za-z0-9]*\z when PCRE2_UTF is not set + ^[_\p{L}][_\p{L}\p{Nd}]*\z when PCRE2_UTF is set ++References to capture groups from other parts of the pattern, such as backreferences, recursion, and @@ -1835,18 +1864,18 @@ and can all be made by name as well as by number.-Named capturing parentheses are allocated numbers as well as names, exactly as -if the names were not present. In both PCRE2 and Perl, capturing subpatterns +Named capture groups are allocated numbers as well as names, exactly as +if the names were not present. In both PCRE2 and Perl, capture groups are primarily identified by numbers; any names are just aliases for these numbers. The PCRE2 API provides function calls for extracting the complete name-to-number translation table from a compiled pattern, as well as convenience functions for extracting captured substrings by name.
-Warning: When more than one subpattern has the same number, as described -in the previous section, a name given to one of them applies to all of them. -Perl allows identically numbered subpatterns to have different names. Consider -this pattern, where there are two capturing subpatterns, both numbered 1: +Warning: When more than one capture group has the same number, as +described in the previous section, a name given to one of them applies to all +of them. Perl allows identically numbered groups to have different names. +Consider this pattern, where there are two capture groups, both numbered 1:
(?|(?<AA>aa)|(?<BB>bb))@@ -1861,21 +1890,21 @@ pattern:(?|(?<AA>aa)|(bb))-Although the second subpattern number 1 is not explicitly named, the name AA is -still an alias for subpattern 1. Whether the pattern matches "aa" or "bb", a +Although the second group number 1 is not explicitly named, the name AA is +still an alias for any group 1. Whether the pattern matches "aa" or "bb", a reference by name to group AA yields the matched string.By default, a name must be unique within a pattern, except that duplicate names -are permitted for subpatterns with the same number, for example: +are permitted for groups with the same number, for example:
(?|(?<AA>aa)|(?<AA>bb))The duplicate name constraint can be disabled by setting the PCRE2_DUPNAMES option at compile time, or by the use of (?J) within the pattern. Duplicate -names can be useful for patterns where only one instance of the named -parentheses can match. Suppose you want to match the name of a weekday, either -as a 3-letter abbreviation or as the full name, and in both cases you want to +names can be useful for patterns where only one instance of the named capture +group can match. Suppose you want to match the name of a weekday, either as a +3-letter abbreviation or as the full name, and in both cases you want to extract the abbreviation. This pattern (ignoring the line breaks) does the job:(?<DN>Mon|Fri|Sun)(?:day)?| @@ -1884,26 +1913,26 @@ extract the abbreviation. This pattern (ignoring the line breaks) does the job: (?<DN>Thu)(?:rsday)?| (?<DN>Sat)(?:urday)?-There are five capturing substrings, but only one is ever set after a match. -The convenience functions for extracting the data by name returns the substring -for the first (and in this example, the only) subpattern of that name that -matched. This saves searching to find which numbered subpattern it was. (An -alternative way of solving this problem is to use a "branch reset" subpattern, -as described in the previous section.) +There are five capture groups, but only one is ever set after a match. The +convenience functions for extracting the data by name returns the substring for +the first (and in this example, the only) group of that name that matched. This +saves searching to find which numbered group it was. (An alternative way of +solving this problem is to use a "branch reset" group, as described in the +previous section.)-If you make a backreference to a non-unique named subpattern from elsewhere in -the pattern, the subpatterns to which the name refers are checked in the order -in which they appear in the overall pattern. The first one that is set is used -for the reference. For example, this pattern matches both "foofoo" and -"barbar" but not "foobar" or "barfoo": +If you make a backreference to a non-unique named group from elsewhere in the +pattern, the groups to which the name refers are checked in the order in which +they appear in the overall pattern. The first one that is set is used for the +reference. For example, this pattern matches both "foofoo" and "barbar" but not +"foobar" or "barfoo":
(?:(?<n>foo)|(?<n>bar))\k<n>-If you make a subroutine call to a non-unique named subpattern, the one that +If you make a subroutine call to a non-unique named group, the one that corresponds to the first occurrence of the name is used. In the absence of duplicate numbers this is the one with the lowest number.
@@ -1911,11 +1940,11 @@ duplicate numbers this is the one with the lowest number. If you use a named reference in a condition test (see the section about conditions -below), either to check whether a subpattern has matched, or to check for -recursion, all subpatterns with the same name are tested. If the condition is -true for any one of them, the overall condition is true. This is the same -behaviour as testing by number. For further details of the interfaces for -handling named subpatterns, see the +below), either to check whether a capture group has matched, or to check for +recursion, all groups with the same name are tested. If the condition is true +for any one of them, the overall condition is true. This is the same behaviour +as testing by number. For further details of the interfaces for handling named +capture groups, see the pcre2api documentation. @@ -1927,18 +1956,18 @@ items: a literal data character the dot metacharacter the \C escape sequence - the \X escape sequence the \R escape sequence + the \X escape sequence an escape such as \d or \pL that matches a single character a character class a backreference - a parenthesized subpattern (including most assertions) - a subroutine call to a subpattern (recursive or otherwise) + a parenthesized group (including most assertions) + a subroutine call (recursive or otherwise)z{2,4}@@ -1968,12 +1997,12 @@ several code units long (and they may be of different lengths).The quantifier {0} is permitted, causing the expression to behave as if the previous item and the quantifier were not present. This may be useful for -subpatterns that are referenced as -subroutines +capture groups that are referenced as +subroutines from elsewhere in the pattern (but see also the section entitled -"Defining subpatterns for use by reference only" -below). Items other than subpatterns that have a {0} quantifier are omitted -from the compiled pattern. +"Defining capture groups for use by reference only" +below). Except for parenthesized groups, items that have a {0} quantifier are +omitted from the compiled pattern.
For convenience, the three most common quantifiers have single-character @@ -1983,23 +2012,25 @@ abbreviations: + is equivalent to {1,} ? is equivalent to {0,1}
(a?)*Earlier versions of Perl and PCRE1 used to give an error at compile time for such patterns. However, because there are cases where this can be useful, such -patterns are now accepted, but if any repetition of the subpattern does in fact -match no characters, the loop is forcibly broken. +patterns are now accepted, but whenever an iteration of such a group matches no +characters, matching moves on to the next item in the pattern instead of +repeatedly matching an empty string. This does not prevent backtracking into +any of the iterations if a subsequent item fails to match.-By default, the quantifiers are "greedy", that is, they match as much as -possible (up to the maximum number of permitted times), without causing the -rest of the pattern to fail. The classic example of where this gives problems -is in trying to match comments in C programs. These appear between /* and */ -and within the comment, individual * and / characters may appear. An attempt to -match C comments by applying the pattern +By default, quantifiers are "greedy", that is, they match as much as possible +(up to the maximum number of permitted times), without causing the rest of the +pattern to fail. The classic example of where this gives problems is in trying +to match comments in C programs. These appear between /* and */ and within the +comment, individual * and / characters may appear. An attempt to match C +comments by applying the pattern
/\*.*\*/@@ -2008,11 +2039,9 @@ to the string /* first comment */ not comment /* second comment */-If a quantifier is followed by a question mark, it ceases to be greedy, and -instead matches the minimum number of times possible, so the pattern +item. However, if a quantifier is followed by a question mark, it ceases to be +greedy, and instead matches the minimum number of times possible, so the +pattern
/\*.*?\*/@@ -2033,7 +2062,7 @@ greedy by following them with a question mark. In other words, it inverts the default behaviour.-When a parenthesized subpattern is quantified with a minimum repeat count that +When a parenthesized group is quantified with a minimum repeat count that is greater than 1 or with a limited maximum, more memory is required for the compiled pattern, in proportion to the size of the minimum or maximum.
@@ -2073,15 +2102,14 @@ It matches "ab" in the subject "aab". The use of the backtracking control verbs PCRE2_NO_DOTSTAR_ANCHOR, to do so explicitly.-When a capturing subpattern is repeated, the value captured is the substring -that matched the final iteration. For example, after +When a capture group is repeated, the value captured is the substring that +matched the final iteration. For example, after
(tweedle[dume]{3}\s*)+has matched "tweedledum tweedledee" the value of the captured substring is -"tweedledee". However, if there are nested capturing subpatterns, the -corresponding captured values may have been set in previous iterations. For -example, after +"tweedledee". However, if there are nested capture groups, the corresponding +captured values may have been set in previous iterations. For example, after(a|(b))+@@ -2105,7 +2133,7 @@ After matching all 6 digits and then failing to match "foo", the normal action of the matcher is to try again with only 5 digits matching the \d+ item, and then with 4, and so on, before ultimately failing. "Atomic grouping" (a term taken from Jeffrey Friedl's book) provides the means for specifying -that once a subpattern has matched, it is not to be re-evaluated in this way. +that once a group has matched, it is not to be re-evaluated in this way.If we use atomic grouping for the previous example, the matcher gives up @@ -2114,26 +2142,31 @@ special parenthesis, starting with (?> as in this example:
(?>\d+)foo-This kind of parenthesis "locks up" the part of the pattern it contains once -it has matched, and a failure further into the pattern is prevented from -backtracking into it. Backtracking past it to previous items, however, works as -normal. +Perl 5.28 introduced an experimental alphabetic form starting with (* which may +be easier to remember: ++ (*atomic:\d+)foo ++This kind of parenthesized group "locks up" the part of the pattern it +contains once it has matched, and a failure further into the pattern is +prevented from backtracking into it. Backtracking past it to previous items, +however, works as normal.-An alternative description is that a subpattern of this type matches exactly -the string of characters that an identical standalone pattern would match, if +An alternative description is that a group of this type matches exactly the +string of characters that an identical standalone pattern would match, if anchored at the current point in the subject string.
-Atomic grouping subpatterns are not capturing subpatterns. Simple cases such as -the above example can be thought of as a maximizing repeat that must swallow -everything it can. So, while both \d+ and \d+? are prepared to adjust the -number of digits they match in order to make the rest of the pattern match, -(?>\d+) can only match an entire sequence of digits. +Atomic groups are not capture groups. Simple cases such as the above example +can be thought of as a maximizing repeat that must swallow everything it can. +So, while both \d+ and \d+? are prepared to adjust the number of digits they +match in order to make the rest of the pattern match, (?>\d+) can only match +an entire sequence of digits.
Atomic groups in general can of course contain arbitrarily complicated -subpatterns, and can be nested. However, when the subpattern for an atomic +expressions, and can be nested. However, when the contents of an atomic group is just a single repeated item, as in the example above, a simpler notation, called a "possessive quantifier" can be used. This consists of an additional + character following a quantifier. Using this notation, the @@ -2156,8 +2189,8 @@ difference; possessive quantifiers should be slightly faster. The possessive quantifier syntax is an extension to the Perl 5.8 syntax. Jeffrey Friedl originated the idea (and the name) in the first edition of his book. Mike McCloskey liked it, so implemented it when he built Sun's Java -package, and PCRE1 copied it from there. It ultimately found its way into Perl -at release 5.10. +package, and PCRE1 copied it from there. It found its way into Perl at release +5.10.
PCRE2 has an optimization that automatically "possessifies" certain simple @@ -2167,10 +2200,9 @@ This feature can be disabled by the PCRE2_NO_AUTOPOSSESS option, or starting the pattern with (*NO_AUTO_POSSESS).
-When a pattern contains an unlimited repeat inside a subpattern that can itself -be repeated an unlimited number of times, the use of an atomic group is the -only way to avoid some failing matches taking a very long time indeed. The -pattern +When a pattern contains an unlimited repeat inside a group that can itself be +repeated an unlimited number of times, the use of an atomic group is the only +way to avoid some failing matches taking a very long time indeed. The pattern
(\D+|<\d+>)*[!?]@@ -2196,28 +2228,27 @@ sequences of non-digits cannot be broken, and failure happens quickly.
BACKREFERENCES
Outside a character class, a backslash followed by a digit greater than 0 (and -possibly further digits) is a backreference to a capturing subpattern earlier -(that is, to its left) in the pattern, provided there have been that many -previous capturing left parentheses. +possibly further digits) is a backreference to a capture group earlier (that +is, to its left) in the pattern, provided there have been that many previous +capture groups.
However, if the decimal number following the backslash is less than 8, it is -always taken as a backreference, and causes an error only if there are not -that many capturing left parentheses in the entire pattern. In other words, the -parentheses that are referenced need not be to the left of the reference for -numbers less than 8. A "forward backreference" of this type can make sense -when a repetition is involved and the subpattern to the right has participated -in an earlier iteration. +always taken as a backreference, and causes an error only if there are not that +many capture groups in the entire pattern. In other words, the group that is +referenced need not be to the left of the reference for numbers less than 8. A +"forward backreference" of this type can make sense when a repetition is +involved and the group to the right has participated in an earlier iteration.
-It is not possible to have a numerical "forward backreference" to a subpattern -whose number is 8 or more using this syntax because a sequence such as \50 is +It is not possible to have a numerical "forward backreference" to a group whose +number is 8 or more using this syntax because a sequence such as \50 is interpreted as a character defined in octal. See the subsection entitled "Non-printing characters" above -for further details of the handling of digits following a backslash. There is -no such problem when named parentheses are used. A backreference to any -subpattern is possible using named parentheses (see below). +for further details of the handling of digits following a backslash. Other +forms of backreferencing do not suffer from this restriction. In particular, +there is no problem when named capture groups are used (see below).
Another way of avoiding the ambiguity inherent in the use of digits following a @@ -2235,22 +2266,22 @@ the reference. A signed number is a relative reference. Consider this example:
(abc(def)ghi)\g{-1}-The sequence \g{-1} is a reference to the most recently started capturing -subpattern before \g, that is, is it equivalent to \2 in this example. -Similarly, \g{-2} would be equivalent to \1. The use of relative references -can be helpful in long patterns, and also in patterns that are created by -joining together fragments that contain references within themselves. +The sequence \g{-1} is a reference to the most recently started capture group +before \g, that is, is it equivalent to \2 in this example. Similarly, +\g{-2} would be equivalent to \1. The use of relative references can be +helpful in long patterns, and also in patterns that are created by joining +together fragments that contain references within themselves.-The sequence \g{+1} is a reference to the next capturing subpattern. This kind -of forward reference can be useful it patterns that repeat. Perl does not -support the use of + in this way. +The sequence \g{+1} is a reference to the next capture group. This kind of +forward reference can be useful in patterns that repeat. Perl does not support +the use of + in this way.
-A backreference matches whatever actually matched the capturing subpattern in -the current subject string, rather than anything matching the subpattern -itself (see -"Subpatterns as subroutines" +A backreference matches whatever actually most recently matched the capture +group in the current subject string, rather than anything at all that matches +the group (see +"Groups as subroutines" below for a way of doing that). So the pattern
(sens|respons)e and \1ibility @@ -2262,28 +2293,28 @@ backreference, the case of letters is relevant. For example, ((?i)rah)\s+\1matches "rah rah" and "RAH RAH", but not "RAH rah", even though the original -capturing subpattern is matched caselessly. +capture group is matched caselessly.-There are several different ways of writing backreferences to named -subpatterns. The .NET syntax \k{name} and the Perl syntax \k<name> or -\k'name' are supported, as is the Python syntax (?P=name). Perl 5.10's unified +There are several different ways of writing backreferences to named capture +groups. The .NET syntax \k{name} and the Perl syntax \k<name> or \k'name' +are supported, as is the Python syntax (?P=name). Perl 5.10's unified backreference syntax, in which \g can be used for both numeric and named -references, is also supported. We could rewrite the above example in any of -the following ways: +references, is also supported. We could rewrite the above example in any of the +following ways:
(?<p1>(?i)rah)\s+\k<p1> (?'p1'(?i)rah)\s+\k{p1} (?P<p1>(?i)rah)\s+(?P=p1) (?<p1>(?i)rah)\s+\g{p1}-A subpattern that is referenced by name may appear in the pattern before or +A capture group that is referenced by name may appear in the pattern before or after the reference.-There may be more than one backreference to the same subpattern. If a -subpattern has not actually been used in a particular match, any backreferences -to it always fail by default. For example, the pattern +There may be more than one backreference to the same group. If a group has not +actually been used in a particular match, backreferences to it always fail by +default. For example, the pattern
(a|(bc))\2@@ -2292,12 +2323,11 @@ PCRE2_MATCH_UNSET_BACKREF option is set at compile time, a backreference to an unset value matches an empty string.-Because there may be many capturing parentheses in a pattern, all digits -following a backslash are taken as part of a potential backreference number. -If the pattern continues with a digit character, some delimiter must be used to -terminate the backreference. If the PCRE2_EXTENDED or PCRE2_EXTENDED_MORE -option is set, this can be white space. Otherwise, the \g{ syntax or an empty -comment (see +Because there may be many capture groups in a pattern, all digits following a +backslash are taken as part of a potential backreference number. If the pattern +continues with a digit character, some delimiter must be used to terminate the +backreference. If the PCRE2_EXTENDED or PCRE2_EXTENDED_MORE option is set, this +can be white space. Otherwise, the \g{} syntax or an empty comment (see "Comments" below) can be used.
@@ -2305,19 +2335,18 @@ below) can be used. Recursive backreferences
-A backreference that occurs inside the parentheses to which it refers fails -when the subpattern is first used, so, for example, (a\1) never matches. -However, such references can be useful inside repeated subpatterns. For -example, the pattern +A backreference that occurs inside the group to which it refers fails when the +group is first used, so, for example, (a\1) never matches. However, such +references can be useful inside repeated groups. For example, the pattern
(a|b\1)+matches any number of "a"s and also "aba", "ababbaa" etc. At each iteration of -the subpattern, the backreference matches the character string corresponding -to the previous iteration. In order for this to work, the pattern must be such -that the first iteration does not need to match the backreference. This can be -done using alternation, as in the example above, or by a quantifier with a -minimum of zero. +the group, the backreference matches the character string corresponding to the +previous iteration. In order for this to work, the pattern must be such that +the first iteration does not need to match the backreference. This can be done +using alternation, as in the example above, or by a quantifier with a minimum +of zero.Backreferences of this type cause the group that they reference to be treated @@ -2334,26 +2363,40 @@ coded as \b, \B, \A, \G, \Z, \z, ^ and $ are described above.
-More complicated assertions are coded as subpatterns. There are two kinds: -those that look ahead of the current position in the subject string, and those -that look behind it, and in each case an assertion may be positive (must -succeed for matching to continue) or negative (must not succeed for matching to -continue). An assertion subpattern is matched in the normal way, except that, -when matching continues after a successful assertion, the matching position in -the subject string is as it was before the assertion was processed. +More complicated assertions are coded as parenthesized groups. There are two +kinds: those that look ahead of the current position in the subject string, and +those that look behind it, and in each case an assertion may be positive (must +match for the assertion to be true) or negative (must not match for the +assertion to be true). An assertion group is matched in the normal way, +and if it is true, matching continues after it, but with the matching position +in the subject string reset to what it was before the assertion was processed. +
++The Perl-compatible lookaround assertions are atomic. If an assertion is true, +but there is a subsequent matching failure, there is no backtracking into the +assertion. However, there are some cases where non-atomic assertions can be +useful. PCRE2 has some support for these, described in the section entitled +"Non-atomic assertions" +below, but they are not Perl-compatible. +
++A lookaround assertion may appear as the condition in a +conditional group +(see below). In this case, the result of matching the assertion determines +which branch of the condition is followed.
-Assertion subpatterns are not capturing subpatterns. If an assertion contains -capturing subpatterns within it, these are counted for the purposes of -numbering the capturing subpatterns in the whole pattern. Within each branch of -an assertion, locally captured substrings may be referenced in the usual way. -For example, a sequence such as (.)\g{-1} can be used to check that two -adjacent characters are the same. +Assertion groups are not capture groups. If an assertion contains capture +groups within it, these are counted for the purposes of numbering the capture +groups in the whole pattern. Within each branch of an assertion, locally +captured substrings may be referenced in the usual way. For example, a sequence +such as (.)\g{-1} can be used to check that two adjacent characters are the +same.
When a branch within an assertion fails to match, any substrings that were captured are discarded (as happens with any pattern branch that fails to -match). A negative assertion succeeds only when all its branches fail to match; +match). A negative assertion is true only when all its branches fail to match; this means that no captured substrings are ever retained after a successful negative assertion. When an assertion contains a matching branch, what happens depends on the type of assertion. @@ -2362,25 +2405,25 @@ depends on the type of assertion. For a positive assertion, internally captured substrings in the successful branch are retained, and matching continues with the next pattern item after the assertion. For a negative assertion, a matching branch means that the -assertion has failed. If the assertion is being used as a condition in a -conditional subpattern +assertion is not true. If such an assertion is being used as a condition in a +conditional group (see below), captured substrings are retained, because matching continues with the "no" branch of the condition. For other failing negative assertions, control passes to the previous backtracking point, thus discarding any captured strings within the assertion.
-For compatibility with Perl, most assertion subpatterns may be repeated; though -it makes no sense to assert the same thing several times, the side effect of -capturing parentheses may occasionally be useful. However, an assertion that -forms the condition for a conditional subpattern may not be quantified. In -practice, for other assertions, there only three cases: +For compatibility with Perl, most assertion groups may be repeated; though it +makes no sense to assert the same thing several times, the side effect of +capturing may occasionally be useful. However, an assertion that forms the +condition for a conditional group may not be quantified. In practice, for +other assertions, there only three cases:
(1) If the quantifier is {0}, the assertion is never obeyed during matching. -However, it may contain internal capturing parenthesized groups that are called -from elsewhere via the -subroutine mechanism. +However, it may contain internal capture groups that are called from elsewhere +via the +subroutine mechanism.
(2) If quantifier is {0,n} where n is greater than zero, it is treated as if it @@ -2392,6 +2435,25 @@ without the assertion, the order depending on the greediness of the quantifier. The assertion is obeyed just once when encountered during matching.
+Alphabetic assertion names +
++Traditionally, symbolic sequences such as (?= and (?<= have been used to +specify lookaround assertions. Perl 5.28 introduced some experimental +alphabetic alternatives which might be easier to remember. They all start with +(* instead of (? and must be written using lower case letters. PCRE2 supports +the following synonyms: +
+ (*positive_lookahead: or (*pla: is the same as (?= + (*negative_lookahead: or (*nla: is the same as (?! + (*positive_lookbehind: or (*plb: is the same as (?<= + (*negative_lookbehind: or (*nlb: is the same as (?<! ++For example, (*pla:foo) is the same assertion as (?=foo). In the following +sections, the various assertions are described using the original symbolic +forms. + +
Lookahead assertions
@@ -2473,9 +2535,9 @@ because it makes it impossible to calculate the length of the lookbehind. The permitted in lookbehinds.
-"Subroutine" +"Subroutine" calls (see below) such as (?2) or (?&X) are permitted in lookbehinds, as long -as the subpattern matches a fixed-length string. However, +as the called capture group matches a fixed-length string. However, recursion, that is, a "subroutine" call into a group that is already active, is not supported. @@ -2484,10 +2546,10 @@ is not supported. Perl does not support backreferences in lookbehinds. PCRE2 does support them, but only if certain conditions are met. The PCRE2_MATCH_UNSET_BACKREF option must not be set, there must be no use of (?| in the pattern (it creates -duplicate subpattern numbers), and if the backreference is by name, the name -must be unique. Of course, the referenced subpattern must itself be of fixed -length. The following pattern matches words containing at least two characters -that begin and end with the same character: +duplicate group numbers), and if the backreference is by name, the name +must be unique. Of course, the referenced group must itself match a fixed +length substring. The following pattern matches words containing at least two +characters that begin and end with the same character:
\b(\w)\w++(?<=\1)@@ -2553,13 +2615,130 @@ preceded by "foo", while
+The traditional Perl-compatible lookaround assertions are atomic. That is, if +an assertion is true, but there is a subsequent matching failure, there is no +backtracking into the assertion. However, there are some cases where non-atomic +positive assertions can be useful. PCRE2 provides these using the following +syntax: +
+ (*non_atomic_positive_lookahead: or (*napla: + (*non_atomic_positive_lookbehind: or (*naplb: ++Consider the problem of finding the right-most word in a string that also +appears earlier in the string, that is, it must appear at least twice in total. +This pattern returns the required result as captured substring 1: +
+ ^(?x)(*napla: .* \b(\w++)) (?> .*? \b\1\b ){2}
+
+For a subject such as "word1 word2 word3 word2 word3 word4" the result is
+"word3". How does it work? At the start, ^(?x) anchors the pattern and sets the
+"x" option, which causes white space (introduced for readability) to be
+ignored. Inside the assertion, the greedy .* at first consumes the entire
+string, but then has to backtrack until the rest of the assertion can match a
+word, which is captured by group 1. In other words, when the assertion first
+succeeds, it captures the right-most word in the string.
+
++The current matching point is then reset to the start of the subject, and the +rest of the pattern match checks for two occurrences of the captured word, +using an ungreedy .*? to scan from the left. If this succeeds, we are done, but +if the last word in the string does not occur twice, this part of the pattern +fails. If a traditional atomic lookhead (?= or (*pla: had been used, the +assertion could not be re-entered, and the whole match would fail. The pattern +would succeed only if the very last word in the subject was found twice. +
++Using a non-atomic lookahead, however, means that when the last word does not +occur twice in the string, the lookahead can backtrack and find the second-last +word, and so on, until either the match succeeds, or all words have been +tested. +
++Two conditions must be met for a non-atomic assertion to be useful: the +contents of one or more capturing groups must change after a backtrack into the +assertion, and there must be a backreference to a changed group later in the +pattern. If this is not the case, the rest of the pattern match fails exactly +as before because nothing has changed, so using a non-atomic assertion just +wastes resources. +
++Non-atomic assertions are not supported by the alternative matching function +pcre2_dfa_match(). They are also not supported by JIT (but may be in +future). Note that assertions that appear as conditions for +conditional groups +(see below) must be atomic. +
++In concept, a script run is a sequence of characters that are all from the same +Unicode script such as Latin or Greek. However, because some scripts are +commonly used together, and because some diacritical and other marks are used +with multiple scripts, it is not that simple. There is a full description of +the rules that PCRE2 uses in the section entitled +"Script Runs" +in the +pcre2unicode +documentation. +
++If part of a pattern is enclosed between (*script_run: or (*sr: and a closing +parenthesis, it fails if the sequence of characters that it matches are not a +script run. After a failure, normal backtracking occurs. Script runs can be +used to detect spoofing attacks using characters that look the same, but are +from different scripts. The string "paypal.com" is an infamous example, where +the letters could be a mixture of Latin and Cyrillic. This pattern ensures that +the matched characters in a sequence of non-spaces that follow white space are +a script run: +
+ \s+(*sr:\S+) ++To be sure that they are all from the Latin script (for example), a lookahead +can be used: +
+ \s+(?=\p{Latin})(*sr:\S+)
+
+This works as long as the first character is expected to be a character in that
+script, and not (for example) punctuation, which is allowed with any script. If
+this is not the case, a more creative lookahead is needed. For example, if
+digits, underscore, and dots are permitted at the start:
+
+ \s+(?=[0-9_.]*\p{Latin})(*sr:\S+)
+
+
+
++In many cases, backtracking into a script run pattern fragment is not +desirable. The script run can employ an atomic group to prevent this. Because +this is a common requirement, a shorthand notation is provided by +(*atomic_script_run: or (*asr: +
+ (*asr:...) is the same as (*sr:(?>...)) ++Note that the atomic group is inside the script run. Putting it outside would +not prevent backtracking into the script run pattern. + +
+Support for script runs is not available if PCRE2 is compiled without Unicode +support. A compile-time error is given if any of the above constructs is +encountered. Script runs are not supported by the alternate matching function, +pcre2_dfa_match() because they use the same mechanism as capturing +parentheses. +
++Warning: The (*ACCEPT) control verb +(see below) +should not be used within a script run group, because it causes an immediate +exit from the group, bypassing the script run checking.
--It is possible to cause the matching process to obey a subpattern -conditionally or to choose between two alternative subpatterns, depending on -the result of an assertion, or whether a specific capturing subpattern has -already been matched. The two possible forms of conditional subpattern are: +It is possible to cause the matching process to obey a pattern fragment +conditionally or to choose between two alternative fragments, depending on +the result of an assertion, or whether a specific capture group has +already been matched. The two possible forms of conditional group are:
(?(condition)yes-pattern) (?(condition)yes-pattern|no-pattern) @@ -2567,36 +2746,34 @@ already been matched. The two possible forms of conditional subpattern are: If the condition is satisfied, the yes-pattern is used; otherwise the no-pattern (if present) is used. An absent no-pattern is equivalent to an empty string (it always matches). If there are more than two alternatives in the -subpattern, a compile-time error occurs. Each of the two alternatives may -itself contain nested subpatterns of any form, including conditional -subpatterns; the restriction to two alternatives applies only at the level of -the condition. This pattern fragment is an example where the alternatives are -complex: +group, a compile-time error occurs. Each of the two alternatives may itself +contain nested groups of any form, including conditional groups; the +restriction to two alternatives applies only at the level of the condition +itself. This pattern fragment is an example where the alternatives are complex:(?(1) (A|B|C) | (D | (?(2)E|F) | E) )-There are five kinds of condition: references to subpatterns, references to +There are five kinds of condition: references to capture groups, references to recursion, two pseudo-conditions called DEFINE and VERSION, and assertions.
-Checking for a used subpattern by number +Checking for a used capture group by number
If the text between the parentheses consists of a sequence of digits, the -condition is true if a capturing subpattern of that number has previously -matched. If there is more than one capturing subpattern with the same number -(see the earlier -section about duplicate subpattern numbers), +condition is true if a capture group of that number has previously matched. If +there is more than one capture group with the same number (see the earlier +section about duplicate group numbers), the condition is true if any of them have matched. An alternative notation is -to precede the digits with a plus or minus sign. In this case, the subpattern -number is relative rather than absolute. The most recently opened parentheses -can be referenced by (?(-1), the next most recent by (?(-2), and so on. Inside -loops it can also make sense to refer to subsequent groups. The next -parentheses to be opened can be referenced as (?(+1), and so on. (The value -zero in any of these forms is not used; it provokes a compile-time error.) +to precede the digits with a plus or minus sign. In this case, the group number +is relative rather than absolute. The most recently opened capture group can be +referenced by (?(-1), the next most recent by (?(-2), and so on. Inside loops +it can also make sense to refer to subsequent groups. The next capture group +can be referenced as (?(+1), and so on. (The value zero in any of these forms +is not used; it provokes a compile-time error.)
Consider the following pattern, which contains non-significant white space to @@ -2608,12 +2785,12 @@ three parts for ease of discussion: The first part matches an optional opening parenthesis, and if that character is present, sets it as the first captured substring. The second part matches one or more characters that are not parentheses. The third part is a -conditional subpattern that tests whether or not the first set of parentheses -matched. If they did, that is, if subject started with an opening parenthesis, +conditional group that tests whether or not the first capture group +matched. If it did, that is, if subject started with an opening parenthesis, the condition is true, and so the yes-pattern is executed and a closing parenthesis is required. Otherwise, since no-pattern is not present, the -subpattern matches nothing. In other words, this pattern matches a sequence of -non-parentheses, optionally enclosed in parentheses. +conditional group matches nothing. In other words, this pattern matches a +sequence of non-parentheses, optionally enclosed in parentheses.
If you were embedding this pattern in a larger one, you could use a relative @@ -2624,22 +2801,20 @@ reference: This makes the fragment independent of the parentheses in the larger pattern.
-Checking for a used subpattern by name +Checking for a used capture group by name
Perl uses the syntax (?(<name>)...) or (?('name')...) to test for a used -subpattern by name. For compatibility with earlier versions of PCRE1, which had -this facility before Perl, the syntax (?(name)...) is also recognized. Note, -however, that undelimited names consisting of the letter R followed by digits -are ambiguous (see the following section). -
--Rewriting the above example to use a named subpattern gives this: +capture group by name. For compatibility with earlier versions of PCRE1, which +had this facility before Perl, the syntax (?(name)...) is also recognized. +Note, however, that undelimited names consisting of the letter R followed by +digits are ambiguous (see the following section). Rewriting the above example +to use a named group gives this:
(?<OPEN> \( )? [^()]+ (?(<OPEN>) \) )If the name used in a condition of this kind is a duplicate, the test is -applied to all subpatterns of the same name, and is true if any one of them has +applied to all groups of the same name, and is true if any one of them has matched.
@@ -2651,20 +2826,20 @@ the pattern to another, whether or not it is actually recursive. See the sections entitled "Recursive patterns" and -"Subpatterns as subroutines" -below for details of recursion and subpattern calls. +"Groups as subroutines" +below for details of recursion and subroutine calls.-If a condition is the string (R), and there is no subpattern with the name R, -the condition is true if matching is currently in a recursion or subroutine -call to the whole pattern or any subpattern. If digits follow the letter R, and -there is no subpattern with that name, the condition is true if the most recent -call is into a subpattern with the given number, which must exist somewhere in -the overall pattern. This is a contrived example that is equivalent to a+b: +If a condition is the string (R), and there is no capture group with the name +R, the condition is true if matching is currently in a recursion or subroutine +call to the whole pattern or any capture group. If digits follow the letter R, +and there is no group with that name, the condition is true if the most recent +call is into a group with the given number, which must exist somewhere in the +overall pattern. This is a contrived example that is equivalent to a+b:
((?(R1)a+|(?1)b))-However, in both cases, if there is a subpattern with a matching name, the +However, in both cases, if there is a capture group with a matching name, the condition tests for its being set, as described in the section above, instead of testing for recursion. For example, creating a group with the name R1 by adding (?<R1>) to the above pattern completely changes its meaning. @@ -2674,28 +2849,28 @@ If a name preceded by ampersand follows the letter R, for example:(?(R&name)...)-the condition is true if the most recent recursion is into a subpattern of that -name (which must exist within the pattern). +the condition is true if the most recent recursion is into a group of that name +(which must exist within the pattern).This condition does not check the entire recursion stack. It tests only the current level. If the name used in a condition of this kind is a duplicate, the -test is applied to all subpatterns of the same name, and is true if any one of +test is applied to all groups of the same name, and is true if any one of them is the most recent recursion.
At "top level", all these recursion test conditions are false.
-Defining subpatterns for use by reference only +Defining capture groups for use by reference only
If the condition is the string (DEFINE), the condition is always false, even if there is a group with the name DEFINE. In this case, there may be only one -alternative in the subpattern. It is always skipped if control reaches this -point in the pattern; the idea of DEFINE is that it can be used to define -subroutines that can be referenced from elsewhere. (The use of -subroutines +alternative in the rest of the conditional group. It is always skipped if +control reaches this point in the pattern; the idea of DEFINE is that it can be +used to define subroutines that can be referenced from elsewhere. (The use of +subroutines is described below.) For example, a pattern to match an IPv4 address such as "192.168.23.245" could be written like this (ignore white space and line breaks): @@ -2732,10 +2907,15 @@ than two digits. Assertion conditions
-If the condition is not in any of the above formats, it must be an assertion. -This may be a positive or negative lookahead or lookbehind assertion. Consider -this pattern, again containing non-significant white space, and with the two -alternatives on the second line: +If the condition is not in any of the above formats, it must be a parenthesized +assertion. This may be a positive or negative lookahead or lookbehind +assertion. However, it must be a traditional atomic assertion, not one of the +PCRE2-specific +non-atomic assertions. +
++Consider this pattern, again containing non-significant white space, and with +the two alternatives on the second line:
(?(?=[^a-z]*[a-z]) \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) @@ -2748,18 +2928,18 @@ against the second. This pattern matches strings in one of the two forms dd-aaa-dd or dd-dd-dd, where aaa are letters and dd are digits.the value for the inner capturing parentheses (numbered 2) is "ef", which is -the last value taken on at the top level. If a capturing subpattern is not -matched at the top level, its final captured value is unset, even if it was -(temporarily) set at a deeper level during the matching process. +the last value taken on at the top level. If a capture group is not matched at +the top level, its final captured value is unset, even if it was (temporarily) +set at a deeper level during the matching process.-When an assertion that is a condition contains capturing subpatterns, any +When an assertion that is a condition contains capture groups, any capturing that occurs in a matching branch is retained afterwards, for both positive and negative assertions, because matching always continues after the assertion, whether it succeeds or fails. (Compare non-conditional assertions, -when captures are retained only for positive assertions that succeed.) +for which captures are retained only for positive assertions that succeed.)
-
COMMENTS
+
COMMENTS
There are two ways of including comments in patterns that are processed by PCRE2. In both cases, the start of the comment must not be in a character class, nor in the middle of any other sequence of related characters such as -(?: or a subpattern name or number. The characters that make up a comment play +(?: or a group name or number. The characters that make up a comment play no part in the pattern matching.
@@ -2784,7 +2964,7 @@ a newline in the pattern. The sequence \n is still literal at this stage, so it does not terminate the comment. Only an actual character with the code value 0x0a (the default newline) does so.
-
RECURSIVE PATTERNS
+
RECURSIVE PATTERNS
Consider the problem of matching a string in parentheses, allowing for unlimited nested parentheses. Without the use of recursion, the best that can @@ -2806,14 +2986,14 @@ recursively to the pattern in which it appears.
Obviously, PCRE2 cannot support the interpolation of Perl code. Instead, it supports special syntax for recursion of the entire pattern, and also for -individual subpattern recursion. After its introduction in PCRE1 and Python, +individual capture group recursion. After its introduction in PCRE1 and Python, this kind of recursion was subsequently introduced into Perl at release 5.10.
A special item that consists of (? followed by a number greater than zero and a -closing parenthesis is a recursive subroutine call of the subpattern of the -given number, provided that it occurs inside that subpattern. (If not, it is a -non-recursive subroutine +closing parenthesis is a recursive subroutine call of the capture group of the +given number, provided that it occurs inside that group. (If not, it is a +non-recursive subroutine call, which is described in the next section.) The special item (?R) or (?0) is a recursive call of the entire regular expression.
@@ -2847,13 +3027,13 @@ capturing parentheses leftwards from the point at which it is encountered.Be aware however, that if -duplicate subpattern numbers -are in use, relative references refer to the earliest subpattern with the +duplicate capture group numbers +are in use, relative references refer to the earliest group with the appropriate number. Consider, for example:
(?|(a)|(b)) (c) (?-2)-The first two capturing groups (a) and (b) are both numbered 1, and group (c) +The first two capture groups (a) and (b) are both numbered 1, and group (c) is number 2. When the reference (?-2) is encountered, the second most recently opened parentheses has the number 1, but it is the first such group (the (a) group) to which the recursion refers. This would be the same if an absolute @@ -2861,10 +3041,10 @@ reference (?1) was used. In other words, relative references are just a shorthand for computing a group number.-It is also possible to refer to subsequently opened parentheses, by writing +It is also possible to refer to subsequent capture groups, by writing references such as (?+2). However, these cannot be recursive because the reference is not inside the parentheses that are referenced. They are always -non-recursive subroutine +non-recursive subroutine calls, as described in the next section.
@@ -2874,7 +3054,7 @@ rewrite the above example as follows:
(?<pn> \( ( [^()]++ | (?&pn) )* \) )-If there is more than one subpattern with the same name, the earliest one is +If there is more than one group with the same name, the earliest one is used.@@ -2900,9 +3080,9 @@ documentation). If the pattern above is matched against (ab(cd)ef)
Do not confuse the (?R) item with the condition (R), which tests for recursion. @@ -2912,9 +3092,9 @@ recursing), whereas any characters are permitted at the outer level.
< (?: (?(R) \d++ | [^<>]*+) | (?R)) * >-In this pattern, (?(R) is the start of a conditional subpattern, with two -different alternatives for the recursive and non-recursive cases. The (?R) item -is the actual recursive call. +In this pattern, (?(R) is the start of a conditional group, with two different +alternatives for the recursive and non-recursive cases. The (?R) item is the +actual recursive call.
Differences in recursion processing between PCRE2 and Perl @@ -2924,7 +3104,7 @@ Some former differences between PCRE2 and Perl no longer exist.Before release 10.30, recursion processing in PCRE2 differed from Perl in that -a recursive subpattern call was always treated as an atomic group. That is, +a recursive subroutine call was always treated as an atomic group. That is, once it had matched some of the subject string, it was never re-entered, even if it contained untried alternatives and there was a subsequent matching failure. (Historical note: PCRE implemented recursion before Perl did.) @@ -2960,7 +3140,7 @@ Perl takes so long that you think it has gone into a loop.
Another way in which PCRE2 and Perl used to differ in their recursion processing is in the handling of captured values. Formerly in Perl, when a -subpattern was called recursively or as a subpattern (see the next section), it +group was called recursively or as a subroutine (see the next section), it had no access to any values that were captured outside the recursion, whereas in PCRE2 these values can be referenced. Consider this pattern:
@@ -2971,16 +3151,15 @@ the second group, when the backreference \1 fails to match "b", the second alternative matches "a" and then recurses. In the recursion, \1 does now match "b" and so the whole match succeeds. This match used to fail in Perl, but in later versions (I tried 5.024) it now works. - -This matches "AB", "AAD", or "ACD"; when it matches "AB", "B" is captured by the outer parentheses. + +
SUBPATTERNS AS SUBROUTINES
+ +
GROUPS AS SUBROUTINES
-If the syntax for a recursive subpattern call (either by number or by -name) is used outside the parentheses to which it refers, it operates a bit -like a subroutine in a programming language. More accurately, PCRE2 treats the -referenced subpattern as an independent subpattern which it tries to match at -the current matching position. The called subpattern may be defined before or -after the reference. A numbered reference can be absolute or relative, as in -these examples: +If the syntax for a recursive group call (either by number or by name) is used +outside the parentheses to which it refers, it operates a bit like a subroutine +in a programming language. More accurately, PCRE2 treats the referenced group +as an independent subpattern which it tries to match at the current matching +position. The called group may be defined before or after the reference. A +numbered reference can be absolute or relative, as in these examples:
(...(absolute)...)...(?2)... (...(relative)...)...(?-1)... @@ -3005,28 +3184,28 @@ occur. However, any capturing parentheses that are set during the subroutine call revert to their previous values afterwards.This verb causes the match to end successfully, skipping the remainder of the -pattern. However, when it is inside a subpattern that is called as a -subroutine, only that subpattern is ended successfully. Matching then continues +pattern. However, when it is inside a capture group that is called as a +subroutine, only that group is ended successfully. Matching then continues at the outer level. If (*ACCEPT) in triggered in a positive assertion, the assertion succeeds; in a negative assertion, the assertion fails. @@ -3209,6 +3390,23 @@ example:-Processing options such as case-independence are fixed when a subpattern is +Processing options such as case-independence are fixed when a group is defined, so if it is used as a subroutine, such options cannot be changed for different calls. For example, consider this pattern:
(abc)(?i:(?-1))It matches "abcabc". It does not match "abcABC" because the change of -processing option does not affect the called subpattern. +processing option does not affect the called group.The behaviour of backtracking control verbs -in subpatterns when called as subroutines is described in the section entitled +in groups when called as subroutines is described in the section entitled "Backtracking verbs in subroutines" below.
-
ONIGURUMA SUBROUTINE SYNTAX
+
ONIGURUMA SUBROUTINE SYNTAX
For compatibility with Oniguruma, the non-Perl syntax \g followed by a name or a number enclosed either in angle brackets or single quotes, is an alternative -syntax for referencing a subpattern as a subroutine, possibly recursively. Here -are two of the examples used above, rewritten using this syntax: +syntax for calling a group as a subroutine, possibly recursively. Here are two +of the examples used above, rewritten using this syntax:
(?<pn> \( ( (?>[^()]+) | \g<pn> )* \) ) (sens|respons)e and \g'1'ibility @@ -3039,7 +3218,7 @@ plus or a minus sign it is taken as a relative reference. For example: Note that \g{...} (Perl syntax) and \g<...> (Oniguruma syntax) are not synonymous. The former is a backreference; the latter is a subroutine call. -The doubling is removed before the string is passed to the callout function. -
CALLOUTS
+
CALLOUTS
Perl has a feature whereby using the sequence (?{...}) causes arbitrary Perl code to be obeyed in the middle of matching a regular expression. This makes it @@ -3115,12 +3294,13 @@ example:
BACKTRACKING CONTROL
+
BACKTRACKING CONTROL
There are a number of special "Backtracking Control Verbs" (to use Perl's terminology) that modify the behaviour of backtracking during matching. They are generally of the form (*VERB) or (*VERB:NAME). Some verbs take either form, -possibly behaving differently depending on whether or not a name is present. +and may behave differently depending on whether or not a name argument is +present. The names are not required to be unique within the pattern.
By default, for compatibility with Perl, a name is any sequence of characters @@ -3148,7 +3328,8 @@ PCRE2_ALT_VERBNAMES is also set. The maximum length of a name is 255 in the 8-bit library and 65535 in the 16-bit and 32-bit libraries. If the name is empty, that is, if the closing parenthesis immediately follows the colon, the effect is as if the colon were -not there. Any number of these verbs may occur in a pattern. +not there. Any number of these verbs may occur in a pattern. Except for +(*ACCEPT), they may not be quantified.
Since these verbs are specifically related to backtracking, most of them can be @@ -3162,7 +3343,7 @@ The behaviour of these verbs in repeated groups, assertions, and in -subpatterns called as subroutines +capture groups called as subroutines (whether or not recursively) is documented below.
@@ -3186,7 +3367,7 @@ documentation.Experiments with Perl suggest that it too has similar optimizations, and like PCRE2, turning them off can change the result of a match. -
+
Verbs that act immediately
@@ -3196,8 +3377,8 @@ The following verbs act as soon as they are encountered. (*ACCEPT) or (*ACCEPT:NAME)+(*ACCEPT) is the only backtracking verb that is allowed to be quantified +because an ungreedy quantification with a minimum of zero acts only when a +backtrack happens. Consider, for example, +
+ (A(*ACCEPT)??B)C ++where A, B, and C may be complex expressions. After matching "A", the matcher +processes "BC"; if that fails, causing a backtrack, (*ACCEPT) is triggered and +the match succeeds. In both cases, all but C is captured. Whereas (*COMMIT) +(see below) means "fail on backtrack", a repeated (*ACCEPT) of this type means +"succeed on backtrack". + ++Warning: (*ACCEPT) should not be used within a script run group, because +it causes an immediate exit from the group, bypassing the script run checking.
(*FAIL) or (*FAIL:NAME)@@ -3224,8 +3422,9 @@ A match with the string "aaaa" always fails, but the callout is taken before each backtrack happens (in this example, 10 times).-(*ACCEPT:NAME) and (*FAIL:NAME) behave exactly the same as -(*MARK:NAME)(*ACCEPT) and (*MARK:NAME)(*FAIL), respectively. +(*ACCEPT:NAME) and (*FAIL:NAME) behave the same as (*MARK:NAME)(*ACCEPT) and +(*MARK:NAME)(*FAIL), respectively, that is, a (*MARK) is recorded just before +the verb acts.
Recording which path was taken @@ -3237,27 +3436,25 @@ starting point (see (*SKIP) below).(*MARK:NAME) or (*:NAME)-A name is always required with this verb. There may be as many instances of -(*MARK) as you like in a pattern, and their names do not have to be unique. +A name is always required with this verb. For all the other backtracking +control verbs, a NAME argument is optional.-When a match succeeds, the name of the last-encountered (*MARK:NAME) on the +When a match succeeds, the name of the last-encountered mark name on the matching path is passed back to the caller as described in the section entitled "Other information about the match" in the pcre2api -documentation. This applies to all instances of (*MARK), including those inside -assertions and atomic groups. (There are differences in those cases when -(*MARK) is used in conjunction with (*SKIP) as described below.) +documentation. This applies to all instances of (*MARK) and other verbs, +including those inside assertions and atomic groups. However, there are +differences in those cases when (*MARK) is used in conjunction with (*SKIP) as +described below.
-As well as (*MARK), the (*COMMIT), (*PRUNE) and (*THEN) verbs may have -associated NAME arguments. Whichever is last on the matching path is passed -back. See below for more details of these other verbs. -
--Here is an example of pcre2test output, where the "mark" modifier -requests the retrieval and outputting of (*MARK) data: +The mark name that was last encountered on the matching path is passed back. A +verb without a NAME argument is ignored for this purpose. Here is an example of +pcre2test output, where the "mark" modifier requests the retrieval and +outputting of (*MARK) data:
re> /X(*MARK:A)Y|X(*MARK:B)Z/mark data> XY @@ -3307,7 +3504,7 @@ to the left of the verb. However, when one of these verbs appears inside an atomic group or in a lookaround assertion that is true, its effect is confined to that group, because once the group has been matched, there is never any backtracking into it. Backtracking from beyond an assertion or an atomic group -ignores the entire group, and seeks a preceeding backtracking point. +ignores the entire group, and seeks a preceding backtracking point.These verbs differ in exactly what kind of failure occurs when backtracking @@ -3332,8 +3529,8 @@ dynamic anchor, or "I've started, so I must finish."
The behaviour of (*COMMIT:NAME) is not the same as (*MARK:NAME)(*COMMIT). It is like (*MARK:NAME) in that the name is remembered for passing back to the -caller. However, (*SKIP:NAME) searches only for names set with (*MARK), -ignoring those set by (*COMMIT), (*PRUNE) and (*THEN). +caller. However, (*SKIP:NAME) searches only for names that are set with +(*MARK), ignoring those set by any of the other backtracking verbs.
If there is more than one backtracking verb in a pattern, a different one that @@ -3377,7 +3574,7 @@ as (*COMMIT). The behaviour of (*PRUNE:NAME) is not the same as (*MARK:NAME)(*PRUNE). It is like (*MARK:NAME) in that the name is remembered for passing back to the caller. However, (*SKIP:NAME) searches only for names set with (*MARK), -ignoring those set by (*COMMIT), (*PRUNE) or (*THEN). +ignoring those set by other backtracking verbs.
(*SKIP)@@ -3395,6 +3592,12 @@ next attempt at "c". Note that a possessive quantifer does not have the same effect as this example; although it would suppress backtracking during the first match attempt, the second attempt would start at the second character instead of skipping on to "c". + ++If (*SKIP) is used to specify a new starting position that is the same as the +starting position of the current match, or (by being inside a lookbehind) +earlier, the position specified by (*SKIP) is ignored, and instead the normal +"bumpalong" occurs.
(*SKIP:NAME)@@ -3432,7 +3635,7 @@ the second branch of the pattern.Note that (*SKIP:NAME) searches only for names set by (*MARK:NAME). It ignores -names that are set by (*COMMIT:NAME), (*PRUNE:NAME) or (*THEN:NAME). +names that are set by other backtracking verbs.
(*THEN) or (*THEN:NAME)@@ -3454,34 +3657,32 @@ group. If (*THEN) is not inside an alternation, it acts like (*PRUNE). The behaviour of (*THEN:NAME) is not the same as (*MARK:NAME)(*THEN). It is like (*MARK:NAME) in that the name is remembered for passing back to the caller. However, (*SKIP:NAME) searches only for names set with (*MARK), -ignoring those set by (*COMMIT), (*PRUNE) and (*THEN). +ignoring those set by other backtracking verbs.-A subpattern that does not contain a | character is just a part of the -enclosing alternative; it is not a nested alternation with only one -alternative. The effect of (*THEN) extends beyond such a subpattern to the -enclosing alternative. Consider this pattern, where A, B, etc. are complex -pattern fragments that do not contain any | characters at this level: +A group that does not contain a | character is just a part of the enclosing +alternative; it is not a nested alternation with only one alternative. The +effect of (*THEN) extends beyond such a group to the enclosing alternative. +Consider this pattern, where A, B, etc. are complex pattern fragments that do +not contain any | characters at this level:
A (B(*THEN)C) | DIf A and B are matched, but there is a failure in C, matching does not backtrack into A; instead it moves to the next alternative, that is, D. -However, if the subpattern containing (*THEN) is given an alternative, it +However, if the group containing (*THEN) is given an alternative, it behaves differently:A (B(*THEN)C | (*FAIL)) | D-The effect of (*THEN) is now confined to the inner subpattern. After a failure -in C, matching moves to (*FAIL), which causes the whole subpattern to fail -because there are no more alternatives to try. In this case, matching does now -backtrack into A. +The effect of (*THEN) is now confined to the inner group. After a failure in C, +matching moves to (*FAIL), which causes the whole group to fail because there +are no more alternatives to try. In this case, matching does backtrack into A.-Note that a conditional subpattern is not considered as having two -alternatives, because only one is ever used. In other words, the | character in -a conditional subpattern has a different meaning. Ignoring white space, -consider: +Note that a conditional group is not considered as having two alternatives, +because only one is ever used. In other words, the | character in a conditional +group has a different meaning. Ignoring white space, consider:
^.*? (?(?=a) a | b(*THEN)c )@@ -3489,7 +3690,7 @@ If the subject is "ba", this pattern does not match. Because .*? is ungreedy, it initially matches zero characters. The condition (?=a) then fails, the character "b" is matched, but "c" is not. At this point, matching does not backtrack to .*? as might perhaps be expected from the presence of the | -character. The conditional subpattern is part of the single alternative that +character. The conditional group is part of the single alternative that comprises the whole pattern, and so the match fails. (If there was a backtrack into .*?, allowing it to match "b", the match would succeed.) @@ -3545,14 +3746,14 @@ Backtracking verbs in assertions (*FAIL) in any assertion has its normal effect: it forces an immediate backtrack. The behaviour of the other backtracking verbs depends on whether or not the assertion is standalone or acting as the condition in a conditional -subpattern. +group.(*ACCEPT) in a standalone positive assertion causes the assertion to succeed -without any further processing; captured strings and a (*MARK) name (if set) -are retained. In a standalone negative assertion, (*ACCEPT) causes the -assertion to fail without any further processing; captured substrings and any -(*MARK) name are discarded. +without any further processing; captured strings and a mark name (if set) are +retained. In a standalone negative assertion, (*ACCEPT) causes the assertion to +fail without any further processing; captured substrings and any mark name are +discarded.
If the assertion is a condition, (*ACCEPT) causes the condition to be true for @@ -3561,11 +3762,20 @@ retained in both cases.
The remaining verbs act only when a later failure causes a backtrack to -reach them. This means that their effect is confined to the assertion, -because lookaround assertions are atomic. A backtrack that occurs after an -assertion is complete does not jump back into the assertion. Note in particular -that a (*MARK) name that is set in an assertion is not "seen" by an instance of -(*SKIP:NAME) latter in the pattern. +reach them. This means that, for the Perl-compatible assertions, their effect +is confined to the assertion, because Perl lookaround assertions are atomic. A +backtrack that occurs after such an assertion is complete does not jump back +into the assertion. Note in particular that a (*MARK) name that is set in an +assertion is not "seen" by an instance of (*SKIP:NAME) later in the pattern. +
++PCRE2 now supports non-atomic positive assertions, as described in the section +entitled +"Non-atomic assertions" +above. These assertions must be standalone (not used as conditions). They are +not Perl-compatible. For these assertions, a later backtrack does jump back +into the assertion, and therefore verbs such as (*COMMIT) can be triggered by +backtracks from later in the pattern.
The effect of (*THEN) is not allowed to escape beyond an assertion. If there @@ -3584,36 +3794,35 @@ the assertion to be true, without considering any further alternative branches. Backtracking verbs in subroutines
-These behaviours occur whether or not the subpattern is called recursively. +These behaviours occur whether or not the group is called recursively.
-(*ACCEPT) in a subpattern called as a subroutine causes the subroutine match to +(*ACCEPT) in a group called as a subroutine causes the subroutine match to succeed without any further processing. Matching then continues after the subroutine call. Perl documents this behaviour. Perl's treatment of the other verbs in subroutines is different in some cases.
-(*FAIL) in a subpattern called as a subroutine has its normal effect: it forces +(*FAIL) in a group called as a subroutine has its normal effect: it forces an immediate backtrack.
(*COMMIT), (*SKIP), and (*PRUNE) cause the subroutine match to fail when -triggered by being backtracked to in a subpattern called as a subroutine. There -is then a backtrack at the outer level. +triggered by being backtracked to in a group called as a subroutine. There is +then a backtrack at the outer level.
(*THEN), when triggered, skips to the next alternative in the innermost -enclosing group within the subpattern that has alternatives (its normal -behaviour). However, if there is no such group within the subroutine -subpattern, the subroutine match fails and there is a backtrack at the outer -level. +enclosing group that has alternatives (its normal behaviour). However, if there +is no such group within the subroutine's group, the subroutine match fails and +there is a backtrack at the outer level.
-
SEE ALSO
+
SEE ALSO
pcre2api(3), pcre2callout(3), pcre2matching(3), pcre2syntax(3), pcre2(3).
-
AUTHOR
+
AUTHOR
Philip Hazel
-
@@ -3622,11 +3831,11 @@ University Computing Service Cambridge, England.
REVISION
+
REVISION
-Last updated: 04 September 2018 +Last updated: 29 July 2019
-Copyright © 1997-2018 University of Cambridge. +Copyright © 1997-2019 University of Cambridge.
Return to the PCRE2 index page. diff --git a/doc/html/pcre2perform.html b/doc/html/pcre2perform.html index f823c12..80d716c 100644 --- a/doc/html/pcre2perform.html +++ b/doc/html/pcre2perform.html @@ -31,9 +31,9 @@ of them. Patterns are compiled by PCRE2 into a reasonably efficient interpretive code, so that most simple patterns do not use much memory for storing the compiled version. However, there is one case where the memory usage of a compiled -pattern can be unexpectedly large. If a parenthesized subpattern has a -quantifier with a minimum greater than 1 and/or a limited maximum, the whole -subpattern is repeated in the compiled code. For example, the pattern +pattern can be unexpectedly large. If a parenthesized group has a quantifier +with a minimum greater than 1 and/or a limited maximum, the whole group is +repeated in the compiled code. For example, the pattern
(abc|def){2,4}@@ -252,9 +252,9 @@ Cambridge, England.
REVISION
-Last updated: 25 April 2018 +Last updated: 03 February 2019
-Copyright © 1997-2018 University of Cambridge. +Copyright © 1997-2019 University of Cambridge.
Return to the PCRE2 index page. diff --git a/doc/html/pcre2posix.html b/doc/html/pcre2posix.html index 1da2460..20a2009 100644 --- a/doc/html/pcre2posix.html +++ b/doc/html/pcre2posix.html @@ -15,51 +15,75 @@ please consult the man page, in case the conversion went wrong.
#include <pcre2posix.h>
-int regcomp(regex_t *preg, const char *pattern,
+int pcre2_regcomp(regex_t *preg, const char *pattern,
int cflags);
-int regexec(const regex_t *preg, const char *string,
+int pcre2_regexec(const regex_t *preg, const char *string,
size_t nmatch, regmatch_t pmatch[], int eflags);
-size_t regerror(int errcode, const regex_t *preg,
+size_t pcre2_regerror(int errcode, const regex_t *preg,
char *errbuf, size_t errbuf_size);
-void regfree(regex_t *preg);
+void pcre2_regfree(regex_t *preg);
This set of functions provides a POSIX-style API for the PCRE2 regular -expression 8-bit library. See the +expression 8-bit library. There are no POSIX-style wrappers for PCRE2's 16-bit +and 32-bit libraries. See the pcre2api documentation for a description of PCRE2's native API, which contains much -additional functionality. There are no POSIX-style wrappers for PCRE2's 16-bit -and 32-bit libraries. +additional functionality.
-The functions described here are just wrapper functions that ultimately call -the PCRE2 native API. Their prototypes are defined in the pcre2posix.h -header file, and on Unix systems the library itself is called -libpcre2-posix.a, so can be accessed by adding -lpcre2-posix to the -command for linking an application that uses them. Because the POSIX functions -call the native ones, it is also necessary to add -lpcre2-8. +The functions described here are wrapper functions that ultimately call the +PCRE2 native API. Their prototypes are defined in the pcre2posix.h header +file, and they all have unique names starting with pcre2_. However, the +pcre2posix.h header also contains macro definitions that convert the +standard POSIX names such regcomp() into pcre2_regcomp() etc. This +means that a program can use the usual POSIX names without running the risk of +accidentally linking with POSIX functions from a different library.
+On Unix-like systems the PCRE2 POSIX library is called libpcre2-posix, so +can be accessed by adding -lpcre2-posix to the command for linking an +application. Because the POSIX functions call the native ones, it is also +necessary to add -lpcre2-8. +
++Although they are not defined as protypes in pcre2posix.h, the library +does contain functions with the POSIX names regcomp() etc. These simply +pass their arguments to the PCRE2 functions. These functions are provided for +backwards compatibility with earlier versions of PCRE2, so that existing +programs do not have to be recompiled. +
++Calling the header file pcre2posix.h avoids any conflict with other POSIX +libraries. It can, of course, be renamed or aliased as regex.h, which is +the "correct" name, if there is no clash. It provides two structure types, +regex_t for compiled internal forms, and regmatch_t for returning +captured substrings. It also defines some constants whose names start with +"REG_"; these are used for setting options and identifying error codes. +
+Those POSIX option bits that can reasonably be mapped to PCRE2 native options have been implemented. In addition, the option REG_EXTENDED is defined with the value zero. This has no effect, but since programs that are written to the @@ -80,17 +104,13 @@ POSIX definition; it is not fully POSIX-compatible, and in multi-unit encoding domains it is probably even less compatible.
-The header for these functions is supplied as pcre2posix.h to avoid any -potential clash with other POSIX libraries. It can, of course, be renamed or -aliased as regex.h, which is the "correct" name. It provides two -structure types, regex_t for compiled internal forms, and -regmatch_t for returning captured substrings. It also defines some -constants whose names start with "REG_"; these are used for setting options and -identifying error codes. +The descriptions below use the actual names of the functions, but, as described +above, the standard POSIX names (without the pcre2_ prefix) may also be +used.
--The function regcomp() is called to compile a pattern into an +The function pcre2_regcomp() is called to compile a pattern into an internal form. By default, the pattern is a C string terminated by a binary zero (but see REG_PEND below). The preg argument is a pointer to a regex_t structure that is used as a base for storing information about @@ -128,18 +148,18 @@ REG_UTF. Note that REG_NOSPEC is not part of the POSIX standard.
REG_NOSUB-When a pattern that is compiled with this flag is passed to regexec() for -matching, the nmatch and pmatch arguments are ignored, and no -captured strings are returned. Versions of the PCRE library prior to 10.22 used -to set the PCRE2_NO_AUTO_CAPTURE compile option, but this no longer happens -because it disables the use of backreferences. +When a pattern that is compiled with this flag is passed to +pcre2_regexec() for matching, the nmatch and pmatch arguments +are ignored, and no captured strings are returned. Versions of the PCRE library +prior to 10.22 used to set the PCRE2_NO_AUTO_CAPTURE compile option, but this +no longer happens because it disables the use of backreferences.
REG_PENDIf this option is set, the reg_endp field in the preg structure (which has the type const char *) must be set to point to the character beyond -the end of the pattern before calling regcomp(). The pattern itself may -now contain binary zeros, which are treated as data characters. Without +the end of the pattern before calling pcre2_regcomp(). The pattern itself +may now contain binary zeros, which are treated as data characters. Without REG_PEND, a binary zero terminates the pattern and the re_endp field is ignored. This is a GNU extension to the POSIX standard and should be used with caution in software intended to be portable to other systems. @@ -174,18 +194,19 @@ newlines are matched by the dot metacharacter (they are not) or by a negative class such as [^a] (they are).
-The yield of regcomp() is zero on success, and non-zero otherwise. The -preg structure is filled in on success, and one other member of the +The yield of pcre2_regcomp() is zero on success, and non-zero otherwise. +The preg structure is filled in on success, and one other member of the structure (as well as re_endp) is public: re_nsub contains the number of capturing subpatterns in the regular expression. Various error codes are defined in the header file.
-NOTE: If the yield of regcomp() is non-zero, you must not attempt to -use the contents of the preg structure. If, for example, you pass it to -regexec(), the result is undefined and your program is likely to crash. +NOTE: If the yield of pcre2_regcomp() is non-zero, you must not attempt +to use the contents of the preg structure. If, for example, you pass it +to pcre2_regexec(), the result is undefined and your program is likely to +crash.
-This area is not simple, because POSIX and Perl take different views of things. It is not possible to get PCRE2 to obey POSIX semantics, but then PCRE2 was @@ -219,16 +240,16 @@ is no way to stop newline from matching [^a]. Default POSIX newline handling can be obtained by setting PCRE2_DOTALL and PCRE2_DOLLAR_ENDONLY when calling pcre2_compile() directly, but there is no way to make PCRE2 behave exactly as for the REG_NEWLINE action. When using -the POSIX API, passing REG_NEWLINE to PCRE2's regcomp() function +the POSIX API, passing REG_NEWLINE to PCRE2's pcre2_regcomp() function causes PCRE2_MULTILINE to be passed to pcre2_compile(), and REG_DOTALL passes PCRE2_DOTALL. There is no way to pass PCRE2_DOLLAR_ENDONLY.
--The function regexec() is called to match a compiled pattern preg -against a given string, which is by default terminated by a zero byte -(but see REG_STARTEND below), subject to the options in eflags. These can -be: +The function pcre2_regexec() is called to match a compiled pattern +preg against a given string, which is by default terminated by a +zero byte (but see REG_STARTEND below), subject to the options in eflags. +These can be:
REG_NOTBOL@@ -272,7 +293,7 @@ are mutually exclusive; the error REG_INVARG is returned.
If the pattern was compiled with the REG_NOSUB flag, no data about any matched strings is returned. The nmatch and pmatch arguments of -regexec() are ignored (except possibly as input for REG_STARTEND). +pcre2_regexec() are ignored (except possibly as input for REG_STARTEND).
The value of nmatch may be zero, and the value pmatch may be NULL @@ -294,24 +315,25 @@ array have both structure members set to -1. A successful match yields a zero return; various error codes are defined in the header file, of which REG_NOMATCH is the "expected" failure code.
--The regerror() function maps a non-zero errorcode from either -regcomp() or regexec() to a printable message. If preg is not -NULL, the error should have arisen from the use of that structure. A message -terminated by a binary zero is placed in errbuf. If the buffer is too -short, only the first errbuf_size - 1 characters of the error message are -used. The yield of the function is the size of buffer needed to hold the whole -message, including the terminating zero. This value is greater than -errbuf_size if the message was truncated. +The pcre2_regerror() function maps a non-zero errorcode from either +pcre2_regcomp() or pcre2_regexec() to a printable message. If +preg is not NULL, the error should have arisen from the use of that +structure. A message terminated by a binary zero is placed in errbuf. If +the buffer is too short, only the first errbuf_size - 1 characters of the +error message are used. The yield of the function is the size of buffer needed +to hold the whole message, including the terminating zero. This value is +greater than errbuf_size if the message was truncated.
-Compiling a regular expression causes memory to be allocated and associated -with the preg structure. The function regfree() frees all such -memory, after which preg may no longer be used as a compiled expression. +with the preg structure. The function pcre2_regfree() frees all +such memory, after which preg may no longer be used as a compiled +expression.
-
Philip Hazel
@@ -320,11 +342,11 @@ University Computing Service
Cambridge, England.
-Last updated: 15 June 2017
+Last updated: 30 January 2019
-Copyright © 1997-2017 University of Cambridge.
+Copyright © 1997-2019 University of Cambridge.
Return to the PCRE2 index page. diff --git a/doc/html/pcre2syntax.html b/doc/html/pcre2syntax.html index 7d332a1..00f0513 100644 --- a/doc/html/pcre2syntax.html +++ b/doc/html/pcre2syntax.html @@ -32,14 +32,16 @@ please consult the man page, in case the conversion went wrong.
@@ -57,7 +59,8 @@ documentation. This document contains a quick-reference summary of the syntax.
-This table applies to ASCII and Unicode environments. +This table applies to ASCII and Unicode environments. An unrecognized escape +sequence causes an error.
\a alarm, that is, the BEL character (hex 07)
\cx "control-x", where x is any ASCII printing character
@@ -69,12 +72,25 @@ This table applies to ASCII and Unicode environments.
\0dd character with octal code 0dd
\ddd character with octal code ddd, or backreference
\o{ddd..} character with octal code ddd..
- \U "U" if PCRE2_ALT_BSUX is set (otherwise is an error)
\N{U+hh..} character with Unicode code point hh.. (Unicode mode only)
- \uhhhh character with hex code hhhh (if PCRE2_ALT_BSUX is set)
\xhh character with hex code hh
\x{hh..} character with hex code hh..
+If PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX is set ("ALT_BSUX mode"), the
+following are also recognized:
+
+ \U the character "U"
+ \uhhhh character with hex code hhhh
+ \u{hh..} character with hex code hh.. but only for EXTRA_ALT_BSUX
+
+When \x is not followed by {, from zero to two hexadecimal digits are read,
+but in ALT_BSUX mode \x must be followed by two hexadecimal digits to be
+recognized as a hexadecimal escape; otherwise it matches a literal "x".
+Likewise, if \u (in ALT_BSUX mode) is not followed by four hexadecimal digits
+or (in EXTRA_ALT_BSUX mode) a sequence of hex digits in curly brackets, it
+matches a literal "u".
+
+Note that \0dd is always an octal code. The treatment of backslash followed by a non-zero digit is complicated; for details see the section "Non-printing characters" @@ -85,13 +101,6 @@ also given. \N{U+hh..} is synonymous with \x{hh..} in PCRE2 but is not supported in EBCDIC environments. Note that \N not followed by an opening curly bracket has a different meaning (see below).
--When \x is not followed by {, from zero to two hexadecimal digits are read, -but if PCRE2_ALT_BSUX is set, \x must be followed by two hexadecimal digits to -be recognized as a hexadecimal escape; otherwise it matches a literal "x". -Likewise, if \u (in ALT_BSUX mode) is not followed by four hexadecimal digits, -it matches a literal "u". -
@@ -225,6 +234,7 @@ Dogra, Duployan, Egyptian_Hieroglyphs, Elbasan, +Elymaic, Ethiopic, Georgian, Glagolitic, @@ -282,10 +292,12 @@ Mro, Multani, Myanmar, Nabataean, +Nandinagari, New_Tai_Lue, Newa, Nko, Nushu, +Nyakeng_Puachue_Hmong, Ogham, Ol_Chiki, Old_Hungarian, @@ -336,6 +348,7 @@ Tifinagh, Tirhuta, Ugaritic, Vai, +Wancho, Warang_Citi, Yi, Zanabazar_Square. @@ -423,19 +436,23 @@ but some of them use Unicode properties if PCRE2_UCP is set. You can use+In non-UTF modes, names may contain underscores and ASCII letters and digits; +in UTF modes, any Unicode letters and Unicode decimal digits are permitted. In +both cases, a name must not start with a digit.
CAPTURING
- (...) capturing group - (?<name>...) named capturing group (Perl) - (?'name'...) named capturing group (Perl) - (?P<name>...) named capturing group (Python) - (?:...) non-capturing group - (?|...) non-capturing group; reset group numbers for - capturing groups in each alternative -+ (...) capture group + (?<name>...) named capture group (Perl) + (?'name'...) named capture group (Perl) + (?P<name>...) named capture group (Python) + (?:...) non-capture group + (?|...) non-capture group; reset group numbers for + capture groups in each alternative +
- (?>...) atomic, non-capturing group + (?>...) atomic non-capture group + (*atomic:...) atomic non-capture group
@@ -514,14 +531,46 @@ setting with a similar syntax.
LOOKAHEAD AND LOOKBEHIND ASSERTIONS
- (?=...) positive look ahead - (?!...) negative look ahead - (?<=...) positive look behind - (?<!...) negative look behind + (?=...) ) + (*pla:...) ) positive lookahead + (*positive_lookahead:...) ) + + (?!...) ) + (*nla:...) ) negative lookahead + (*negative_lookahead:...) ) + + (?<=...) ) + (*plb:...) ) positive lookbehind + (*positive_lookbehind:...) ) + + (?<!...) ) + (*nlb:...) ) negative lookbehind + (*negative_lookbehind:...) )-Each top-level branch of a look behind must be of a fixed length. +Each top-level branch of a lookbehind must be of a fixed length. + +
+These assertions are specific to PCRE2 and are not Perl-compatible. +
+ (*napla:...) + (*non_atomic_positive_lookahead:...) + + (*naplb:...) + (*non_atomic_positive_lookbehind:...) ++ +
+
+ (*script_run:...) ) script run, can be backtracked into + (*sr:...) ) + + (*atomic_script_run:...) ) atomic script run + (*asr:...) ) +-
\n reference by number (can be ambiguous) @@ -538,26 +587,26 @@ Each top-level branch of a look behind must be of a fixed length. (?P=name) reference by name (Python)-
(?R) recurse whole pattern - (?n) call subpattern by absolute number - (?+n) call subpattern by relative number - (?-n) call subpattern by relative number - (?&name) call subpattern by name (Perl) - (?P>name) call subpattern by name (Python) - \g<name> call subpattern by name (Oniguruma) - \g'name' call subpattern by name (Oniguruma) - \g<n> call subpattern by absolute number (Oniguruma) - \g'n' call subpattern by absolute number (Oniguruma) - \g<+n> call subpattern by relative number (PCRE2 extension) - \g'+n' call subpattern by relative number (PCRE2 extension) - \g<-n> call subpattern by relative number (PCRE2 extension) - \g'-n' call subpattern by relative number (PCRE2 extension) + (?n) call subroutine by absolute number + (?+n) call subroutine by relative number + (?-n) call subroutine by relative number + (?&name) call subroutine by name (Perl) + (?P>name) call subroutine by name (Python) + \g<name> call subroutine by name (Oniguruma) + \g'name' call subroutine by name (Oniguruma) + \g<n> call subroutine by absolute number (Oniguruma) + \g'n' call subroutine by absolute number (Oniguruma) + \g<+n> call subroutine by relative number (PCRE2 extension) + \g'+n' call subroutine by relative number (PCRE2 extension) + \g<-n> call subroutine by relative number (PCRE2 extension) + \g'-n' call subroutine by relative number (PCRE2 extension)-
(?(condition)yes-pattern) @@ -572,7 +621,7 @@ Each top-level branch of a look behind must be of a fixed length. (?(R) overall recursion condition (?(Rn) specific numbered group recursion condition (?(R&name) specific named group recursion condition - (?(DEFINE) define subpattern for reference + (?(DEFINE) define groups for reference (?(VERSION[>]=n.m) test PCRE2 version (?(assert) assertion condition@@ -580,7 +629,7 @@ Note the ambiguity of (?(R) and (?(Rn) which might be named reference conditions or recursion tests. Such a condition is interpreted as a reference condition if the relevant named group exists. -
All backtracking control verbs may be in the form (*VERB:NAME). For (*MARK) the name is mandatory, for the others it is optional. (*SKIP) changes its behaviour @@ -607,7 +656,7 @@ pattern is not anchored. The effect of one of these verbs in a group called as a subroutine is confined to the subroutine call.
-
(?C) callout (assumed number 0)
@@ -618,12 +667,12 @@ The allowed string delimiters are ` ' " ^ % # $ (which are the same for the
start and the end), and the starting delimiter { matched with the ending
delimiter }. To encode the ending delimiter within the string, double it.
-
SEE ALSO
+
SEE ALSO
pcre2pattern(3), pcre2api(3), pcre2callout(3),
pcre2matching(3), pcre2(3).
-
AUTHOR
+
AUTHOR
Philip Hazel
@@ -632,11 +681,11 @@ University Computing Service
Cambridge, England.
-
REVISION
+
REVISION
-Last updated: 02 September 2018
+Last updated: 29 July 2019
-Copyright © 1997-2018 University of Cambridge.
+Copyright © 1997-2019 University of Cambridge.
Return to the PCRE2 index page.
diff --git a/doc/html/pcre2test.html b/doc/html/pcre2test.html
index af2b18c..e387315 100644
--- a/doc/html/pcre2test.html
+++ b/doc/html/pcre2test.html
@@ -242,10 +242,17 @@ Behave as if each pattern line has the jit modifier; after successful
compilation, each pattern is passed to the just-in-time compiler, if available.
+-jitfast
+Behave as if each pattern line has the jitfast modifier; after
+successful compilation, each pattern is passed to the just-in-time compiler, if
+available, and each subject line is passed directly to the JIT matcher via its
+"fast path".
+
+
-jitverify
Behave as if each pattern line has the jitverify modifier; after
successful compilation, each pattern is passed to the just-in-time compiler, if
-available, and the use of JIT is verified.
+available, and the use of JIT for matching is verified.
-LM
@@ -606,11 +613,14 @@ for a description of the effects of these options.
/s dotall set PCRE2_DOTALL
dupnames set PCRE2_DUPNAMES
endanchored set PCRE2_ENDANCHORED
+ escaped_cr_is_lf set PCRE2_EXTRA_ESCAPED_CR_IS_LF
/x extended set PCRE2_EXTENDED
/xx extended_more set PCRE2_EXTENDED_MORE
+ extra_alt_bsux set PCRE2_EXTRA_ALT_BSUX
firstline set PCRE2_FIRSTLINE
literal set PCRE2_LITERAL
match_line set PCRE2_EXTRA_MATCH_LINE
+ match_invalid_utf set PCRE2_MATCH_INVALID_UTF
match_unset_backref set PCRE2_MATCH_UNSET_BACKREF
match_word set PCRE2_EXTRA_MATCH_WORD
/m multiline set PCRE2_MULTILINE
@@ -715,14 +725,14 @@ information is obtained from the pcre2_pattern_info() function. Here are
some typical examples:
re> /(?i)(^a|^b)/m,info
- Capturing subpattern count = 1
+ Capture group count = 1
Compile options: multiline
Overall options: caseless multiline
First code unit at start or follows newline
Subject length lower bound = 1
re> /(?i)abc/info
- Capturing subpattern count = 0
+ Capture group count = 0
Compile options: <none>
Overall options: caseless
First code unit = 'a' (caseless)
@@ -736,7 +746,9 @@ options, the line is omitted. "First code unit" is where any match must start;
if there is more than one they are listed as "starting code units". "Last code
unit" is the last literal code unit that must be present in any match. This is
not necessarily the last character. These lines are omitted if no starting or
-ending code units are recorded.
+ending code units are recorded. The subject length line is omitted when
+no_start_optimize is set because the minimum length is not calculated
+when it can never be used.
The framesize modifier shows the size, in bytes, of the storage frames
@@ -1041,6 +1053,7 @@ process.
aftertext show text after match
allaftertext show text after captures
allcaptures show all captures
+ allvector show the entire ovector
allusedtext show all consulted text
altglobal alternative global matching
/g global global matching
@@ -1048,8 +1061,11 @@ process.
mark show mark values
replace=<string> specify a replacement string
startchar show starting character when relevant
+ substitute_callout use substitution callouts
substitute_extended use PCRE2_SUBSTITUTE_EXTENDED
+ substitute_skip=<n> skip substitution number n
substitute_overflow_length use PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+ substitute_stop=<n> skip substitution number n and greater
substitute_unknown_unset use PCRE2_SUBSTITUTE_UNKNOWN_UNSET
substitute_unset_empty use PCRE2_SUBSTITUTE_UNSET_EMPTY
@@ -1185,6 +1201,7 @@ pattern.
aftertext show text after match
allaftertext show text after captures
allcaptures show all captures
+ allvector show the entire ovector
allusedtext show all consulted text (non-JIT only)
altglobal alternative global matching
callout_capture show captures at callout time
@@ -1214,8 +1231,11 @@ pattern.
replace=<string> specify a replacement string
startchar show startchar when relevant
startoffset=<n> same as offset=<n>
+ substitute_callout use substitution callouts
substitute_extedded use PCRE2_SUBSTITUTE_EXTENDED
+ substitute_skip=<n> skip substitution number n
substitute_overflow_length use PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+ substitute_stop=<n> skip substitution number n and greater
substitute_unknown_unset use PCRE2_SUBSTITUTE_UNKNOWN_UNSET
substitute_unset_empty use PCRE2_SUBSTITUTE_UNSET_EMPTY
zero_terminate pass the subject as zero-terminated
@@ -1239,22 +1259,27 @@ following line with a plus character following the capture number.
The allusedtext modifier requests that all the text that was consulted
-during a successful pattern match by the interpreter should be shown. This
-feature is not supported for JIT matching, and if requested with JIT it is
-ignored (with a warning message). Setting this modifier affects the output if
-there is a lookbehind at the start of a match, or a lookahead at the end, or if
-\K is used in the pattern. Characters that precede or follow the start and end
-of the actual match are indicated in the output by '<' or '>' characters
-underneath them. Here is an example:
+during a successful pattern match by the interpreter should be shown, for both
+full and partial matches. This feature is not supported for JIT matching, and
+if requested with JIT it is ignored (with a warning message). Setting this
+modifier affects the output if there is a lookbehind at the start of a match,
+or, for a complete match, a lookahead at the end, or if \K is used in the
+pattern. Characters that precede or follow the start and end of the actual
+match are indicated in the output by '<' or '>' characters underneath them.
+Here is an example:
re> /(?<=pqr)abc(?=xyz)/
data> 123pqrabcxyz456\=allusedtext
0: pqrabcxyz
<<< >>>
+ data> 123pqrabcxy\=ph,allusedtext
+ Partial match: pqrabcxy
+ <<<
-This shows that the matched string is "abc", with the preceding and following
-strings "pqr" and "xyz" having been consulted during the match (when processing
-the assertions).
+The first, complete match shows that the matched string is "abc", with the
+preceding and following strings "pqr" and "xyz" having been consulted during
+the match (when processing the assertions). The partial match can indicate only
+the preceding string.
The startchar modifier requests that the starting character for the match
@@ -1281,10 +1306,28 @@ captured parentheses be output after a match. By default, only those up to the
highest one actually used in the match are output (corresponding to the return
code from pcre2_match()). Groups that did not take part in the match
are output as "<unset>". This modifier is not relevant for DFA matching (which
-does no capturing); it is ignored, with a warning message, if present.
+does no capturing) and does not apply when replace is specified; it is
+ignored, with a warning message, if present.
+
+
+Showing the entire ovector, for all outcomes
+
+
+The allvector modifier requests that the entire ovector be shown,
+whatever the outcome of the match. Compare allcaptures, which shows only
+up to the maximum number of capture groups for the pattern, and then only for a
+successful complete non-DFA match. This modifier, which acts after any match
+result, and also for DFA matching, provides a means of checking that there are
+no unexpected modifications to ovector fields. Before each match attempt, the
+ovector is filled with a special value, and if this is found in both elements
+of a capturing pair, "<unchanged>" is output. After a successful match, this
+applies to all groups after the maximum capture group for the pattern. In other
+cases it applies to the entire ovector. After a partial match, the first two
+elements are the only ones that should be set. After a DFA match, the amount of
+ovector that is used depends on the number of matches that were found.
-Testing callouts
+Testing pattern callouts
A callout function is supplied when pcre2test calls the library matching
@@ -1292,6 +1335,9 @@ functions, unless callout_none is specified. Its behaviour can be
controlled by various modifiers listed above whose names begin with
callout_. Details are given in the section entitled "Callouts"
below.
+Testing callouts from pcre2_substitute() is decribed separately in
+"Testing the substitution function"
+below.
Finding all matches in a string
@@ -1323,8 +1369,8 @@ Testing substring extraction functions
The copy and get modifiers can be used to test the
pcre2_substring_copy_xxx() and pcre2_substring_get_xxx() functions.
-They can be given more than once, and each can specify a group name or number,
-for example:
+They can be given more than once, and each can specify a capture group name or
+number, for example:
abcd\=copy=1,copy=3,get=G1
@@ -1343,7 +1389,7 @@ instead of a colon. This is in addition to the normal full list. The string
length (that is, the return from the extraction function) is given in
parentheses after each substring, followed by the name when the extraction was
by name.
-
+
Testing the substitution function
@@ -1401,10 +1447,10 @@ The default action of pcre2_substitute() is to return
PCRE2_ERROR_NOMEMORY when the output buffer is too small. However, if the
PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option is set (by using the
substitute_overflow_length modifier), pcre2_substitute() continues
-to go through the motions of matching and substituting, in order to compute the
-size of buffer that is required. When this happens, pcre2test shows the
-required buffer length (which includes space for the trailing zero) as part of
-the error message. For example:
+to go through the motions of matching and substituting (but not doing any
+callouts), in order to compute the size of buffer that is required. When this
+happens, pcre2test shows the required buffer length (which includes space
+for the trailing zero) as part of the error message. For example:
/abc/substitute_overflow_length
123abc123\=replace=[9]XYZ
@@ -1415,6 +1461,49 @@ matching provokes an error return ("bad option value") from
pcre2_substitute().
+Testing substitute callouts
+
+
+If the substitute_callout modifier is set, a substitution callout
+function is set up. The null_context modifier must not be set, because
+the address of the callout function is passed in a match context. When the
+callout function is called (after each substitution), details of the the input
+and output strings are output. For example:
+
+ /abc/g,replace=<$0>,substitute_callout
+ abcdefabcpqr
+ 1(1) Old 0 3 "abc" New 0 5 "<abc>"
+ 2(1) Old 6 9 "abc" New 8 13 "<abc>"
+ 2: <abc>def<abc>pqr
+
+The first number on each callout line is the count of matches. The
+parenthesized number is the number of pairs that are set in the ovector (that
+is, one more than the number of capturing groups that were set). Then are
+listed the offsets of the old substring, its contents, and the same for the
+replacement.
+
+
+By default, the substitution callout function returns zero, which accepts the
+replacement and causes matching to continue if /g was used. Two further
+modifiers can be used to test other return values. If substitute_skip is
+set to a value greater than zero the callout function returns +1 for the match
+of that number, and similarly substitute_stop returns -1. These cause the
+replacement to be rejected, and -1 causes no further matching to take place. If
+either of them are set, substitute_callout is assumed. For example:
+
+ /abc/g,replace=<$0>,substitute_skip=1
+ abcdefabcpqr
+ 1(1) Old 0 3 "abc" New 0 5 "<abc> SKIPPED"
+ 2(1) Old 6 9 "abc" New 6 11 "<abc>"
+ 2: abcdef<abc>pqr
+ abcdefabcpqr\=substitute_stop=1
+ 1(1) Old 0 3 "abc" New 0 5 "<abc> STOPPED"
+ 1: abcdefabcpqr
+
+If both are set for the same number, stop takes precedence. Only a single skip
+or stop is supported, which is sufficient for testing that the feature works.
+
+
Setting the JIT stack size
@@ -1554,11 +1643,11 @@ Passing a NULL context
Normally, pcre2test passes a context block to pcre2_match(),
-pcre2_dfa_match() or pcre2_jit_match(). If the null_context
-modifier is set, however, NULL is passed. This is for testing that the matching
-functions behave correctly in this case (they use default values). This
-modifier cannot be used with the find_limits modifier or when testing the
-substitution function.
+pcre2_dfa_match(), pcre2_jit_match() or pcre2_substitute().
+If the null_context modifier is set, however, NULL is passed. This is for
+testing that the matching and substitution functions behave correctly in this
+case (they use default values). This modifier cannot be used with the
+find_limits or substitute_callout modifiers.
THE ALTERNATIVE MATCHING FUNCTION
@@ -1705,7 +1794,7 @@ restart the match with additional subject data by means of the
dfa_restart modifier. For example:
re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
- data> 23ja\=P,dfa
+ data> 23ja\=ps,dfa
Partial match: 23ja
data> n05\=dfa,dfa_restart
0: n05
@@ -2004,9 +2093,9 @@ Cambridge, England.
REVISION
-Last updated: 21 July 2018
+Last updated: 30 July 2019
-Copyright © 1997-2018 University of Cambridge.
+Copyright © 1997-2019 University of Cambridge.
Return to the PCRE2 index page.
diff --git a/doc/html/pcre2unicode.html b/doc/html/pcre2unicode.html
index 24f6d93..3d4e6b4 100644
--- a/doc/html/pcre2unicode.html
+++ b/doc/html/pcre2unicode.html
@@ -16,32 +16,44 @@ please consult the man page, in case the conversion went wrong.
UNICODE AND UTF SUPPORT
-When PCRE2 is built with Unicode support (which is the default), it has
-knowledge of Unicode character properties and can process text strings in
-UTF-8, UTF-16, or UTF-32 format (depending on the code unit width). However, by
-default, PCRE2 assumes that one code unit is one character. To process a
-pattern as a UTF string, where a character may require more than one code unit,
-you must call
+PCRE2 is normally built with Unicode support, though if you do not need it, you
+can build it without, in which case the library will be smaller. With Unicode
+support, PCRE2 has knowledge of Unicode character properties and can process
+text strings in UTF-8, UTF-16, or UTF-32 format (depending on the code unit
+width), but this is not the default. Unless specifically requested, PCRE2
+treats each code unit in a string as one character.
+
+
+There are two ways of telling PCRE2 to switch to UTF mode, where characters may
+consist of more than one code unit and the range of values is constrained. The
+program can call
pcre2_compile()
-with the PCRE2_UTF option flag, or the pattern must start with the sequence
-(*UTF). When either of these is the case, both the pattern and any subject
-strings that are matched against it are treated as UTF strings instead of
-strings of individual one-code-unit characters. There are also some other
-changes to the way characters are handled, as documented below.
+with the PCRE2_UTF option, or the pattern may start with the sequence (*UTF).
+However, the latter facility can be locked out by the PCRE2_NEVER_UTF option.
+That is, the programmer can prevent the supplier of the pattern from switching
+to UTF mode.
+
+
+Note that the PCRE2_MATCH_INVALID_UTF option (see
+below)
+forces PCRE2_UTF to be set.
-If you do not need Unicode support you can build PCRE2 without it, in which
-case the library will be smaller.
+In UTF mode, both the pattern and any subject strings that are matched against
+it are treated as UTF strings instead of strings of individual one-code-unit
+characters. There are also some other changes to the way characters are
+handled, as documented below.
UNICODE PROPERTY SUPPORT
When PCRE2 is built with Unicode support, the escape sequences \p{..},
-\P{..}, and \X can be used. The Unicode properties that can be tested are
-limited to the general category properties such as Lu for an upper case letter
-or Nd for a decimal number, the Unicode script names such as Arabic or Han, and
-the derived properties Any and L&. Full lists are given in the
+\P{..}, and \X can be used. This is not dependent on the PCRE2_UTF setting.
+The Unicode properties that can be tested are limited to the general category
+properties such as Lu for an upper case letter or Nd for a decimal number, the
+Unicode script names such as Arabic or Han, and the derived properties Any and
+L&. Full lists are given in the
pcre2pattern
and
pcre2syntax
@@ -62,22 +74,28 @@ also recognized; larger ones can be coded using \o{...}.
The escape sequence \N{U+<hex digits>} is recognized as another way of
specifying a Unicode character by code point in a UTF mode. It is not allowed
-in non-UTF modes.
+in non-UTF mode.
-In UTF modes, repeat quantifiers apply to complete UTF characters, not to
+In UTF mode, repeat quantifiers apply to complete UTF characters, not to
individual code units.
-In UTF modes, the dot metacharacter matches one UTF character instead of a
+In UTF mode, the dot metacharacter matches one UTF character instead of a
single code unit.
-The escape sequence \C can be used to match a single code unit in a UTF mode,
+In UTF mode, capture group names are not restricted to ASCII, and may contain
+any Unicode letters and decimal digits, as well as underscore.
+
+
+The escape sequence \C can be used to match a single code unit in UTF mode,
but its use can lead to some strange effects because it breaks up multi-unit
characters (see the description of \C in the
pcre2pattern
-documentation).
+documentation). For this reason, there is a build-time option that disables
+support for \C completely. There is also a less draconian compile-time option
+for locking out the use of \C when a pattern is compiled.
The use of \C is not supported by the alternative matching function
@@ -86,7 +104,7 @@ may consist of more than one code unit. The use of \C in these modes provokes
a match-time error. Also, the JIT optimization does not support \C in these
modes. If JIT optimization is requested for a UTF-8 or UTF-16 pattern that
contains \C, it will not succeed, and so when pcre2_match() is called,
-the matching will be carried out by the normal interpretive function.
+the matching will be carried out by the interpretive function.
The character escapes \b, \B, \d, \D, \s, \S, \w, and \W correctly test
@@ -116,25 +134,157 @@ However, the special horizontal and vertical white space matching escapes (\h,
not PCRE2_UCP is set.
-CASE-EQUIVALENCE IN UTF MODES
+CASE-EQUIVALENCE IN UTF MODE
-Case-insensitive matching in a UTF mode makes use of Unicode properties except
+Case-insensitive matching in UTF mode makes use of Unicode properties except
for characters whose code points are less than 128 and that have at most two
case-equivalent values. For these, a direct table lookup is used for speed. A
few Unicode characters such as Greek sigma have more than two code points that
-are case-equivalent, and these are treated as such.
+are case-equivalent, and these are treated specially.
+
+
+SCRIPT RUNS
+
+
+The pattern constructs (*script_run:...) and (*atomic_script_run:...), with
+synonyms (*sr:...) and (*asr:...), verify that the string matched within the
+parentheses is a script run. In concept, a script run is a sequence of
+characters that are all from the same Unicode script. However, because some
+scripts are commonly used together, and because some diacritical and other
+marks are used with multiple scripts, it is not that simple.
+
+
+Every Unicode character has a Script property, mostly with a value
+corresponding to the name of a script, such as Latin, Greek, or Cyrillic. There
+are also three special values:
+
+
+"Unknown" is used for code points that have not been assigned, and also for the
+surrogate code points. In the PCRE2 32-bit library, characters whose code
+points are greater than the Unicode maximum (U+10FFFF), which are accessible
+only in non-UTF mode, are assigned the Unknown script.
+
+
+"Common" is used for characters that are used with many scripts. These include
+punctuation, emoji, mathematical, musical, and currency symbols, and the ASCII
+digits 0 to 9.
+
+
+"Inherited" is used for characters such as diacritical marks that modify a
+previous character. These are considered to take on the script of the character
+that they modify.
+
+
+Some Inherited characters are used with many scripts, but many of them are only
+normally used with a small number of scripts. For example, U+102E0 (Coptic
+Epact thousands mark) is used only with Arabic and Coptic. In order to make it
+possible to check this, a Unicode property called Script Extension exists. Its
+value is a list of scripts that apply to the character. For the majority of
+characters, the list contains just one script, the same one as the Script
+property. However, for characters such as U+102E0 more than one Script is
+listed. There are also some Common characters that have a single, non-Common
+script in their Script Extension list.
+
+
+The next section describes the basic rules for deciding whether a given string
+of characters is a script run. Note, however, that there are some special cases
+involving the Chinese Han script, and an additional constraint for decimal
+digits. These are covered in subsequent sections.
+
+
+Basic script run rules
+
+
+A string that is less than two characters long is a script run. This is the
+only case in which an Unknown character can be part of a script run. Longer
+strings are checked using only the Script Extensions property, not the basic
+Script property.
+
+
+If a character's Script Extension property is the single value "Inherited", it
+is always accepted as part of a script run. This is also true for the property
+"Common", subject to the checking of decimal digits described below. All the
+remaining characters in a script run must have at least one script in common in
+their Script Extension lists. In set-theoretic terminology, the intersection of
+all the sets of scripts must not be empty.
+
+
+A simple example is an Internet name such as "google.com". The letters are all
+in the Latin script, and the dot is Common, so this string is a script run.
+However, the Cyrillic letter "o" looks exactly the same as the Latin "o"; a
+string that looks the same, but with Cyrillic "o"s is not a script run.
+
+
+More interesting examples involve characters with more than one script in their
+Script Extension. Consider the following characters:
+
+ U+060C Arabic comma
+ U+06D4 Arabic full stop
+
+The first has the Script Extension list Arabic, Hanifi Rohingya, Syriac, and
+Thaana; the second has just Arabic and Hanifi Rohingya. Both of them could
+appear in script runs of either Arabic or Hanifi Rohingya. The first could also
+appear in Syriac or Thaana script runs, but the second could not.
+
+
+The Chinese Han script
+
+
+The Chinese Han script is commonly used in conjunction with other scripts for
+writing certain languages. Japanese uses the Hiragana and Katakana scripts
+together with Han; Korean uses Hangul and Han; Taiwanese Mandarin uses Bopomofo
+and Han. These three combinations are treated as special cases when checking
+script runs and are, in effect, "virtual scripts". Thus, a script run may
+contain a mixture of Hiragana, Katakana, and Han, or a mixture of Hangul and
+Han, or a mixture of Bopomofo and Han, but not, for example, a mixture of
+Hangul and Bopomofo and Han. PCRE2 (like Perl) follows Unicode's Technical
+Standard 39 ("Unicode Security Mechanisms", http://unicode.org/reports/tr39/)
+in allowing such mixtures.
+
+
+Decimal digits
+
+
+Unicode contains many sets of 10 decimal digits in different scripts, and some
+scripts (including the Common script) contain more than one set. Some of these
+decimal digits them are visually indistinguishable from the common ASCII
+digits. In addition to the script checking described above, if a script run
+contains any decimal digits, they must all come from the same set of 10
+adjacent characters.
VALIDITY OF UTF STRINGS
When the PCRE2_UTF option is set, the strings passed as patterns and subjects
-are (by default) checked for validity on entry to the relevant functions.
-If an invalid UTF string is passed, an negative error code is returned. The
-code unit offset to the offending character can be extracted from the match
-data block by calling pcre2_get_startchar(), which is used for this
-purpose after a UTF error.
+are (by default) checked for validity on entry to the relevant functions. If an
+invalid UTF string is passed, a negative error code is returned. The code unit
+offset to the offending character can be extracted from the match data block by
+calling pcre2_get_startchar(), which is used for this purpose after a UTF
+error.
+
+
+In some situations, you may already know that your strings are valid, and
+therefore want to skip these checks in order to improve performance, for
+example in the case of a long subject string that is being scanned repeatedly.
+If you set the PCRE2_NO_UTF_CHECK option at compile time or at match time,
+PCRE2 assumes that the pattern or subject it is given (respectively) contains
+only valid UTF code unit sequences.
+
+
+If you pass an invalid UTF string when PCRE2_NO_UTF_CHECK is set, the result
+is undefined and your program may crash or loop indefinitely or give incorrect
+results. There is, however, one mode of matching that can handle invalid UTF
+subject strings. This is enabled by passing PCRE2_MATCH_INVALID_UTF to
+pcre2_compile() and is discussed below in the next section. The rest of
+this section covers the case when PCRE2_MATCH_INVALID_UTF is not set.
+
+
+Passing PCRE2_NO_UTF_CHECK to pcre2_compile() just disables the UTF check
+for the pattern; it does not also apply to subject strings. If you want to
+disable the check for a subject string you must pass this same option to
+pcre2_match() or pcre2_dfa_match().
UTF-16 and UTF-32 strings can indicate their endianness by special code knows
@@ -142,13 +292,14 @@ as a byte-order mark (BOM). The PCRE2 functions do not handle this, expecting
strings to be in host byte order.
-A UTF string is checked before any other processing takes place. In the case of
-pcre2_match() and pcre2_dfa_match() calls with a non-zero starting
-offset, the check is applied only to that part of the subject that could be
-inspected during matching, and there is a check that the starting offset points
-to the first code unit of a character or to the end of the subject. If there
-are no lookbehind assertions in the pattern, the check starts at the starting
-offset. Otherwise, it starts at the length of the longest lookbehind before the
+Unless PCRE2_NO_UTF_CHECK is set, a UTF string is checked before any other
+processing takes place. In the case of pcre2_match() and
+pcre2_dfa_match() calls with a non-zero starting offset, the check is
+applied only to that part of the subject that could be inspected during
+matching, and there is a check that the starting offset points to the first
+code unit of a character or to the end of the subject. If there are no
+lookbehind assertions in the pattern, the check starts at the starting offset.
+Otherwise, it starts at the length of the longest lookbehind before the
starting offset, or at the start of the subject if there are not that many
characters before the starting offset. Note that the sequences \b and \B are
one-character lookbehinds.
@@ -168,31 +319,12 @@ surrogate thing is a fudge for UTF-16 which unfortunately messes up UTF-8 and
UTF-32.)
-In some situations, you may already know that your strings are valid, and
-therefore want to skip these checks in order to improve performance, for
-example in the case of a long subject string that is being scanned repeatedly.
-If you set the PCRE2_NO_UTF_CHECK option at compile time or at match time,
-PCRE2 assumes that the pattern or subject it is given (respectively) contains
-only valid UTF code unit sequences.
-
-
-Passing PCRE2_NO_UTF_CHECK to pcre2_compile() just disables the check for
-the pattern; it does not also apply to subject strings. If you want to disable
-the check for a subject string you must pass this option to pcre2_match()
-or pcre2_dfa_match().
-
-
-If you pass an invalid UTF string when PCRE2_NO_UTF_CHECK is set, the result
-is undefined and your program may crash or loop indefinitely.
-
-
-Note that setting PCRE2_NO_UTF_CHECK at compile time does not disable the error
-that is given if an escape sequence for an invalid Unicode code point is
-encountered in the pattern. If you want to allow escape sequences such as
-\x{d800} (a surrogate code point) you can set the
-PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES extra option. However, this is possible
-only in UTF-8 and UTF-32 modes, because these values are not representable in
-UTF-16.
+Setting PCRE2_NO_UTF_CHECK at compile time does not disable the error that is
+given if an escape sequence for an invalid Unicode code point is encountered in
+the pattern. If you want to allow escape sequences such as \x{d800} (a
+surrogate code point) you can set the PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES extra
+option. However, this is possible only in UTF-8 and UTF-32 modes, because these
+values are not representable in UTF-16.
Errors in UTF-8 strings
@@ -230,7 +362,7 @@ these code points are excluded by RFC 3629.
PCRE2_ERROR_UTF8_ERR13
-A 4-byte character has a value greater than 0x10fff; these code points are
+A 4-byte character has a value greater than 0x10ffff; these code points are
excluded by RFC 3629.
PCRE2_ERROR_UTF8_ERR14
@@ -283,7 +415,59 @@ The following negative error codes are given for invalid UTF-32 strings:
PCRE2_ERROR_UTF32_ERR1 Surrogate character (0xd800 to 0xdfff)
PCRE2_ERROR_UTF32_ERR2 Code point is greater than 0x10ffff
-
+
+
+
+MATCHING IN INVALID UTF STRINGS
+
+
+You can run pattern matches on subject strings that may contain invalid UTF
+sequences if you call pcre2_compile() with the PCRE2_MATCH_INVALID_UTF
+option. This is supported by pcre2_match(), including JIT matching, but
+not by pcre2_dfa_match(). When PCRE2_MATCH_INVALID_UTF is set, it forces
+PCRE2_UTF to be set as well. Note, however, that the pattern itself must be a
+valid UTF string.
+
+
+Setting PCRE2_MATCH_INVALID_UTF does not affect what pcre2_compile()
+generates, but if pcre2_jit_compile() is subsequently called, it does
+generate different code. If JIT is not used, the option affects the behaviour
+of the interpretive code in pcre2_match(). When PCRE2_MATCH_INVALID_UTF
+is set at compile time, PCRE2_NO_UTF_CHECK is ignored at match time.
+
+
+In this mode, an invalid code unit sequence in the subject never matches any
+pattern item. It does not match dot, it does not match \p{Any}, it does not
+even match negative items such as [^X]. A lookbehind assertion fails if it
+encounters an invalid sequence while moving the current point backwards. In
+other words, an invalid UTF code unit sequence acts as a barrier which no match
+can cross.
+
+
+You can also think of this as the subject being split up into fragments of
+valid UTF, delimited internally by invalid code unit sequences. The pattern is
+matched fragment by fragment. The result of a successful match, however, is
+given as code unit offsets in the entire subject string in the usual way. There
+are a few points to consider:
+
+
+The internal boundaries are not interpreted as the beginnings or ends of lines
+and so do not match circumflex or dollar characters in the pattern.
+
+
+If pcre2_match() is called with an offset that points to an invalid
+UTF-sequence, that sequence is skipped, and the match starts at the next valid
+UTF character, or the end of the subject.
+
+
+At internal fragment boundaries, \b and \B behave in the same way as at the
+beginning and end of the subject. For example, a sequence such as \bWORD\b
+would match an instance of WORD that is surrounded by invalid UTF code units.
+
+
+Using PCRE2_MATCH_INVALID_UTF, an application can run matches on arbitrary
+data, knowing that any matched strings that are returned are valid UTF. This
+can be useful when searching for UTF text in executable or other binary files.
AUTHOR
@@ -300,9 +484,9 @@ Cambridge, England.
REVISION
-Last updated: 02 September 2018
+Last updated: 24 May 2019
-Copyright © 1997-2018 University of Cambridge.
+Copyright © 1997-2019 University of Cambridge.
Return to the PCRE2 index page.
diff --git a/doc/index.html.src b/doc/index.html.src
index 82b43c3..2c7c5fb 100644
--- a/doc/index.html.src
+++ b/doc/index.html.src
@@ -146,6 +146,9 @@ in the library.
pcre2_get_mark
Get a (*MARK) name
+pcre2_get_match_data_size
+ Get the size of a match data block
+
pcre2_get_ovector_count
Get the ovector count
@@ -176,6 +179,9 @@ in the library.
pcre2_maketables
Build character tables in current locale
+pcre2_maketables_free
+ Free character tables
+
pcre2_match
Match a compiled pattern to a subject string
(Perl compatible)
diff --git a/doc/pcre2-config.txt b/doc/pcre2-config.txt
index 8ddea2a..33785f4 100644
--- a/doc/pcre2-config.txt
+++ b/doc/pcre2-config.txt
@@ -16,8 +16,8 @@ DESCRIPTION
pcre2-config returns the configuration of the installed PCRE2 libraries
and the options required to compile a program to use them. Some of the
- options apply only to the 8-bit, or 16-bit, or 32-bit libraries,
- respectively, and are not available for libraries that have not been
+ options apply only to the 8-bit, or 16-bit, or 32-bit libraries, re-
+ spectively, and are not available for libraries that have not been
built. If an unavailable option is encountered, the "usage" information
is output.
@@ -36,30 +36,30 @@ OPTIONS
--version Writes the version number of the installed PCRE2 libraries to
the standard output.
- --libs8 Writes to the standard output the command line options
- required to link with the 8-bit PCRE2 library (-lpcre2-8 on
+ --libs8 Writes to the standard output the command line options re-
+ quired to link with the 8-bit PCRE2 library (-lpcre2-8 on
many systems).
- --libs16 Writes to the standard output the command line options
- required to link with the 16-bit PCRE2 library (-lpcre2-16 on
+ --libs16 Writes to the standard output the command line options re-
+ quired to link with the 16-bit PCRE2 library (-lpcre2-16 on
many systems).
- --libs32 Writes to the standard output the command line options
- required to link with the 32-bit PCRE2 library (-lpcre2-32 on
+ --libs32 Writes to the standard output the command line options re-
+ quired to link with the 32-bit PCRE2 library (-lpcre2-32 on
many systems).
--libs-posix
- Writes to the standard output the command line options
- required to link with PCRE2's POSIX API wrapper library
+ Writes to the standard output the command line options re-
+ quired to link with PCRE2's POSIX API wrapper library
(-lpcre2-posix -lpcre2-8 on many systems).
- --cflags Writes to the standard output the command line options
- required to compile files that use PCRE2 (this may include
- some -I options, but is blank on many systems).
+ --cflags Writes to the standard output the command line options re-
+ quired to compile files that use PCRE2 (this may include some
+ -I options, but is blank on many systems).
--cflags-posix
- Writes to the standard output the command line options
- required to compile files that use PCRE2's POSIX API wrapper
+ Writes to the standard output the command line options re-
+ quired to compile files that use PCRE2's POSIX API wrapper
library (this may include some -I options, but is blank on
many systems).
diff --git a/doc/pcre2.3 b/doc/pcre2.3
index 2f83658..75450ec 100644
--- a/doc/pcre2.3
+++ b/doc/pcre2.3
@@ -1,4 +1,4 @@
-.TH PCRE2 3 "11 July 2018" "PCRE2 10.32"
+.TH PCRE2 3 "17 September 2018" "PCRE2 10.33"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH INTRODUCTION
@@ -156,7 +156,7 @@ listing), and the short pages for individual functions, are concatenated in
pcre2-config show PCRE2 installation configuration information
pcre2api details of PCRE2's native C API
pcre2build building PCRE2
- pcre2callout details of the callout feature
+ pcre2callout details of the pattern callout feature
pcre2compat discussion of Perl compatibility
pcre2convert details of pattern conversion functions
pcre2demo a demonstration C program that uses PCRE2
@@ -197,6 +197,6 @@ use my two initials, followed by the two digits 10, at the domain cam.ac.uk.
.rs
.sp
.nf
-Last updated: 11 July 2018
+Last updated: 17 September 2018
Copyright (c) 1997-2018 University of Cambridge.
.fi
diff --git a/doc/pcre2.txt b/doc/pcre2.txt
index 30ba2f9..948b91a 100644
--- a/doc/pcre2.txt
+++ b/doc/pcre2.txt
@@ -31,8 +31,8 @@ INTRODUCTION
appeared in Python and the original PCRE before they appeared in Perl
are available using the Python syntax. There is also some support for
one or two .NET and Oniguruma syntax items, and there are options for
- requesting some minor changes that give better ECMAScript (aka
- JavaScript) compatibility.
+ requesting some minor changes that give better ECMAScript (aka Java-
+ Script) compatibility.
The source code for PCRE2 can be compiled to support 8-bit, 16-bit, or
32-bit code units, which means that up to three separate libraries may
@@ -111,9 +111,9 @@ SECURITY CONSIDERATIONS
The use of the \C escape sequence in a UTF-8 or UTF-16 pattern can lead
to problems, because it may leave the current matching point in the
- middle of a multi-code-unit character. The PCRE2_NEVER_BACKSLASH_C
- option can be used by an application to lock out the use of \C, causing
- a compile-time error if it is encountered. It is also possible to build
+ middle of a multi-code-unit character. The PCRE2_NEVER_BACKSLASH_C op-
+ tion can be used by an application to lock out the use of \C, causing a
+ compile-time error if it is encountered. It is also possible to build
PCRE2 with the use of \C permanently disabled.
Another way that performance can be hit is by running a pattern that
@@ -141,7 +141,7 @@ USER DOCUMENTATION
pcre2-config show PCRE2 installation configuration information
pcre2api details of PCRE2's native C API
pcre2build building PCRE2
- pcre2callout details of the callout feature
+ pcre2callout details of the pattern callout feature
pcre2compat discussion of Perl compatibility
pcre2convert details of pattern conversion functions
pcre2demo a demonstration C program that uses PCRE2
@@ -177,7 +177,7 @@ AUTHOR
REVISION
- Last updated: 11 July 2018
+ Last updated: 17 September 2018
Copyright (c) 1997-2018 University of Cambridge.
------------------------------------------------------------------------------
@@ -261,7 +261,7 @@ PCRE2 NATIVE API COMPILE CONTEXT FUNCTIONS
uint32_t value);
int pcre2_set_character_tables(pcre2_compile_context *ccontext,
- const unsigned char *tables);
+ const uint8_t *tables);
int pcre2_set_compile_extra_options(pcre2_compile_context *ccontext,
uint32_t extra_options);
@@ -293,6 +293,10 @@ PCRE2 NATIVE API MATCH CONTEXT FUNCTIONS
int (*callout_function)(pcre2_callout_block *, void *),
void *callout_data);
+ int pcre2_set_substitute_callout(pcre2_match_context *mcontext,
+ int (*callout_function)(pcre2_substitute_callout_block *, void *),
+ void *callout_data);
+
int pcre2_set_offset_limit(pcre2_match_context *mcontext,
PCRE2_SIZE value);
@@ -396,9 +400,13 @@ PCRE2 NATIVE API AUXILIARY FUNCTIONS
int pcre2_get_error_message(int errorcode, PCRE2_UCHAR *buffer,
PCRE2_SIZE bufflen);
- const unsigned char *pcre2_maketables(pcre2_general_context *gcontext);
+ const uint8_t *pcre2_maketables(pcre2_general_context *gcontext);
- int pcre2_pattern_info(const pcre2 *code, uint32_t what, void *where);
+ void pcre2_maketables_free(pcre2_general_context *gcontext,
+ const uint8_t *tables);
+
+ int pcre2_pattern_info(const pcre2_code *code, uint32_t what,
+ void *where);
int pcre2_callout_enumerate(const pcre2_code *code,
int (*callback)(pcre2_callout_enumerate_block *, void *),
@@ -446,8 +454,8 @@ PCRE2 EXPERIMENTAL PATTERN CONVERSION FUNCTIONS
void pcre2_converted_pattern_free(PCRE2_UCHAR *converted_pattern);
These functions provide a way of converting non-PCRE2 patterns into
- patterns that can be processed by pcre2_compile(). This facility is
- experimental and may be changed in future releases. At present, "globs"
+ patterns that can be processed by pcre2_compile(). This facility is ex-
+ perimental and may be changed in future releases. At present, "globs"
and POSIX basic and extended patterns can be converted. Details are
given in the pcre2convert documentation.
@@ -538,22 +546,22 @@ PCRE2 API OVERVIEW
The compiling and matching functions recognize various options that are
passed as bits in an options argument. There are also some more compli-
- cated parameters such as custom memory management functions and
- resource limits that are passed in "contexts" (which are just memory
+ cated parameters such as custom memory management functions and re-
+ source limits that are passed in "contexts" (which are just memory
blocks, described below). Simple applications do not need to make use
of contexts.
Just-in-time (JIT) compiler support is an optional feature of PCRE2
that can be built in appropriate hardware environments. It greatly
- speeds up the matching performance of many patterns. Programs can
- request that it be used if available by calling pcre2_jit_compile()
- after a pattern has been successfully compiled by pcre2_compile(). This
- does nothing if JIT support is not available.
+ speeds up the matching performance of many patterns. Programs can re-
+ quest that it be used if available by calling pcre2_jit_compile() after
+ a pattern has been successfully compiled by pcre2_compile(). This does
+ nothing if JIT support is not available.
More complicated programs might need to make use of the specialist
functions pcre2_jit_stack_create(), pcre2_jit_stack_free(), and
- pcre2_jit_stack_assign() in order to control the JIT code's memory
- usage.
+ pcre2_jit_stack_assign() in order to control the JIT code's memory us-
+ age.
JIT matching is automatically used by pcre2_match() if it is available,
unless the PCRE2_NO_JIT option is set. There is also a direct interface
@@ -565,13 +573,12 @@ PCRE2 API OVERVIEW
patible, is also provided. This uses a different algorithm for the
matching. The alternative algorithm finds all possible matches (at a
given point in the subject), and scans the subject just once (unless
- there are lookaround assertions). However, this algorithm does not
- return captured substrings. A description of the two matching algo-
- rithms and their advantages and disadvantages is given in the
- pcre2matching documentation. There is no JIT support for
- pcre2_dfa_match().
+ there are lookaround assertions). However, this algorithm does not re-
+ turn captured substrings. A description of the two matching algorithms
+ and their advantages and disadvantages is given in the pcre2matching
+ documentation. There is no JIT support for pcre2_dfa_match().
- In addition to the main compiling and matching functions, there are
+ In addition to the main compiling and matching functions, there are
convenience functions for extracting captured substrings from a subject
string that has been matched by pcre2_match(). They are:
@@ -585,97 +592,97 @@ PCRE2 API OVERVIEW
pcre2_substring_nametable_scan()
pcre2_substring_number_from_name()
- pcre2_substring_free() and pcre2_substring_list_free() are also pro-
- vided, to free memory used for extracted strings. If either of these
- functions is called with a NULL argument, the function returns immedi-
+ pcre2_substring_free() and pcre2_substring_list_free() are also pro-
+ vided, to free memory used for extracted strings. If either of these
+ functions is called with a NULL argument, the function returns immedi-
ately without doing anything.
- The function pcre2_substitute() can be called to match a pattern and
- return a copy of the subject string with substitutions for parts that
+ The function pcre2_substitute() can be called to match a pattern and
+ return a copy of the subject string with substitutions for parts that
were matched.
- Functions whose names begin with pcre2_serialize_ are used for saving
+ Functions whose names begin with pcre2_serialize_ are used for saving
compiled patterns on disc or elsewhere, and reloading them later.
- Finally, there are functions for finding out information about a com-
- piled pattern (pcre2_pattern_info()) and about the configuration with
+ Finally, there are functions for finding out information about a com-
+ piled pattern (pcre2_pattern_info()) and about the configuration with
which PCRE2 was built (pcre2_config()).
- Functions with names ending with _free() are used for freeing memory
- blocks of various sorts. In all cases, if one of these functions is
+ Functions with names ending with _free() are used for freeing memory
+ blocks of various sorts. In all cases, if one of these functions is
called with a NULL argument, it does nothing.
STRING LENGTHS AND OFFSETS
- The PCRE2 API uses string lengths and offsets into strings of code
- units in several places. These values are always of type PCRE2_SIZE,
- which is an unsigned integer type, currently always defined as size_t.
- The largest value that can be stored in such a type (that is
- ~(PCRE2_SIZE)0) is reserved as a special indicator for zero-terminated
- strings and unset offsets. Therefore, the longest string that can be
+ The PCRE2 API uses string lengths and offsets into strings of code
+ units in several places. These values are always of type PCRE2_SIZE,
+ which is an unsigned integer type, currently always defined as size_t.
+ The largest value that can be stored in such a type (that is
+ ~(PCRE2_SIZE)0) is reserved as a special indicator for zero-terminated
+ strings and unset offsets. Therefore, the longest string that can be
handled is one less than this maximum.
NEWLINES
PCRE2 supports five different conventions for indicating line breaks in
- strings: a single CR (carriage return) character, a single LF (line-
+ strings: a single CR (carriage return) character, a single LF (line-
feed) character, the two-character sequence CRLF, any of the three pre-
- ceding, or any Unicode newline sequence. The Unicode newline sequences
- are the three just mentioned, plus the single characters VT (vertical
+ ceding, or any Unicode newline sequence. The Unicode newline sequences
+ are the three just mentioned, plus the single characters VT (vertical
tab, U+000B), FF (form feed, U+000C), NEL (next line, U+0085), LS (line
separator, U+2028), and PS (paragraph separator, U+2029).
- Each of the first three conventions is used by at least one operating
+ Each of the first three conventions is used by at least one operating
system as its standard newline sequence. When PCRE2 is built, a default
can be specified. If it is not, the default is set to LF, which is the
- Unix standard. However, the newline convention can be changed by an
- application when calling pcre2_compile(), or it can be specified by
- special text at the start of the pattern itself; this overrides any
- other settings. See the pcre2pattern page for details of the special
- character sequences.
+ Unix standard. However, the newline convention can be changed by an ap-
+ plication when calling pcre2_compile(), or it can be specified by spe-
+ cial text at the start of the pattern itself; this overrides any other
+ settings. See the pcre2pattern page for details of the special charac-
+ ter sequences.
- In the PCRE2 documentation the word "newline" is used to mean "the
+ In the PCRE2 documentation the word "newline" is used to mean "the
character or pair of characters that indicate a line break". The choice
- of newline convention affects the handling of the dot, circumflex, and
+ of newline convention affects the handling of the dot, circumflex, and
dollar metacharacters, the handling of #-comments in /x mode, and, when
- CRLF is a recognized line ending sequence, the match position advance-
+ CRLF is a recognized line ending sequence, the match position advance-
ment for a non-anchored pattern. There is more detail about this in the
section on pcre2_match() options below.
- The choice of newline convention does not affect the interpretation of
+ The choice of newline convention does not affect the interpretation of
the \n or \r escape sequences, nor does it affect what \R matches; this
has its own separate convention.
MULTITHREADING
- In a multithreaded application it is important to keep thread-specific
- data separate from data that can be shared between threads. The PCRE2
- library code itself is thread-safe: it contains no static or global
- variables. The API is designed to be fairly simple for non-threaded
- applications while at the same time ensuring that multithreaded appli-
- cations can use it.
+ In a multithreaded application it is important to keep thread-specific
+ data separate from data that can be shared between threads. The PCRE2
+ library code itself is thread-safe: it contains no static or global
+ variables. The API is designed to be fairly simple for non-threaded ap-
+ plications while at the same time ensuring that multithreaded applica-
+ tions can use it.
There are several different blocks of data that are used to pass infor-
mation between the application and the PCRE2 libraries.
The compiled pattern
- A pointer to the compiled form of a pattern is returned to the user
+ A pointer to the compiled form of a pattern is returned to the user
when pcre2_compile() is successful. The data in the compiled pattern is
- fixed, and does not change when the pattern is matched. Therefore, it
- is thread-safe, that is, the same compiled pattern can be used by more
+ fixed, and does not change when the pattern is matched. Therefore, it
+ is thread-safe, that is, the same compiled pattern can be used by more
than one thread simultaneously. For example, an application can compile
all its patterns at the start, before forking off multiple threads that
- use them. However, if the just-in-time (JIT) optimization feature is
- being used, it needs separate memory stack areas for each thread. See
+ use them. However, if the just-in-time (JIT) optimization feature is
+ being used, it needs separate memory stack areas for each thread. See
the pcre2jit documentation for more details.
- In a more complicated situation, where patterns are compiled only when
- they are first needed, but are still shared between threads, pointers
- to compiled patterns must be protected from simultaneous writing by
+ In a more complicated situation, where patterns are compiled only when
+ they are first needed, but are still shared between threads, pointers
+ to compiled patterns must be protected from simultaneous writing by
multiple threads, at least until a pattern has been compiled. The logic
can be something like this:
@@ -688,72 +695,72 @@ MULTITHREADING
Release the lock
Use pointer in pcre2_match()
- Of course, testing for compilation errors should also be included in
+ Of course, testing for compilation errors should also be included in
the code.
If JIT is being used, but the JIT compilation is not being done immedi-
- ately, (perhaps waiting to see if the pattern is used often enough)
+ ately, (perhaps waiting to see if the pattern is used often enough)
similar logic is required. JIT compilation updates a pointer within the
- compiled code block, so a thread must gain unique write access to the
- pointer before calling pcre2_jit_compile(). Alternatively,
- pcre2_code_copy() or pcre2_code_copy_with_tables() can be used to
- obtain a private copy of the compiled code before calling the JIT com-
+ compiled code block, so a thread must gain unique write access to the
+ pointer before calling pcre2_jit_compile(). Alternatively,
+ pcre2_code_copy() or pcre2_code_copy_with_tables() can be used to ob-
+ tain a private copy of the compiled code before calling the JIT com-
piler.
Context blocks
- The next main section below introduces the idea of "contexts" in which
+ The next main section below introduces the idea of "contexts" in which
PCRE2 functions are called. A context is nothing more than a collection
of parameters that control the way PCRE2 operates. Grouping a number of
parameters together in a context is a convenient way of passing them to
- a PCRE2 function without using lots of arguments. The parameters that
- are stored in contexts are in some sense "advanced features" of the
+ a PCRE2 function without using lots of arguments. The parameters that
+ are stored in contexts are in some sense "advanced features" of the
API. Many straightforward applications will not need to use contexts.
In a multithreaded application, if the parameters in a context are val-
- ues that are never changed, the same context can be used by all the
+ ues that are never changed, the same context can be used by all the
threads. However, if any thread needs to change any value in a context,
it must make its own thread-specific copy.
Match blocks
- The matching functions need a block of memory for storing the results
+ The matching functions need a block of memory for storing the results
of a match. This includes details of what was matched, as well as addi-
- tional information such as the name of a (*MARK) setting. Each thread
+ tional information such as the name of a (*MARK) setting. Each thread
must provide its own copy of this memory.
PCRE2 CONTEXTS
- Some PCRE2 functions have a lot of parameters, many of which are used
- only by specialist applications, for example, those that use custom
- memory management or non-standard character tables. To keep function
- argument lists at a reasonable size, and at the same time to keep the
- API extensible, "uncommon" parameters are passed to certain functions
- in a context instead of directly. A context is just a block of memory
- that holds the parameter values. Applications that do not need to
- adjust any of the context parameters can pass NULL when a context
- pointer is required.
-
- There are three different types of context: a general context that is
- relevant for several PCRE2 operations, a compile-time context, and a
+ Some PCRE2 functions have a lot of parameters, many of which are used
+ only by specialist applications, for example, those that use custom
+ memory management or non-standard character tables. To keep function
+ argument lists at a reasonable size, and at the same time to keep the
+ API extensible, "uncommon" parameters are passed to certain functions
+ in a context instead of directly. A context is just a block of memory
+ that holds the parameter values. Applications that do not need to ad-
+ just any of the context parameters can pass NULL when a context pointer
+ is required.
+
+ There are three different types of context: a general context that is
+ relevant for several PCRE2 operations, a compile-time context, and a
match-time context.
The general context
- At present, this context just contains pointers to (and data for)
- external memory management functions that are called from several
- places in the PCRE2 library. The context is named `general' rather than
- specifically `memory' because in future other fields may be added. If
- you do not want to supply your own custom memory management functions,
- you do not need to bother with a general context. A general context is
+ At present, this context just contains pointers to (and data for) ex-
+ ternal memory management functions that are called from several places
+ in the PCRE2 library. The context is named `general' rather than
+ specifically `memory' because in future other fields may be added. If
+ you do not want to supply your own custom memory management functions,
+ you do not need to bother with a general context. A general context is
created by:
pcre2_general_context *pcre2_general_context_create(
void *(*private_malloc)(PCRE2_SIZE, void *),
void (*private_free)(void *, void *), void *memory_data);
- The two function pointers specify custom memory management functions,
+ The two function pointers specify custom memory management functions,
whose prototypes are:
void *private_malloc(PCRE2_SIZE, void *);
@@ -761,16 +768,16 @@ PCRE2 CONTEXTS
Whenever code in PCRE2 calls these functions, the final argument is the
value of memory_data. Either of the first two arguments of the creation
- function may be NULL, in which case the system memory management func-
- tions malloc() and free() are used. (This is not currently useful, as
- there are no other fields in a general context, but in future there
- might be.) The private_malloc() function is used (if supplied) to
- obtain memory for storing the context, and all three values are saved
- as part of the context.
-
- Whenever PCRE2 creates a data block of any kind, the block contains a
- pointer to the free() function that matches the malloc() function that
- was used. When the time comes to free the block, this function is
+ function may be NULL, in which case the system memory management func-
+ tions malloc() and free() are used. (This is not currently useful, as
+ there are no other fields in a general context, but in future there
+ might be.) The private_malloc() function is used (if supplied) to ob-
+ tain memory for storing the context, and all three values are saved as
+ part of the context.
+
+ Whenever PCRE2 creates a data block of any kind, the block contains a
+ pointer to the free() function that matches the malloc() function that
+ was used. When the time comes to free the block, this function is
called.
A general context can be copied by calling:
@@ -782,13 +789,13 @@ PCRE2 CONTEXTS
void pcre2_general_context_free(pcre2_general_context *gcontext);
- If this function is passed a NULL argument, it returns immediately
+ If this function is passed a NULL argument, it returns immediately
without doing anything.
The compile context
- A compile context is required if you want to provide an external func-
- tion for stack checking during compilation or to change the default
+ A compile context is required if you want to provide an external func-
+ tion for stack checking during compilation or to change the default
values of any of the following compile-time parameters:
What \R matches (Unicode newlines or CR, LF, CRLF only)
@@ -798,11 +805,11 @@ PCRE2 CONTEXTS
The maximum length of the pattern string
The extra options bits (none set by default)
- A compile context is also required if you are using custom memory man-
- agement. If none of these apply, just pass NULL as the context argu-
+ A compile context is also required if you are using custom memory man-
+ agement. If none of these apply, just pass NULL as the context argu-
ment of pcre2_compile().
- A compile context is created, copied, and freed by the following func-
+ A compile context is created, copied, and freed by the following func-
tions:
pcre2_compile_context *pcre2_compile_context_create(
@@ -813,91 +820,91 @@ PCRE2 CONTEXTS
void pcre2_compile_context_free(pcre2_compile_context *ccontext);
- A compile context is created with default values for its parameters.
+ A compile context is created with default values for its parameters.
These can be changed by calling the following functions, which return 0
on success, or PCRE2_ERROR_BADDATA if invalid data is detected.
int pcre2_set_bsr(pcre2_compile_context *ccontext,
uint32_t value);
- The value must be PCRE2_BSR_ANYCRLF, to specify that \R matches only
- CR, LF, or CRLF, or PCRE2_BSR_UNICODE, to specify that \R matches any
+ The value must be PCRE2_BSR_ANYCRLF, to specify that \R matches only
+ CR, LF, or CRLF, or PCRE2_BSR_UNICODE, to specify that \R matches any
Unicode line ending sequence. The value is used by the JIT compiler and
- by the two interpreted matching functions, pcre2_match() and
+ by the two interpreted matching functions, pcre2_match() and
pcre2_dfa_match().
int pcre2_set_character_tables(pcre2_compile_context *ccontext,
- const unsigned char *tables);
+ const uint8_t *tables);
- The value must be the result of a call to pcre2_maketables(), whose
+ The value must be the result of a call to pcre2_maketables(), whose
only argument is a general context. This function builds a set of char-
acter tables in the current locale.
int pcre2_set_compile_extra_options(pcre2_compile_context *ccontext,
uint32_t extra_options);
- As PCRE2 has developed, almost all the 32 option bits that are avail-
- able in the options argument of pcre2_compile() have been used up. To
- avoid running out, the compile context contains a set of extra option
- bits which are used for some newer, assumed rarer, options. This func-
- tion sets those bits. It always sets all the bits (either on or off).
- It does not modify any existing setting. The available options are
- defined in the section entitled "Extra compile options" below.
+ As PCRE2 has developed, almost all the 32 option bits that are avail-
+ able in the options argument of pcre2_compile() have been used up. To
+ avoid running out, the compile context contains a set of extra option
+ bits which are used for some newer, assumed rarer, options. This func-
+ tion sets those bits. It always sets all the bits (either on or off).
+ It does not modify any existing setting. The available options are de-
+ fined in the section entitled "Extra compile options" below.
int pcre2_set_max_pattern_length(pcre2_compile_context *ccontext,
PCRE2_SIZE value);
- This sets a maximum length, in code units, for any pattern string that
- is compiled with this context. If the pattern is longer, an error is
- generated. This facility is provided so that applications that accept
+ This sets a maximum length, in code units, for any pattern string that
+ is compiled with this context. If the pattern is longer, an error is
+ generated. This facility is provided so that applications that accept
patterns from external sources can limit their size. The default is the
- largest number that a PCRE2_SIZE variable can hold, which is effec-
+ largest number that a PCRE2_SIZE variable can hold, which is effec-
tively unlimited.
int pcre2_set_newline(pcre2_compile_context *ccontext,
uint32_t value);
This specifies which characters or character sequences are to be recog-
- nized as newlines. The value must be one of PCRE2_NEWLINE_CR (carriage
+ nized as newlines. The value must be one of PCRE2_NEWLINE_CR (carriage
return only), PCRE2_NEWLINE_LF (linefeed only), PCRE2_NEWLINE_CRLF (the
- two-character sequence CR followed by LF), PCRE2_NEWLINE_ANYCRLF (any
- of the above), PCRE2_NEWLINE_ANY (any Unicode newline sequence), or
+ two-character sequence CR followed by LF), PCRE2_NEWLINE_ANYCRLF (any
+ of the above), PCRE2_NEWLINE_ANY (any Unicode newline sequence), or
PCRE2_NEWLINE_NUL (the NUL character, that is a binary zero).
A pattern can override the value set in the compile context by starting
with a sequence such as (*CRLF). See the pcre2pattern page for details.
- When a pattern is compiled with the PCRE2_EXTENDED or
- PCRE2_EXTENDED_MORE option, the newline convention affects the recogni-
- tion of the end of internal comments starting with #. The value is
- saved with the compiled pattern for subsequent use by the JIT compiler
- and by the two interpreted matching functions, pcre2_match() and
+ When a pattern is compiled with the PCRE2_EXTENDED or PCRE2_EX-
+ TENDED_MORE option, the newline convention affects the recognition of
+ the end of internal comments starting with #. The value is saved with
+ the compiled pattern for subsequent use by the JIT compiler and by the
+ two interpreted matching functions, pcre2_match() and
pcre2_dfa_match().
int pcre2_set_parens_nest_limit(pcre2_compile_context *ccontext,
uint32_t value);
- This parameter ajusts the limit, set when PCRE2 is built (default 250),
- on the depth of parenthesis nesting in a pattern. This limit stops
- rogue patterns using up too much system stack when being compiled. The
- limit applies to parentheses of all kinds, not just capturing parenthe-
- ses.
+ This parameter adjusts the limit, set when PCRE2 is built (default
+ 250), on the depth of parenthesis nesting in a pattern. This limit
+ stops rogue patterns using up too much system stack when being com-
+ piled. The limit applies to parentheses of all kinds, not just captur-
+ ing parentheses.
int pcre2_set_compile_recursion_guard(pcre2_compile_context *ccontext,
int (*guard_function)(uint32_t, void *), void *user_data);
- There is at least one application that runs PCRE2 in threads with very
- limited system stack, where running out of stack is to be avoided at
- all costs. The parenthesis limit above cannot take account of how much
- stack is actually available during compilation. For a finer control,
- you can supply a function that is called whenever pcre2_compile()
- starts to compile a parenthesized part of a pattern. This function can
- check the actual stack size (or anything else that it wants to, of
+ There is at least one application that runs PCRE2 in threads with very
+ limited system stack, where running out of stack is to be avoided at
+ all costs. The parenthesis limit above cannot take account of how much
+ stack is actually available during compilation. For a finer control,
+ you can supply a function that is called whenever pcre2_compile()
+ starts to compile a parenthesized part of a pattern. This function can
+ check the actual stack size (or anything else that it wants to, of
course).
- The first argument to the callout function gives the current depth of
- nesting, and the second is user data that is set up by the last argu-
- ment of pcre2_set_compile_recursion_guard(). The callout function
+ The first argument to the callout function gives the current depth of
+ nesting, and the second is user data that is set up by the last argu-
+ ment of pcre2_set_compile_recursion_guard(). The callout function
should return zero if all is well, or non-zero to force an error.
The match context
@@ -911,10 +918,10 @@ PCRE2 CONTEXTS
Change the backtracking depth limit
Set custom memory management specifically for the match
- If none of these apply, just pass NULL as the context argument of
+ If none of these apply, just pass NULL as the context argument of
pcre2_match(), pcre2_dfa_match(), or pcre2_jit_match().
- A match context is created, copied, and freed by the following func-
+ A match context is created, copied, and freed by the following func-
tions:
pcre2_match_context *pcre2_match_context_create(
@@ -925,7 +932,7 @@ PCRE2 CONTEXTS
void pcre2_match_context_free(pcre2_match_context *mcontext);
- A match context is created with default values for its parameters.
+ A match context is created with default values for its parameters.
These can be changed by calling the following functions, which return 0
on success, or PCRE2_ERROR_BADDATA if invalid data is detected.
@@ -933,36 +940,42 @@ PCRE2 CONTEXTS
int (*callout_function)(pcre2_callout_block *, void *),
void *callout_data);
- This sets up a "callout" function for PCRE2 to call at specified points
+ This sets up a callout function for PCRE2 to call at specified points
during a matching operation. Details are given in the pcre2callout doc-
umentation.
+ int pcre2_set_substitute_callout(pcre2_match_context *mcontext,
+ int (*callout_function)(pcre2_substitute_callout_block *, void *),
+ void *callout_data);
+
+ This sets up a callout function for PCRE2 to call after each substitu-
+ tion made by pcre2_substitute(). Details are given in the section enti-
+ tled "Creating a new string with substitutions" below.
+
int pcre2_set_offset_limit(pcre2_match_context *mcontext,
PCRE2_SIZE value);
- The offset_limit parameter limits how far an unanchored search can
- advance in the subject string. The default value is PCRE2_UNSET. The
- pcre2_match() and pcre2_dfa_match() functions return
- PCRE2_ERROR_NOMATCH if a match with a starting point before or at the
- given offset is not found. The pcre2_substitute() function makes no
- more substitutions.
+ The offset_limit parameter limits how far an unanchored search can ad-
+ vance in the subject string. The default value is PCRE2_UNSET. The
+ pcre2_match() and pcre2_dfa_match() functions return PCRE2_ERROR_NO-
+ MATCH if a match with a starting point before or at the given offset is
+ not found. The pcre2_substitute() function makes no more substitutions.
For example, if the pattern /abc/ is matched against "123abc" with an
- offset limit less than 3, the result is PCRE2_ERROR_NO_MATCH. A match
+ offset limit less than 3, the result is PCRE2_ERROR_NOMATCH. A match
can never be found if the startoffset argument of pcre2_match(),
pcre2_dfa_match(), or pcre2_substitute() is greater than the offset
limit set in the match context.
- When using this facility, you must set the PCRE2_USE_OFFSET_LIMIT
- option when calling pcre2_compile() so that when JIT is in use, differ-
- ent code can be compiled. If a match is started with a non-default
- match limit when PCRE2_USE_OFFSET_LIMIT is not set, an error is gener-
- ated.
+ When using this facility, you must set the PCRE2_USE_OFFSET_LIMIT op-
+ tion when calling pcre2_compile() so that when JIT is in use, different
+ code can be compiled. If a match is started with a non-default match
+ limit when PCRE2_USE_OFFSET_LIMIT is not set, an error is generated.
- The offset limit facility can be used to track progress when searching
- large subject strings or to limit the extent of global substitutions.
- See also the PCRE2_FIRSTLINE option, which requires a match to start
- before or at the first newline that follows the start of matching in
+ The offset limit facility can be used to track progress when searching
+ large subject strings or to limit the extent of global substitutions.
+ See also the PCRE2_FIRSTLINE option, which requires a match to start
+ before or at the first newline that follows the start of matching in
the subject. If this is set with an offset limit, a match must occur in
the first line and also within the offset limit. In other words, which-
ever limit comes first is used.
@@ -971,15 +984,15 @@ PCRE2 CONTEXTS
uint32_t value);
The heap_limit parameter specifies, in units of kibibytes (1024 bytes),
- the maximum amount of heap memory that pcre2_match() may use to hold
+ the maximum amount of heap memory that pcre2_match() may use to hold
backtracking information when running an interpretive match. This limit
also applies to pcre2_dfa_match(), which may use the heap when process-
- ing patterns with a lot of nested pattern recursion or lookarounds or
+ ing patterns with a lot of nested pattern recursion or lookarounds or
atomic groups. This limit does not apply to matching with the JIT opti-
- mization, which has its own memory control arrangements (see the
- pcre2jit documentation for more details). If the limit is reached, the
- negative error code PCRE2_ERROR_HEAPLIMIT is returned. The default
- limit can be set when PCRE2 is built; if it is not, the default is set
+ mization, which has its own memory control arrangements (see the
+ pcre2jit documentation for more details). If the limit is reached, the
+ negative error code PCRE2_ERROR_HEAPLIMIT is returned. The default
+ limit can be set when PCRE2 is built; if it is not, the default is set
very large and is essentially "unlimited".
A value for the heap limit may also be supplied by an item at the start
@@ -987,101 +1000,101 @@ PCRE2 CONTEXTS
(*LIMIT_HEAP=ddd)
- where ddd is a decimal number. However, such a setting is ignored
- unless ddd is less than the limit set by the caller of pcre2_match()
- or, if no such limit is set, less than the default.
+ where ddd is a decimal number. However, such a setting is ignored un-
+ less ddd is less than the limit set by the caller of pcre2_match() or,
+ if no such limit is set, less than the default.
- The pcre2_match() function starts out using a 20KiB vector on the sys-
+ The pcre2_match() function starts out using a 20KiB vector on the sys-
tem stack for recording backtracking points. The more nested backtrack-
- ing points there are (that is, the deeper the search tree), the more
- memory is needed. Heap memory is used only if the initial vector is
+ ing points there are (that is, the deeper the search tree), the more
+ memory is needed. Heap memory is used only if the initial vector is
too small. If the heap limit is set to a value less than 21 (in partic-
- ular, zero) no heap memory will be used. In this case, only patterns
- that do not have a lot of nested backtracking can be successfully pro-
+ ular, zero) no heap memory will be used. In this case, only patterns
+ that do not have a lot of nested backtracking can be successfully pro-
cessed.
- Similarly, for pcre2_dfa_match(), a vector on the system stack is used
- when processing pattern recursions, lookarounds, or atomic groups, and
- only if this is not big enough is heap memory used. In this case, too,
+ Similarly, for pcre2_dfa_match(), a vector on the system stack is used
+ when processing pattern recursions, lookarounds, or atomic groups, and
+ only if this is not big enough is heap memory used. In this case, too,
setting a value of zero disables the use of the heap.
int pcre2_set_match_limit(pcre2_match_context *mcontext,
uint32_t value);
- The match_limit parameter provides a means of preventing PCRE2 from
- using up too many computing resources when processing patterns that are
+ The match_limit parameter provides a means of preventing PCRE2 from us-
+ ing up too many computing resources when processing patterns that are
not going to match, but which have a very large number of possibilities
- in their search trees. The classic example is a pattern that uses
+ in their search trees. The classic example is a pattern that uses
nested unlimited repeats.
- There is an internal counter in pcre2_match() that is incremented each
- time round its main matching loop. If this value reaches the match
+ There is an internal counter in pcre2_match() that is incremented each
+ time round its main matching loop. If this value reaches the match
limit, pcre2_match() returns the negative value PCRE2_ERROR_MATCHLIMIT.
- This has the effect of limiting the amount of backtracking that can
+ This has the effect of limiting the amount of backtracking that can
take place. For patterns that are not anchored, the count restarts from
- zero for each position in the subject string. This limit also applies
+ zero for each position in the subject string. This limit also applies
to pcre2_dfa_match(), though the counting is done in a different way.
- When pcre2_match() is called with a pattern that was successfully pro-
+ When pcre2_match() is called with a pattern that was successfully pro-
cessed by pcre2_jit_compile(), the way in which matching is executed is
- entirely different. However, there is still the possibility of runaway
- matching that goes on for a very long time, and so the match_limit
- value is also used in this case (but in a different way) to limit how
+ entirely different. However, there is still the possibility of runaway
+ matching that goes on for a very long time, and so the match_limit
+ value is also used in this case (but in a different way) to limit how
long the matching can continue.
- The default value for the limit can be set when PCRE2 is built; the
- default default is 10 million, which handles all but the most extreme
- cases. A value for the match limit may also be supplied by an item at
+ The default value for the limit can be set when PCRE2 is built; the de-
+ fault default is 10 million, which handles all but the most extreme
+ cases. A value for the match limit may also be supplied by an item at
the start of a pattern of the form
(*LIMIT_MATCH=ddd)
- where ddd is a decimal number. However, such a setting is ignored
- unless ddd is less than the limit set by the caller of pcre2_match() or
+ where ddd is a decimal number. However, such a setting is ignored un-
+ less ddd is less than the limit set by the caller of pcre2_match() or
pcre2_dfa_match() or, if no such limit is set, less than the default.
int pcre2_set_depth_limit(pcre2_match_context *mcontext,
uint32_t value);
- This parameter limits the depth of nested backtracking in
- pcre2_match(). Each time a nested backtracking point is passed, a new
+ This parameter limits the depth of nested backtracking in
+ pcre2_match(). Each time a nested backtracking point is passed, a new
memory "frame" is used to remember the state of matching at that point.
- Thus, this parameter indirectly limits the amount of memory that is
- used in a match. However, because the size of each memory "frame"
- depends on the number of capturing parentheses, the actual memory limit
- varies from pattern to pattern. This limit was more useful in versions
+ Thus, this parameter indirectly limits the amount of memory that is
+ used in a match. However, because the size of each memory "frame" de-
+ pends on the number of capturing parentheses, the actual memory limit
+ varies from pattern to pattern. This limit was more useful in versions
before 10.30, where function recursion was used for backtracking.
- The depth limit is not relevant, and is ignored, when matching is done
+ The depth limit is not relevant, and is ignored, when matching is done
using JIT compiled code. However, it is supported by pcre2_dfa_match(),
- which uses it to limit the depth of nested internal recursive function
- calls that implement atomic groups, lookaround assertions, and pattern
+ which uses it to limit the depth of nested internal recursive function
+ calls that implement atomic groups, lookaround assertions, and pattern
recursions. This limits, indirectly, the amount of system stack that is
- used. It was more useful in versions before 10.32, when stack memory
+ used. It was more useful in versions before 10.32, when stack memory
was used for local workspace vectors for recursive function calls. From
- version 10.32, only local variables are allocated on the stack and as
+ version 10.32, only local variables are allocated on the stack and as
each call uses only a few hundred bytes, even a small stack can support
quite a lot of recursion.
- If the depth of internal recursive function calls is great enough,
- local workspace vectors are allocated on the heap from version 10.32
- onwards, so the depth limit also indirectly limits the amount of heap
+ If the depth of internal recursive function calls is great enough, lo-
+ cal workspace vectors are allocated on the heap from version 10.32 on-
+ wards, so the depth limit also indirectly limits the amount of heap
memory that is used. A recursive pattern such as /(.(?2))((?1)|)/, when
- matched to a very long string using pcre2_dfa_match(), can use a great
- deal of memory. However, it is probably better to limit heap usage
- directly by calling pcre2_set_heap_limit().
+ matched to a very long string using pcre2_dfa_match(), can use a great
+ deal of memory. However, it is probably better to limit heap usage di-
+ rectly by calling pcre2_set_heap_limit().
- The default value for the depth limit can be set when PCRE2 is built;
- if it is not, the default is set to the same value as the default for
- the match limit. If the limit is exceeded, pcre2_match() or
+ The default value for the depth limit can be set when PCRE2 is built;
+ if it is not, the default is set to the same value as the default for
+ the match limit. If the limit is exceeded, pcre2_match() or
pcre2_dfa_match() returns PCRE2_ERROR_DEPTHLIMIT. A value for the depth
- limit may also be supplied by an item at the start of a pattern of the
+ limit may also be supplied by an item at the start of a pattern of the
form
(*LIMIT_DEPTH=ddd)
- where ddd is a decimal number. However, such a setting is ignored
- unless ddd is less than the limit set by the caller of pcre2_match() or
+ where ddd is a decimal number. However, such a setting is ignored un-
+ less ddd is less than the limit set by the caller of pcre2_match() or
pcre2_dfa_match() or, if no such limit is set, less than the default.
@@ -1089,96 +1102,96 @@ CHECKING BUILD-TIME OPTIONS
int pcre2_config(uint32_t what, void *where);
- The function pcre2_config() makes it possible for a PCRE2 client to
- discover which optional features have been compiled into the PCRE2
- library. The pcre2build documentation has more details about these
- optional features.
-
- The first argument for pcre2_config() specifies which information is
- required. The second argument is a pointer to memory into which the
- information is placed. If NULL is passed, the function returns the
- amount of memory that is needed for the requested information. For
- calls that return numerical values, the value is in bytes; when
- requesting these values, where should point to appropriately aligned
- memory. For calls that return strings, the required length is given in
- code units, not counting the terminating zero.
-
- When requesting information, the returned value from pcre2_config() is
- non-negative on success, or the negative error code PCRE2_ERROR_BADOP-
- TION if the value in the first argument is not recognized. The follow-
+ The function pcre2_config() makes it possible for a PCRE2 client to
+ discover which optional features have been compiled into the PCRE2 li-
+ brary. The pcre2build documentation has more details about these op-
+ tional features.
+
+ The first argument for pcre2_config() specifies which information is
+ required. The second argument is a pointer to memory into which the in-
+ formation is placed. If NULL is passed, the function returns the amount
+ of memory that is needed for the requested information. For calls that
+ return numerical values, the value is in bytes; when requesting these
+ values, where should point to appropriately aligned memory. For calls
+ that return strings, the required length is given in code units, not
+ counting the terminating zero.
+
+ When requesting information, the returned value from pcre2_config() is
+ non-negative on success, or the negative error code PCRE2_ERROR_BADOP-
+ TION if the value in the first argument is not recognized. The follow-
ing information is available:
PCRE2_CONFIG_BSR
- The output is a uint32_t integer whose value indicates what character
- sequences the \R escape sequence matches by default. A value of
- PCRE2_BSR_UNICODE means that \R matches any Unicode line ending
- sequence; a value of PCRE2_BSR_ANYCRLF means that \R matches only CR,
- LF, or CRLF. The default can be overridden when a pattern is compiled.
+ The output is a uint32_t integer whose value indicates what character
+ sequences the \R escape sequence matches by default. A value of
+ PCRE2_BSR_UNICODE means that \R matches any Unicode line ending se-
+ quence; a value of PCRE2_BSR_ANYCRLF means that \R matches only CR, LF,
+ or CRLF. The default can be overridden when a pattern is compiled.
PCRE2_CONFIG_COMPILED_WIDTHS
- The output is a uint32_t integer whose lower bits indicate which code
- unit widths were selected when PCRE2 was built. The 1-bit indicates
- 8-bit support, and the 2-bit and 4-bit indicate 16-bit and 32-bit sup-
+ The output is a uint32_t integer whose lower bits indicate which code
+ unit widths were selected when PCRE2 was built. The 1-bit indicates
+ 8-bit support, and the 2-bit and 4-bit indicate 16-bit and 32-bit sup-
port, respectively.
PCRE2_CONFIG_DEPTHLIMIT
- The output is a uint32_t integer that gives the default limit for the
- depth of nested backtracking in pcre2_match() or the depth of nested
- recursions, lookarounds, and atomic groups in pcre2_dfa_match(). Fur-
+ The output is a uint32_t integer that gives the default limit for the
+ depth of nested backtracking in pcre2_match() or the depth of nested
+ recursions, lookarounds, and atomic groups in pcre2_dfa_match(). Fur-
ther details are given with pcre2_set_depth_limit() above.
PCRE2_CONFIG_HEAPLIMIT
- The output is a uint32_t integer that gives, in kibibytes, the default
- limit for the amount of heap memory used by pcre2_match() or
- pcre2_dfa_match(). Further details are given with
+ The output is a uint32_t integer that gives, in kibibytes, the default
+ limit for the amount of heap memory used by pcre2_match() or
+ pcre2_dfa_match(). Further details are given with
pcre2_set_heap_limit() above.
PCRE2_CONFIG_JIT
- The output is a uint32_t integer that is set to one if support for
+ The output is a uint32_t integer that is set to one if support for
just-in-time compiling is available; otherwise it is set to zero.
PCRE2_CONFIG_JITTARGET
- The where argument should point to a buffer that is at least 48 code
- units long. (The exact length required can be found by calling
- pcre2_config() with where set to NULL.) The buffer is filled with a
- string that contains the name of the architecture for which the JIT
- compiler is configured, for example "x86 32bit (little endian +
- unaligned)". If JIT support is not available, PCRE2_ERROR_BADOPTION is
- returned, otherwise the number of code units used is returned. This is
+ The where argument should point to a buffer that is at least 48 code
+ units long. (The exact length required can be found by calling
+ pcre2_config() with where set to NULL.) The buffer is filled with a
+ string that contains the name of the architecture for which the JIT
+ compiler is configured, for example "x86 32bit (little endian + un-
+ aligned)". If JIT support is not available, PCRE2_ERROR_BADOPTION is
+ returned, otherwise the number of code units used is returned. This is
the length of the string, plus one unit for the terminating zero.
PCRE2_CONFIG_LINKSIZE
The output is a uint32_t integer that contains the number of bytes used
- for internal linkage in compiled regular expressions. When PCRE2 is
- configured, the value can be set to 2, 3, or 4, with the default being
- 2. This is the value that is returned by pcre2_config(). However, when
- the 16-bit library is compiled, a value of 3 is rounded up to 4, and
- when the 32-bit library is compiled, internal linkages always use 4
+ for internal linkage in compiled regular expressions. When PCRE2 is
+ configured, the value can be set to 2, 3, or 4, with the default being
+ 2. This is the value that is returned by pcre2_config(). However, when
+ the 16-bit library is compiled, a value of 3 is rounded up to 4, and
+ when the 32-bit library is compiled, internal linkages always use 4
bytes, so the configured value is not relevant.
The default value of 2 for the 8-bit and 16-bit libraries is sufficient
- for all but the most massive patterns, since it allows the size of the
- compiled pattern to be up to 65535 code units. Larger values allow
- larger regular expressions to be compiled by those two libraries, but
+ for all but the most massive patterns, since it allows the size of the
+ compiled pattern to be up to 65535 code units. Larger values allow
+ larger regular expressions to be compiled by those two libraries, but
at the expense of slower matching.
PCRE2_CONFIG_MATCHLIMIT
The output is a uint32_t integer that gives the default match limit for
- pcre2_match(). Further details are given with pcre2_set_match_limit()
+ pcre2_match(). Further details are given with pcre2_set_match_limit()
above.
PCRE2_CONFIG_NEWLINE
- The output is a uint32_t integer whose value specifies the default
- character sequence that is recognized as meaning "newline". The values
+ The output is a uint32_t integer whose value specifies the default
+ character sequence that is recognized as meaning "newline". The values
are:
PCRE2_NEWLINE_CR Carriage return (CR)
@@ -1188,23 +1201,23 @@ CHECKING BUILD-TIME OPTIONS
PCRE2_NEWLINE_ANYCRLF Any of CR, LF, or CRLF
PCRE2_NEWLINE_NUL The NUL character (binary zero)
- The default should normally correspond to the standard sequence for
+ The default should normally correspond to the standard sequence for
your operating system.
PCRE2_CONFIG_NEVER_BACKSLASH_C
- The output is a uint32_t integer that is set to one if the use of \C
- was permanently disabled when PCRE2 was built; otherwise it is set to
+ The output is a uint32_t integer that is set to one if the use of \C
+ was permanently disabled when PCRE2 was built; otherwise it is set to
zero.
PCRE2_CONFIG_PARENSLIMIT
- The output is a uint32_t integer that gives the maximum depth of nest-
+ The output is a uint32_t integer that gives the maximum depth of nest-
ing of parentheses (of any kind) in a pattern. This limit is imposed to
- cap the amount of system stack used when a pattern is compiled. It is
- specified when PCRE2 is built; the default is 250. This limit does not
- take into account the stack that may already be used by the calling
- application. For finer control over compilation stack usage, see
+ cap the amount of system stack used when a pattern is compiled. It is
+ specified when PCRE2 is built; the default is 250. This limit does not
+ take into account the stack that may already be used by the calling ap-
+ plication. For finer control over compilation stack usage, see
pcre2_set_compile_recursion_guard().
PCRE2_CONFIG_STACKRECURSE
@@ -1214,25 +1227,25 @@ CHECKING BUILD-TIME OPTIONS
PCRE2_CONFIG_UNICODE_VERSION
- The where argument should point to a buffer that is at least 24 code
- units long. (The exact length required can be found by calling
- pcre2_config() with where set to NULL.) If PCRE2 has been compiled
- without Unicode support, the buffer is filled with the text "Unicode
- not supported". Otherwise, the Unicode version string (for example,
- "8.0.0") is inserted. The number of code units used is returned. This
+ The where argument should point to a buffer that is at least 24 code
+ units long. (The exact length required can be found by calling
+ pcre2_config() with where set to NULL.) If PCRE2 has been compiled
+ without Unicode support, the buffer is filled with the text "Unicode
+ not supported". Otherwise, the Unicode version string (for example,
+ "8.0.0") is inserted. The number of code units used is returned. This
is the length of the string plus one unit for the terminating zero.
PCRE2_CONFIG_UNICODE
- The output is a uint32_t integer that is set to one if Unicode support
- is available; otherwise it is set to zero. Unicode support implies UTF
+ The output is a uint32_t integer that is set to one if Unicode support
+ is available; otherwise it is set to zero. Unicode support implies UTF
support.
PCRE2_CONFIG_VERSION
- The where argument should point to a buffer that is at least 24 code
- units long. (The exact length required can be found by calling
- pcre2_config() with where set to NULL.) The buffer is filled with the
+ The where argument should point to a buffer that is at least 24 code
+ units long. (The exact length required can be found by calling
+ pcre2_config() with where set to NULL.) The buffer is filled with the
PCRE2 version string, zero-terminated. The number of code units used is
returned. This is the length of the string plus one unit for the termi-
nating zero.
@@ -1250,56 +1263,59 @@ COMPILING A PATTERN
pcre2_code *pcre2_code_copy_with_tables(const pcre2_code *code);
- The pcre2_compile() function compiles a pattern into an internal form.
- The pattern is defined by a pointer to a string of code units and a
- length (in code units). If the pattern is zero-terminated, the length
- can be specified as PCRE2_ZERO_TERMINATED. The function returns a
- pointer to a block of memory that contains the compiled pattern and
- related data, or NULL if an error occurred.
-
- If the compile context argument ccontext is NULL, memory for the com-
- piled pattern is obtained by calling malloc(). Otherwise, it is
- obtained from the same memory function that was used for the compile
- context. The caller must free the memory by calling pcre2_code_free()
- when it is no longer needed. If pcre2_code_free() is called with a
- NULL argument, it returns immediately, without doing anything.
+ The pcre2_compile() function compiles a pattern into an internal form.
+ The pattern is defined by a pointer to a string of code units and a
+ length (in code units). If the pattern is zero-terminated, the length
+ can be specified as PCRE2_ZERO_TERMINATED. The function returns a
+ pointer to a block of memory that contains the compiled pattern and re-
+ lated data, or NULL if an error occurred.
+
+ If the compile context argument ccontext is NULL, memory for the com-
+ piled pattern is obtained by calling malloc(). Otherwise, it is ob-
+ tained from the same memory function that was used for the compile con-
+ text. The caller must free the memory by calling pcre2_code_free() when
+ it is no longer needed. If pcre2_code_free() is called with a NULL ar-
+ gument, it returns immediately, without doing anything.
The function pcre2_code_copy() makes a copy of the compiled code in new
- memory, using the same memory allocator as was used for the original.
- However, if the code has been processed by the JIT compiler (see
- below), the JIT information cannot be copied (because it is position-
- dependent). The new copy can initially be used only for non-JIT match-
- ing, though it can be passed to pcre2_jit_compile() if required. If
+ memory, using the same memory allocator as was used for the original.
+ However, if the code has been processed by the JIT compiler (see be-
+ low), the JIT information cannot be copied (because it is position-de-
+ pendent). The new copy can initially be used only for non-JIT match-
+ ing, though it can be passed to pcre2_jit_compile() if required. If
pcre2_code_copy() is called with a NULL argument, it returns NULL.
The pcre2_code_copy() function provides a way for individual threads in
- a multithreaded application to acquire a private copy of shared com-
- piled code. However, it does not make a copy of the character tables
- used by the compiled pattern; the new pattern code points to the same
- tables as the original code. (See "Locale Support" below for details
- of these character tables.) In many applications the same tables are
- used throughout, so this behaviour is appropriate. Nevertheless, there
+ a multithreaded application to acquire a private copy of shared com-
+ piled code. However, it does not make a copy of the character tables
+ used by the compiled pattern; the new pattern code points to the same
+ tables as the original code. (See "Locale Support" below for details
+ of these character tables.) In many applications the same tables are
+ used throughout, so this behaviour is appropriate. Nevertheless, there
are occasions when a copy of a compiled pattern and the relevant tables
- are needed. The pcre2_code_copy_with_tables() provides this facility.
- Copies of both the code and the tables are made, with the new code
- pointing to the new tables. The memory for the new tables is automati-
- cally freed when pcre2_code_free() is called for the new copy of the
- compiled code. If pcre2_code_copy_withy_tables() is called with a NULL
+ are needed. The pcre2_code_copy_with_tables() provides this facility.
+ Copies of both the code and the tables are made, with the new code
+ pointing to the new tables. The memory for the new tables is automati-
+ cally freed when pcre2_code_free() is called for the new copy of the
+ compiled code. If pcre2_code_copy_with_tables() is called with a NULL
argument, it returns NULL.
- NOTE: When one of the matching functions is called, pointers to the
+ NOTE: When one of the matching functions is called, pointers to the
compiled pattern and the subject string are set in the match data block
- so that they can be referenced by the substring extraction functions.
- After running a match, you must not free a compiled pattern (or a sub-
- ject string) until after all operations on the match data block have
- taken place.
+ so that they can be referenced by the substring extraction functions
+ after a successful match. After running a match, you must not free a
+ compiled pattern or a subject string until after all operations on the
+ match data block have taken place, unless, in the case of the subject
+ string, you have used the PCRE2_COPY_MATCHED_SUBJECT option, which is
+ described in the section entitled "Option bits for pcre2_match()" be-
+ low.
The options argument for pcre2_compile() contains various bit settings
- that affect the compilation. It should be zero if no options are
- required. The available options are described below. Some of them (in
+ that affect the compilation. It should be zero if none of them are re-
+ quired. The available options are described below. Some of them (in
particular, those that are compatible with Perl, but some others as
- well) can also be set and unset from within the pattern (see the
- detailed description in the pcre2pattern documentation).
+ well) can also be set and unset from within the pattern (see the de-
+ tailed description in the pcre2pattern documentation).
For those options that can be different in different parts of the pat-
tern, the contents of the options argument specifies their settings at
@@ -1307,42 +1323,43 @@ COMPILING A PATTERN
PCRE2_NO_UTF_CHECK options can be set at the time of matching as well
as at compile time.
- Other, less frequently required compile-time parameters (for example,
- the newline setting) can be provided in a compile context (as described
- above).
+ Some additional options and less frequently required compile-time pa-
+ rameters (for example, the newline setting) can be provided in a com-
+ pile context (as described above).
If errorcode or erroroffset is NULL, pcre2_compile() returns NULL imme-
diately. Otherwise, the variables to which these point are set to an
- error code and an offset (number of code units) within the pattern,
- respectively, when pcre2_compile() returns NULL because a compilation
- error has occurred. The values are not defined when compilation is suc-
+ error code and an offset (number of code units) within the pattern, re-
+ spectively, when pcre2_compile() returns NULL because a compilation er-
+ ror has occurred. The values are not defined when compilation is suc-
cessful and pcre2_compile() returns a non-NULL value.
- There are nearly 100 positive error codes that pcre2_compile() may
- return if it finds an error in the pattern. There are also some nega-
- tive error codes that are used for invalid UTF strings. These are the
- same as given by pcre2_match() and pcre2_dfa_match(), and are described
- in the pcre2unicode page. There is no separate documentation for the
- positive error codes, because the textual error messages that are
- obtained by calling the pcre2_get_error_message() function (see
- "Obtaining a textual error message" below) should be self-explanatory.
- Macro names starting with PCRE2_ERROR_ are defined for both positive
- and negative error codes in pcre2.h.
+ There are nearly 100 positive error codes that pcre2_compile() may re-
+ turn if it finds an error in the pattern. There are also some negative
+ error codes that are used for invalid UTF strings when validity check-
+ ing is in force. These are the same as given by pcre2_match() and
+ pcre2_dfa_match(), and are described in the pcre2unicode documentation.
+ There is no separate documentation for the positive error codes, be-
+ cause the textual error messages that are obtained by calling the
+ pcre2_get_error_message() function (see "Obtaining a textual error mes-
+ sage" below) should be self-explanatory. Macro names starting with
+ PCRE2_ERROR_ are defined for both positive and negative error codes in
+ pcre2.h.
The value returned in erroroffset is an indication of where in the pat-
- tern the error occurred. It is not necessarily the furthest point in
- the pattern that was read. For example, after the error "lookbehind
- assertion is not fixed length", the error offset points to the start of
- the failing assertion. For an invalid UTF-8 or UTF-16 string, the off-
+ tern the error occurred. It is not necessarily the furthest point in
+ the pattern that was read. For example, after the error "lookbehind as-
+ sertion is not fixed length", the error offset points to the start of
+ the failing assertion. For an invalid UTF-8 or UTF-16 string, the off-
set is that of the first code unit of the failing character.
- Some errors are not detected until the whole pattern has been scanned;
- in these cases, the offset passed back is the length of the pattern.
- Note that the offset is in code units, not characters, even in a UTF
+ Some errors are not detected until the whole pattern has been scanned;
+ in these cases, the offset passed back is the length of the pattern.
+ Note that the offset is in code units, not characters, even in a UTF
mode. It may sometimes point into the middle of a UTF-8 or UTF-16 char-
acter.
- This code fragment shows a typical straightforward call to pcre2_com-
+ This code fragment shows a typical straightforward call to pcre2_com-
pile():
pcre2_code *re;
@@ -1356,151 +1373,159 @@ COMPILING A PATTERN
&erroffset, /* for error offset */
NULL); /* no compile context */
- The following names for option bits are defined in the pcre2.h header
+
+ Main compile options
+
+ The following names for option bits are defined in the pcre2.h header
file:
PCRE2_ANCHORED
If this bit is set, the pattern is forced to be "anchored", that is, it
- is constrained to match only at the first matching point in the string
- that is being searched (the "subject string"). This effect can also be
- achieved by appropriate constructs in the pattern itself, which is the
+ is constrained to match only at the first matching point in the string
+ that is being searched (the "subject string"). This effect can also be
+ achieved by appropriate constructs in the pattern itself, which is the
only way to do it in Perl.
PCRE2_ALLOW_EMPTY_CLASS
- By default, for compatibility with Perl, a closing square bracket that
- immediately follows an opening one is treated as a data character for
- the class. When PCRE2_ALLOW_EMPTY_CLASS is set, it terminates the
+ By default, for compatibility with Perl, a closing square bracket that
+ immediately follows an opening one is treated as a data character for
+ the class. When PCRE2_ALLOW_EMPTY_CLASS is set, it terminates the
class, which therefore contains no characters and so can never match.
PCRE2_ALT_BSUX
- This option request alternative handling of three escape sequences,
- which makes PCRE2's behaviour more like ECMAscript (aka JavaScript).
+ This option request alternative handling of three escape sequences,
+ which makes PCRE2's behaviour more like ECMAscript (aka JavaScript).
When it is set:
(1) \U matches an upper case "U" character; by default \U causes a com-
pile time error (Perl uses \U to upper case subsequent characters).
(2) \u matches a lower case "u" character unless it is followed by four
- hexadecimal digits, in which case the hexadecimal number defines the
- code point to match. By default, \u causes a compile time error (Perl
+ hexadecimal digits, in which case the hexadecimal number defines the
+ code point to match. By default, \u causes a compile time error (Perl
uses it to upper case the following character).
- (3) \x matches a lower case "x" character unless it is followed by two
- hexadecimal digits, in which case the hexadecimal number defines the
- code point to match. By default, as in Perl, a hexadecimal number is
+ (3) \x matches a lower case "x" character unless it is followed by two
+ hexadecimal digits, in which case the hexadecimal number defines the
+ code point to match. By default, as in Perl, a hexadecimal number is
always expected after \x, but it may have zero, one, or two digits (so,
for example, \xz matches a binary zero character followed by z).
+ ECMAscript 6 added additional functionality to \u. This can be accessed
+ using the PCRE2_EXTRA_ALT_BSUX extra option (see "Extra compile op-
+ tions" below). Note that this alternative escape handling applies only
+ to patterns. Neither of these options affects the processing of re-
+ placement strings passed to pcre2_substitute().
+
PCRE2_ALT_CIRCUMFLEX
In multiline mode (when PCRE2_MULTILINE is set), the circumflex
- metacharacter matches at the start of the subject (unless PCRE2_NOTBOL
- is set), and also after any internal newline. However, it does not
+ metacharacter matches at the start of the subject (unless PCRE2_NOTBOL
+ is set), and also after any internal newline. However, it does not
match after a newline at the end of the subject, for compatibility with
- Perl. If you want a multiline circumflex also to match after a termi-
+ Perl. If you want a multiline circumflex also to match after a termi-
nating newline, you must set PCRE2_ALT_CIRCUMFLEX.
PCRE2_ALT_VERBNAMES
- By default, for compatibility with Perl, the name in any verb sequence
- such as (*MARK:NAME) is any sequence of characters that does not
- include a closing parenthesis. The name is not processed in any way,
- and it is not possible to include a closing parenthesis in the name.
- However, if the PCRE2_ALT_VERBNAMES option is set, normal backslash
- processing is applied to verb names and only an unescaped closing
- parenthesis terminates the name. A closing parenthesis can be included
- in a name either as \) or between \Q and \E. If the PCRE2_EXTENDED or
- PCRE2_EXTENDED_MORE option is set with PCRE2_ALT_VERBNAMES, unescaped
- whitespace in verb names is skipped and #-comments are recognized,
- exactly as in the rest of the pattern.
+ By default, for compatibility with Perl, the name in any verb sequence
+ such as (*MARK:NAME) is any sequence of characters that does not in-
+ clude a closing parenthesis. The name is not processed in any way, and
+ it is not possible to include a closing parenthesis in the name. How-
+ ever, if the PCRE2_ALT_VERBNAMES option is set, normal backslash pro-
+ cessing is applied to verb names and only an unescaped closing paren-
+ thesis terminates the name. A closing parenthesis can be included in a
+ name either as \) or between \Q and \E. If the PCRE2_EXTENDED or
+ PCRE2_EXTENDED_MORE option is set with PCRE2_ALT_VERBNAMES, unescaped
+ whitespace in verb names is skipped and #-comments are recognized, ex-
+ actly as in the rest of the pattern.
PCRE2_AUTO_CALLOUT
- If this bit is set, pcre2_compile() automatically inserts callout
- items, all with number 255, before each pattern item, except immedi-
- ately before or after an explicit callout in the pattern. For discus-
+ If this bit is set, pcre2_compile() automatically inserts callout
+ items, all with number 255, before each pattern item, except immedi-
+ ately before or after an explicit callout in the pattern. For discus-
sion of the callout facility, see the pcre2callout documentation.
PCRE2_CASELESS
- If this bit is set, letters in the pattern match both upper and lower
- case letters in the subject. It is equivalent to Perl's /i option, and
- it can be changed within a pattern by a (?i) option setting. If
- PCRE2_UTF is set, Unicode properties are used for all characters with
- more than one other case, and for all characters whose code points are
- greater than U+007F. For lower valued characters with only one other
- case, a lookup table is used for speed. When PCRE2_UTF is not set, a
+ If this bit is set, letters in the pattern match both upper and lower
+ case letters in the subject. It is equivalent to Perl's /i option, and
+ it can be changed within a pattern by a (?i) option setting. If
+ PCRE2_UTF is set, Unicode properties are used for all characters with
+ more than one other case, and for all characters whose code points are
+ greater than U+007F. For lower valued characters with only one other
+ case, a lookup table is used for speed. When PCRE2_UTF is not set, a
lookup table is used for all code points less than 256, and higher code
- points (available only in 16-bit or 32-bit mode) are treated as not
+ points (available only in 16-bit or 32-bit mode) are treated as not
having another case.
PCRE2_DOLLAR_ENDONLY
- If this bit is set, a dollar metacharacter in the pattern matches only
- at the end of the subject string. Without this option, a dollar also
- matches immediately before a newline at the end of the string (but not
- before any other newlines). The PCRE2_DOLLAR_ENDONLY option is ignored
- if PCRE2_MULTILINE is set. There is no equivalent to this option in
+ If this bit is set, a dollar metacharacter in the pattern matches only
+ at the end of the subject string. Without this option, a dollar also
+ matches immediately before a newline at the end of the string (but not
+ before any other newlines). The PCRE2_DOLLAR_ENDONLY option is ignored
+ if PCRE2_MULTILINE is set. There is no equivalent to this option in
Perl, and no way to set it within a pattern.
PCRE2_DOTALL
- If this bit is set, a dot metacharacter in the pattern matches any
- character, including one that indicates a newline. However, it only
+ If this bit is set, a dot metacharacter in the pattern matches any
+ character, including one that indicates a newline. However, it only
ever matches one character, even if newlines are coded as CRLF. Without
this option, a dot does not match when the current position in the sub-
- ject is at a newline. This option is equivalent to Perl's /s option,
+ ject is at a newline. This option is equivalent to Perl's /s option,
and it can be changed within a pattern by a (?s) option setting. A neg-
- ative class such as [^a] always matches newline characters, and the \N
- escape sequence always matches a non-newline character, independent of
+ ative class such as [^a] always matches newline characters, and the \N
+ escape sequence always matches a non-newline character, independent of
the setting of PCRE2_DOTALL.
PCRE2_DUPNAMES
- If this bit is set, names used to identify capturing subpatterns need
- not be unique. This can be helpful for certain types of pattern when it
- is known that only one instance of the named subpattern can ever be
- matched. There are more details of named subpatterns below; see also
- the pcre2pattern documentation.
+ If this bit is set, names used to identify capture groups need not be
+ unique. This can be helpful for certain types of pattern when it is
+ known that only one instance of the named group can ever be matched.
+ There are more details of named capture groups below; see also the
+ pcre2pattern documentation.
PCRE2_ENDANCHORED
- If this bit is set, the end of any pattern match must be right at the
+ If this bit is set, the end of any pattern match must be right at the
end of the string being searched (the "subject string"). If the pattern
match succeeds by reaching (*ACCEPT), but does not reach the end of the
- subject, the match fails at the current starting point. For unanchored
- patterns, a new match is then tried at the next starting point. How-
+ subject, the match fails at the current starting point. For unanchored
+ patterns, a new match is then tried at the next starting point. How-
ever, if the match succeeds by reaching the end of the pattern, but not
- the end of the subject, backtracking occurs and an alternative match
+ the end of the subject, backtracking occurs and an alternative match
may be found. Consider these two patterns:
.(*ACCEPT)|..
.|..
- If matched against "abc" with PCRE2_ENDANCHORED set, the first matches
- "c" whereas the second matches "bc". The effect of PCRE2_ENDANCHORED
- can also be achieved by appropriate constructs in the pattern itself,
+ If matched against "abc" with PCRE2_ENDANCHORED set, the first matches
+ "c" whereas the second matches "bc". The effect of PCRE2_ENDANCHORED
+ can also be achieved by appropriate constructs in the pattern itself,
which is the only way to do it in Perl.
For DFA matching with pcre2_dfa_match(), PCRE2_ENDANCHORED applies only
- to the first (that is, the longest) matched string. Other parallel
- matches, which are necessarily substrings of the first one, must obvi-
+ to the first (that is, the longest) matched string. Other parallel
+ matches, which are necessarily substrings of the first one, must obvi-
ously end before the end of the subject.
PCRE2_EXTENDED
- If this bit is set, most white space characters in the pattern are
- totally ignored except when escaped or inside a character class. How-
- ever, white space is not allowed within sequences such as (?> that
- introduce various parenthesized subpatterns, nor within numerical quan-
- tifiers such as {1,3}. Ignorable white space is permitted between an
- item and a following quantifier and between a quantifier and a follow-
- ing + that indicates possessiveness. PCRE2_EXTENDED is equivalent to
- Perl's /x option, and it can be changed within a pattern by a (?x)
- option setting.
+ If this bit is set, most white space characters in the pattern are to-
+ tally ignored except when escaped or inside a character class. However,
+ white space is not allowed within sequences such as (?> that introduce
+ various parenthesized groups, nor within numerical quantifiers such as
+ {1,3}. Ignorable white space is permitted between an item and a follow-
+ ing quantifier and between a quantifier and a following + that indi-
+ cates possessiveness. PCRE2_EXTENDED is equivalent to Perl's /x option,
+ and it can be changed within a pattern by a (?x) option setting.
When PCRE2 is compiled without Unicode support, PCRE2_EXTENDED recog-
nizes as white space only those characters with code points less than
@@ -1535,48 +1560,54 @@ COMPILING A PATTERN
PCRE2_EXTENDED_MORE
- This option has the effect of PCRE2_EXTENDED, but, in addition,
- unescaped space and horizontal tab characters are ignored inside a
- character class. Note: only these two characters are ignored, not the
- full set of pattern white space characters that are ignored outside a
- character class. PCRE2_EXTENDED_MORE is equivalent to Perl's /xx
- option, and it can be changed within a pattern by a (?xx) option set-
- ting.
+ This option has the effect of PCRE2_EXTENDED, but, in addition, un-
+ escaped space and horizontal tab characters are ignored inside a char-
+ acter class. Note: only these two characters are ignored, not the full
+ set of pattern white space characters that are ignored outside a char-
+ acter class. PCRE2_EXTENDED_MORE is equivalent to Perl's /xx option,
+ and it can be changed within a pattern by a (?xx) option setting.
PCRE2_FIRSTLINE
If this option is set, the start of an unanchored pattern match must be
- before or at the first newline in the subject string following the
- start of matching, though the matched text may continue over the new-
+ before or at the first newline in the subject string following the
+ start of matching, though the matched text may continue over the new-
line. If startoffset is non-zero, the limiting newline is not necessar-
- ily the first newline in the subject. For example, if the subject
+ ily the first newline in the subject. For example, if the subject
string is "abc\nxyz" (where \n represents a single-character newline) a
- pattern match for "yz" succeeds with PCRE2_FIRSTLINE if startoffset is
- greater than 3. See also PCRE2_USE_OFFSET_LIMIT, which provides a more
- general limiting facility. If PCRE2_FIRSTLINE is set with an offset
- limit, a match must occur in the first line and also within the offset
+ pattern match for "yz" succeeds with PCRE2_FIRSTLINE if startoffset is
+ greater than 3. See also PCRE2_USE_OFFSET_LIMIT, which provides a more
+ general limiting facility. If PCRE2_FIRSTLINE is set with an offset
+ limit, a match must occur in the first line and also within the offset
limit. In other words, whichever limit comes first is used.
PCRE2_LITERAL
If this option is set, all meta-characters in the pattern are disabled,
- and it is treated as a literal string. Matching literal strings with a
+ and it is treated as a literal string. Matching literal strings with a
regular expression engine is not the most efficient way of doing it. If
- you are doing a lot of literal matching and are worried about effi-
+ you are doing a lot of literal matching and are worried about effi-
ciency, you should consider using other approaches. The only other main
options that are allowed with PCRE2_LITERAL are: PCRE2_ANCHORED,
PCRE2_ENDANCHORED, PCRE2_AUTO_CALLOUT, PCRE2_CASELESS, PCRE2_FIRSTLINE,
- PCRE2_NO_START_OPTIMIZE, PCRE2_NO_UTF_CHECK, PCRE2_UTF, and
- PCRE2_USE_OFFSET_LIMIT. The extra options PCRE2_EXTRA_MATCH_LINE and
- PCRE2_EXTRA_MATCH_WORD are also supported. Any other options cause an
- error.
+ PCRE2_MATCH_INVALID_UTF, PCRE2_NO_START_OPTIMIZE, PCRE2_NO_UTF_CHECK,
+ PCRE2_UTF, and PCRE2_USE_OFFSET_LIMIT. The extra options PCRE2_EX-
+ TRA_MATCH_LINE and PCRE2_EXTRA_MATCH_WORD are also supported. Any other
+ options cause an error.
+
+ PCRE2_MATCH_INVALID_UTF
+
+ This option forces PCRE2_UTF (see below) and also enables support for
+ matching by pcre2_match() in subject strings that contain invalid UTF
+ sequences. This facility is not supported for DFA matching. For de-
+ tails, see the pcre2unicode documentation.
PCRE2_MATCH_UNSET_BACKREF
- If this option is set, a backreference to an unset subpattern group
+ If this option is set, a backreference to an unset capture group
matches an empty string (by default this causes the current matching
- alternative to fail). A pattern such as (\1)(a) succeeds when this
- option is set (assuming it can find an "a" in the subject), whereas it
+ alternative to fail). A pattern such as (\1)(a) succeeds when this op-
+ tion is set (assuming it can find an "a" in the subject), whereas it
fails by default, for Perl compatibility. Setting this option makes
PCRE2 behave more like ECMAscript (aka JavaScript).
@@ -1587,10 +1618,10 @@ COMPILING A PATTERN
of characters, even if it actually contains newlines. The "start of
line" metacharacter (^) matches only at the start of the string, and
the "end of line" metacharacter ($) matches only at the end of the
- string, or before a terminating newline (except when PCRE2_DOL-
- LAR_ENDONLY is set). Note, however, that unless PCRE2_DOTALL is set,
- the "any character" metacharacter (.) does not match at a newline. This
- behaviour (for ^, $, and dot) is the same as Perl.
+ string, or before a terminating newline (except when PCRE2_DOLLAR_EN-
+ DONLY is set). Note, however, that unless PCRE2_DOTALL is set, the "any
+ character" metacharacter (.) does not match at a newline. This behav-
+ iour (for ^, $, and dot) is the same as Perl.
When PCRE2_MULTILINE it is set, the "start of line" and "end of line"
constructs match immediately following or immediately before internal
@@ -1608,118 +1639,122 @@ COMPILING A PATTERN
This option locks out the use of \C in the pattern that is being com-
piled. This escape can cause unpredictable behaviour in UTF-8 or
UTF-16 modes, because it may leave the current matching point in the
- middle of a multi-code-unit character. This option may be useful in
- applications that process patterns from external sources. Note that
- there is also a build-time option that permanently locks out the use of
- \C.
+ middle of a multi-code-unit character. This option may be useful in ap-
+ plications that process patterns from external sources. Note that there
+ is also a build-time option that permanently locks out the use of \C.
PCRE2_NEVER_UCP
- This option locks out the use of Unicode properties for handling \B,
+ This option locks out the use of Unicode properties for handling \B,
\b, \D, \d, \S, \s, \W, \w, and some of the POSIX character classes, as
- described for the PCRE2_UCP option below. In particular, it prevents
- the creator of the pattern from enabling this facility by starting the
- pattern with (*UCP). This option may be useful in applications that
+ described for the PCRE2_UCP option below. In particular, it prevents
+ the creator of the pattern from enabling this facility by starting the
+ pattern with (*UCP). This option may be useful in applications that
process patterns from external sources. The option combination PCRE_UCP
and PCRE_NEVER_UCP causes an error.
PCRE2_NEVER_UTF
- This option locks out interpretation of the pattern as UTF-8, UTF-16,
+ This option locks out interpretation of the pattern as UTF-8, UTF-16,
or UTF-32, depending on which library is in use. In particular, it pre-
- vents the creator of the pattern from switching to UTF interpretation
- by starting the pattern with (*UTF). This option may be useful in
- applications that process patterns from external sources. The combina-
- tion of PCRE2_UTF and PCRE2_NEVER_UTF causes an error.
+ vents the creator of the pattern from switching to UTF interpretation
+ by starting the pattern with (*UTF). This option may be useful in ap-
+ plications that process patterns from external sources. The combination
+ of PCRE2_UTF and PCRE2_NEVER_UTF causes an error.
PCRE2_NO_AUTO_CAPTURE
If this option is set, it disables the use of numbered capturing paren-
- theses in the pattern. Any opening parenthesis that is not followed by
- ? behaves as if it were followed by ?: but named parentheses can still
+ theses in the pattern. Any opening parenthesis that is not followed by
+ ? behaves as if it were followed by ?: but named parentheses can still
be used for capturing (and they acquire numbers in the usual way). This
- is the same as Perl's /n option. Note that, when this option is set,
- references to capturing groups (backreferences or recursion/subroutine
- calls) may only refer to named groups, though the reference can be by
+ is the same as Perl's /n option. Note that, when this option is set,
+ references to capture groups (backreferences or recursion/subroutine
+ calls) may only refer to named groups, though the reference can be by
name or by number.
PCRE2_NO_AUTO_POSSESS
If this option is set, it disables "auto-possessification", which is an
- optimization that, for example, turns a+b into a++b in order to avoid
- backtracks into a+ that can never be successful. However, if callouts
- are in use, auto-possessification means that some callouts are never
+ optimization that, for example, turns a+b into a++b in order to avoid
+ backtracks into a+ that can never be successful. However, if callouts
+ are in use, auto-possessification means that some callouts are never
taken. You can set this option if you want the matching functions to do
- a full unoptimized search and run all the callouts, but it is mainly
+ a full unoptimized search and run all the callouts, but it is mainly
provided for testing purposes.
PCRE2_NO_DOTSTAR_ANCHOR
If this option is set, it disables an optimization that is applied when
- .* is the first significant item in a top-level branch of a pattern,
- and all the other branches also start with .* or with \A or \G or ^.
- The optimization is automatically disabled for .* if it is inside an
- atomic group or a capturing group that is the subject of a backrefer-
- ence, or if the pattern contains (*PRUNE) or (*SKIP). When the opti-
- mization is not disabled, such a pattern is automatically anchored if
+ .* is the first significant item in a top-level branch of a pattern,
+ and all the other branches also start with .* or with \A or \G or ^.
+ The optimization is automatically disabled for .* if it is inside an
+ atomic group or a capture group that is the subject of a backreference,
+ or if the pattern contains (*PRUNE) or (*SKIP). When the optimization
+ is not disabled, such a pattern is automatically anchored if
PCRE2_DOTALL is set for all the .* items and PCRE2_MULTILINE is not set
- for any ^ items. Otherwise, the fact that any match must start either
- at the start of the subject or following a newline is remembered. Like
+ for any ^ items. Otherwise, the fact that any match must start either
+ at the start of the subject or following a newline is remembered. Like
other optimizations, this can cause callouts to be skipped.
PCRE2_NO_START_OPTIMIZE
- This is an option whose main effect is at matching time. It does not
+ This is an option whose main effect is at matching time. It does not
change what pcre2_compile() generates, but it does affect the output of
the JIT compiler.
- There are a number of optimizations that may occur at the start of a
- match, in order to speed up the process. For example, if it is known
- that an unanchored match must start with a specific code unit value,
- the matching code searches the subject for that value, and fails imme-
- diately if it cannot find it, without actually running the main match-
- ing function. This means that a special item such as (*COMMIT) at the
- start of a pattern is not considered until after a suitable starting
- point for the match has been found. Also, when callouts or (*MARK)
- items are in use, these "start-up" optimizations can cause them to be
- skipped if the pattern is never actually used. The start-up optimiza-
- tions are in effect a pre-scan of the subject that takes place before
+ There are a number of optimizations that may occur at the start of a
+ match, in order to speed up the process. For example, if it is known
+ that an unanchored match must start with a specific code unit value,
+ the matching code searches the subject for that value, and fails imme-
+ diately if it cannot find it, without actually running the main match-
+ ing function. This means that a special item such as (*COMMIT) at the
+ start of a pattern is not considered until after a suitable starting
+ point for the match has been found. Also, when callouts or (*MARK)
+ items are in use, these "start-up" optimizations can cause them to be
+ skipped if the pattern is never actually used. The start-up optimiza-
+ tions are in effect a pre-scan of the subject that takes place before
the pattern is run.
The PCRE2_NO_START_OPTIMIZE option disables the start-up optimizations,
- possibly causing performance to suffer, but ensuring that in cases
- where the result is "no match", the callouts do occur, and that items
+ possibly causing performance to suffer, but ensuring that in cases
+ where the result is "no match", the callouts do occur, and that items
such as (*COMMIT) and (*MARK) are considered at every possible starting
position in the subject string.
- Setting PCRE2_NO_START_OPTIMIZE may change the outcome of a matching
+ Setting PCRE2_NO_START_OPTIMIZE may change the outcome of a matching
operation. Consider the pattern
(*COMMIT)ABC
- When this is compiled, PCRE2 records the fact that a match must start
- with the character "A". Suppose the subject string is "DEFABC". The
- start-up optimization scans along the subject, finds "A" and runs the
- first match attempt from there. The (*COMMIT) item means that the pat-
- tern must match the current starting position, which in this case, it
- does. However, if the same match is run with PCRE2_NO_START_OPTIMIZE
- set, the initial scan along the subject string does not happen. The
- first match attempt is run starting from "D" and when this fails,
- (*COMMIT) prevents any further matches being tried, so the overall
- result is "no match".
-
- There are also other start-up optimizations. For example, a minimum
- length for the subject may be recorded. Consider the pattern
-
- (*MARK:A)(X|Y)
-
- The minimum length for a match is one character. If the subject is
- "ABC", there will be attempts to match "ABC", "BC", and "C". An attempt
- to match an empty string at the end of the subject does not take place,
- because PCRE2 knows that the subject is now too short, and so the
- (*MARK) is never encountered. In this case, the optimization does not
- affect the overall match result, which is still "no match", but it does
- affect the auxiliary information that is returned.
+ When this is compiled, PCRE2 records the fact that a match must start
+ with the character "A". Suppose the subject string is "DEFABC". The
+ start-up optimization scans along the subject, finds "A" and runs the
+ first match attempt from there. The (*COMMIT) item means that the pat-
+ tern must match the current starting position, which in this case, it
+ does. However, if the same match is run with PCRE2_NO_START_OPTIMIZE
+ set, the initial scan along the subject string does not happen. The
+ first match attempt is run starting from "D" and when this fails,
+ (*COMMIT) prevents any further matches being tried, so the overall re-
+ sult is "no match".
+
+ As another start-up optimization makes use of a minimum length for a
+ matching subject, which is recorded when possible. Consider the pattern
+
+ (*MARK:1)B(*MARK:2)(X|Y)
+
+ The minimum length for a match is two characters. If the subject is
+ "XXBB", the "starting character" optimization skips "XX", then tries to
+ match "BB", which is long enough. In the process, (*MARK:2) is encoun-
+ tered and remembered. When the match attempt fails, the next "B" is
+ found, but there is only one character left, so there are no more at-
+ tempts, and "no match" is returned with the "last mark seen" set to
+ "2". If NO_START_OPTIMIZE is set, however, matches are tried at every
+ possible starting position, including at the end of the subject, where
+ (*MARK:1) is encountered, but there is no "B", so the "last mark seen"
+ that is returned is "1". In this case, the optimizations do not affect
+ the overall match result, which is still "no match", but they do affect
+ the auxiliary information that is returned.
PCRE2_NO_UTF_CHECK
@@ -1731,8 +1766,8 @@ COMPILING A PATTERN
If you know that your pattern is a valid UTF string, and you want to
skip this check for performance reasons, you can set the
- PCRE2_NO_UTF_CHECK option. When it is set, the effect of passing an
- invalid UTF string as a pattern is undefined. It may cause your program
+ PCRE2_NO_UTF_CHECK option. When it is set, the effect of passing an in-
+ valid UTF string as a pattern is undefined. It may cause your program
to crash or loop.
Note that this option can also be passed to pcre2_match() and
@@ -1772,8 +1807,8 @@ COMPILING A PATTERN
This option must be set for pcre2_compile() if pcre2_set_offset_limit()
is going to be used to set a non-default offset limit in a match con-
text for matches that use this pattern. An error is generated if an
- offset limit is set without this option. For more details, see the
- description of pcre2_set_offset_limit() in the section that describes
+ offset limit is set without this option. For more details, see the de-
+ scription of pcre2_set_offset_limit() in the section that describes
match contexts. See also the PCRE2_FIRSTLINE option above.
PCRE2_UTF
@@ -1782,17 +1817,15 @@ COMPILING A PATTERN
strings that are subsequently processed as strings of UTF characters
instead of single-code-unit strings. It is available when PCRE2 is
built to include Unicode support (which is the default). If Unicode
- support is not available, the use of this option provokes an error.
- Details of how PCRE2_UTF changes the behaviour of PCRE2 are given in
- the pcre2unicode page. In particular, note that it changes the way
+ support is not available, the use of this option provokes an error. De-
+ tails of how PCRE2_UTF changes the behaviour of PCRE2 are given in the
+ pcre2unicode page. In particular, note that it changes the way
PCRE2_CASELESS handles characters with code points greater than 127.
Extra compile options
- Unlike the main compile-time options, the extra options are not saved
- with the compiled pattern. The option bits that can be set in a compile
- context by calling the pcre2_set_compile_extra_options() function are
- as follows:
+ The option bits that can be set in a compile context by calling the
+ pcre2_set_compile_extra_options() function are as follows:
PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES
@@ -1807,18 +1840,26 @@ COMPILING A PATTERN
These values also cause errors if encountered in escape sequences such
as \x{d912} within a pattern. However, it seems that some applications,
- when using PCRE2 to check for unwanted characters in UTF-8 strings,
- explicitly test for the surrogates using escape sequences. The
- PCRE2_NO_UTF_CHECK option does not disable the error that occurs,
- because it applies only to the testing of input strings for UTF valid-
- ity.
-
- If the extra option PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is set, surro-
- gate code point values in UTF-8 and UTF-32 patterns no longer provoke
- errors and are incorporated in the compiled pattern. However, they can
- only match subject characters if the matching function is called with
+ when using PCRE2 to check for unwanted characters in UTF-8 strings, ex-
+ plicitly test for the surrogates using escape sequences. The
+ PCRE2_NO_UTF_CHECK option does not disable the error that occurs, be-
+ cause it applies only to the testing of input strings for UTF validity.
+
+ If the extra option PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is set, surro-
+ gate code point values in UTF-8 and UTF-32 patterns no longer provoke
+ errors and are incorporated in the compiled pattern. However, they can
+ only match subject characters if the matching function is called with
PCRE2_NO_UTF_CHECK set.
+ PCRE2_EXTRA_ALT_BSUX
+
+ The original option PCRE2_ALT_BSUX causes PCRE2 to process \U, \u, and
+ \x in the way that ECMAscript (aka JavaScript) does. Additional func-
+ tionality was defined by ECMAscript 6; setting PCRE2_EXTRA_ALT_BSUX has
+ the effect of PCRE2_ALT_BSUX, but in addition it recognizes \u{hhh..}
+ as a hexadecimal character code, where hhh.. is any number of hexadeci-
+ mal digits.
+
PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL
This is a dangerous option. Use with care. By default, an unrecognized
@@ -1831,28 +1872,41 @@ COMPILING A PATTERN
Perl.
If the PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL extra option is passed to
- pcre2_compile(), all unrecognized or erroneous escape sequences are
+ pcre2_compile(), all unrecognized or malformed escape sequences are
treated as single-character escapes. For example, \j is a literal "j"
- and \x{2z} is treated as the literal string "x{2z}". Setting this
- option means that typos in patterns may go undetected and have unex-
- pected results. This is a dangerous option. Use with care.
+ and \x{2z} is treated as the literal string "x{2z}". Setting this op-
+ tion means that typos in patterns may go undetected and have unexpected
+ results. Also note that a sequence such as [\N{] is interpreted as a
+ malformed attempt at [\N{...}] and so is treated as [N{] whereas [\N]
+ gives an error because an unqualified \N is a valid escape sequence but
+ is not supported in a character class. To reiterate: this is a danger-
+ ous option. Use with great care.
+
+ PCRE2_EXTRA_ESCAPED_CR_IS_LF
+
+ There are some legacy applications where the escape sequence \r in a
+ pattern is expected to match a newline. If this option is set, \r in a
+ pattern is converted to \n so that it matches a LF (linefeed) instead
+ of a CR (carriage return) character. The option does not affect a lit-
+ eral CR in the pattern, nor does it affect CR specified as an explicit
+ code point such as \x{0D}.
PCRE2_EXTRA_MATCH_LINE
- This option is provided for use by the -x option of pcre2grep. It
- causes the pattern only to match complete lines. This is achieved by
- automatically inserting the code for "^(?:" at the start of the com-
- piled pattern and ")$" at the end. Thus, when PCRE2_MULTILINE is set,
- the matched line may be in the middle of the subject string. This
- option can be used with PCRE2_LITERAL.
+ This option is provided for use by the -x option of pcre2grep. It
+ causes the pattern only to match complete lines. This is achieved by
+ automatically inserting the code for "^(?:" at the start of the com-
+ piled pattern and ")$" at the end. Thus, when PCRE2_MULTILINE is set,
+ the matched line may be in the middle of the subject string. This op-
+ tion can be used with PCRE2_LITERAL.
PCRE2_EXTRA_MATCH_WORD
- This option is provided for use by the -w option of pcre2grep. It
- causes the pattern only to match strings that have a word boundary at
- the start and the end. This is achieved by automatically inserting the
- code for "\b(?:" at the start of the compiled pattern and ")\b" at the
- end. The option may be used with PCRE2_LITERAL. However, it is ignored
+ This option is provided for use by the -w option of pcre2grep. It
+ causes the pattern only to match strings that have a word boundary at
+ the start and the end. This is achieved by automatically inserting the
+ code for "\b(?:" at the start of the compiled pattern and ")\b" at the
+ end. The option may be used with PCRE2_LITERAL. However, it is ignored
if PCRE2_EXTRA_MATCH_LINE is also set.
@@ -1875,54 +1929,63 @@ JUST-IN-TIME (JIT) COMPILATION
void pcre2_jit_stack_free(pcre2_jit_stack *jit_stack);
- These functions provide support for JIT compilation, which, if the
- just-in-time compiler is available, further processes a compiled pat-
+ These functions provide support for JIT compilation, which, if the
+ just-in-time compiler is available, further processes a compiled pat-
tern into machine code that executes much faster than the pcre2_match()
- interpretive matching function. Full details are given in the pcre2jit
+ interpretive matching function. Full details are given in the pcre2jit
documentation.
- JIT compilation is a heavyweight optimization. It can take some time
- for patterns to be analyzed, and for one-off matches and simple pat-
- terns the benefit of faster execution might be offset by a much slower
- compilation time. Most (but not all) patterns can be optimized by the
+ JIT compilation is a heavyweight optimization. It can take some time
+ for patterns to be analyzed, and for one-off matches and simple pat-
+ terns the benefit of faster execution might be offset by a much slower
+ compilation time. Most (but not all) patterns can be optimized by the
JIT compiler.
LOCALE SUPPORT
- PCRE2 handles caseless matching, and determines whether characters are
- letters, digits, or whatever, by reference to a set of tables, indexed
- by character code point. This applies only to characters whose code
- points are less than 256. By default, higher-valued code points never
- match escapes such as \w or \d. However, if PCRE2 is built with Uni-
- code support, all characters can be tested with \p and \P, or, alterna-
- tively, the PCRE2_UCP option can be set when a pattern is compiled;
- this causes \w and friends to use Unicode property support instead of
- the built-in tables.
-
- The use of locales with Unicode is discouraged. If you are handling
- characters with code points greater than 128, you should either use
+ const uint8_t *pcre2_maketables(pcre2_general_context *gcontext);
+
+ void pcre2_maketables_free(pcre2_general_context *gcontext,
+ const uint8_t *tables);
+
+ PCRE2 handles caseless matching, and determines whether characters are
+ letters, digits, or whatever, by reference to a set of tables, indexed
+ by character code point. However, this applies only to characters whose
+ code points are less than 256. By default, higher-valued code points
+ never match escapes such as \w or \d. When PCRE2 is built with Unicode
+ support (the default), all characters can be tested with \p and \P, or,
+ alternatively, the PCRE2_UCP option can be set when a pattern is com-
+ piled; this causes \w and friends to use Unicode property support in-
+ stead of the built-in tables.
+
+ The use of locales with Unicode is discouraged. If you are handling
+ characters with code points greater than 128, you should either use
Unicode support, or use locales, but not try to mix the two.
- PCRE2 contains an internal set of character tables that are used by
- default. These are sufficient for many applications. Normally, the
- internal tables recognize only ASCII characters. However, when PCRE2 is
+ PCRE2 contains a built-in set of character tables that are used by de-
+ fault. These are sufficient for many applications. Normally, the in-
+ ternal tables recognize only ASCII characters. However, when PCRE2 is
built, it is possible to cause the internal tables to be rebuilt in the
default "C" locale of the local system, which may cause them to be dif-
ferent.
- The internal tables can be overridden by tables supplied by the appli-
- cation that calls PCRE2. These may be created in a different locale
- from the default. As more and more applications change to using Uni-
+ The built-in tables can be overridden by tables supplied by the appli-
+ cation that calls PCRE2. These may be created in a different locale
+ from the default. As more and more applications change to using Uni-
code, the need for this locale support is expected to die away.
- External tables are built by calling the pcre2_maketables() function,
- in the relevant locale. The result can be passed to pcre2_compile() as
- often as necessary, by creating a compile context and calling
- pcre2_set_character_tables() to set the tables pointer therein. For
- example, to build and use tables that are appropriate for the French
- locale (where accented characters with values greater than 128 are
- treated as letters), the following code could be used:
+ External tables are built by calling the pcre2_maketables() function,
+ in the relevant locale. The only argument to this function is a general
+ context, which can be used to pass a custom memory allocator. If the
+ argument is NULL, the system malloc() is used. The result can be passed
+ to pcre2_compile() as often as necessary, by creating a compile context
+ and calling pcre2_set_character_tables() to set the tables pointer
+ therein.
+
+ For example, to build and use tables that are appropriate for the
+ French locale (where accented characters with values greater than 128
+ are treated as letters), the following code could be used:
setlocale(LC_CTYPE, "fr_FR");
tables = pcre2_maketables(NULL);
@@ -1930,29 +1993,33 @@ LOCALE SUPPORT
pcre2_set_character_tables(ccontext, tables);
re = pcre2_compile(..., ccontext);
- The locale name "fr_FR" is used on Linux and other Unix-like systems;
- if you are using Windows, the name for the French locale is "french".
- It is the caller's responsibility to ensure that the memory containing
- the tables remains available for as long as it is needed.
+ The locale name "fr_FR" is used on Linux and other Unix-like systems;
+ if you are using Windows, the name for the French locale is "french".
The pointer that is passed (via the compile context) to pcre2_compile()
- is saved with the compiled pattern, and the same tables are used by
- pcre2_match() and pcre_dfa_match(). Thus, for any single pattern, com-
- pilation and matching both happen in the same locale, but different
+ is saved with the compiled pattern, and the same tables are used by
+ pcre2_match() and pcre_dfa_match(). Thus, for any single pattern, com-
+ pilation and matching both happen in the same locale, but different
patterns can be processed in different locales.
+ It is the caller's responsibility to ensure that the memory containing
+ the tables remains available while they are still in use. When they are
+ no longer needed, you can discard them using pcre2_maketables_free(),
+ which should pass as its first parameter the same global context that
+ was used to create the tables.
+
INFORMATION ABOUT A COMPILED PATTERN
int pcre2_pattern_info(const pcre2 *code, uint32_t what, void *where);
- The pcre2_pattern_info() function returns general information about a
+ The pcre2_pattern_info() function returns general information about a
compiled pattern. For information about callouts, see the next section.
- The first argument for pcre2_pattern_info() is a pointer to the com-
+ The first argument for pcre2_pattern_info() is a pointer to the com-
piled pattern. The second argument specifies which piece of information
- is required, and the third argument is a pointer to a variable to
- receive the data. If the third argument is NULL, the first argument is
- ignored, and the function returns the size in bytes of the variable
+ is required, and the third argument is a pointer to a variable to re-
+ ceive the data. If the third argument is NULL, the first argument is
+ ignored, and the function returns the size in bytes of the variable
that is required for the information requested. Otherwise, the yield of
the function is zero for success, or one of the following negative num-
bers:
@@ -1962,9 +2029,9 @@ INFORMATION ABOUT A COMPILED PATTERN
PCRE2_ERROR_BADOPTION the value of what was invalid
PCRE2_ERROR_UNSET the requested field is not set
- The "magic number" is placed at the start of each compiled pattern as
- an simple check against passing an arbitrary memory pointer. Here is a
- typical call of pcre2_pattern_info(), to obtain the length of the com-
+ The "magic number" is placed at the start of each compiled pattern as a
+ simple check against passing an arbitrary memory pointer. Here is a
+ typical call of pcre2_pattern_info(), to obtain the length of the com-
piled pattern:
int rc;
@@ -1982,22 +2049,22 @@ INFORMATION ABOUT A COMPILED PATTERN
PCRE2_INFO_EXTRAOPTIONS
Return copies of the pattern's options. The third argument should point
- to a uint32_t variable. PCRE2_INFO_ARGOPTIONS returns exactly the
- options that were passed to pcre2_compile(), whereas PCRE2_INFO_ALLOP-
- TIONS returns the compile options as modified by any top-level (*XXX)
- option settings such as (*UTF) at the start of the pattern itself.
- PCRE2_INFO_EXTRAOPTIONS returns the extra options that were set in the
- compile context by calling the pcre2_set_compile_extra_options() func-
+ to a uint32_t variable. PCRE2_INFO_ARGOPTIONS returns exactly the op-
+ tions that were passed to pcre2_compile(), whereas PCRE2_INFO_ALLOP-
+ TIONS returns the compile options as modified by any top-level (*XXX)
+ option settings such as (*UTF) at the start of the pattern itself.
+ PCRE2_INFO_EXTRAOPTIONS returns the extra options that were set in the
+ compile context by calling the pcre2_set_compile_extra_options() func-
tion.
- For example, if the pattern /(*UTF)abc/ is compiled with the
- PCRE2_EXTENDED option, the result for PCRE2_INFO_ALLOPTIONS is
- PCRE2_EXTENDED and PCRE2_UTF. Option settings such as (?i) that can
- change within a pattern do not affect the result of PCRE2_INFO_ALLOP-
- TIONS, even if they appear right at the start of the pattern. (This was
- different in some earlier releases.)
+ For example, if the pattern /(*UTF)abc/ is compiled with the PCRE2_EX-
+ TENDED option, the result for PCRE2_INFO_ALLOPTIONS is PCRE2_EXTENDED
+ and PCRE2_UTF. Option settings such as (?i) that can change within a
+ pattern do not affect the result of PCRE2_INFO_ALLOPTIONS, even if they
+ appear right at the start of the pattern. (This was different in some
+ earlier releases.)
- A pattern compiled without PCRE2_ANCHORED is automatically anchored by
+ A pattern compiled without PCRE2_ANCHORED is automatically anchored by
PCRE2 if the first significant item in every top-level branch is one of
the following:
@@ -2006,187 +2073,196 @@ INFORMATION ABOUT A COMPILED PATTERN
\G always
.* sometimes - see below
- When .* is the first significant item, anchoring is possible only when
+ When .* is the first significant item, anchoring is possible only when
all the following are true:
.* is not in an atomic group
- .* is not in a capturing group that is the subject
+ .* is not in a capture group that is the subject
of a backreference
PCRE2_DOTALL is in force for .*
Neither (*PRUNE) nor (*SKIP) appears in the pattern
PCRE2_NO_DOTSTAR_ANCHOR is not set
- For patterns that are auto-anchored, the PCRE2_ANCHORED bit is set in
+ For patterns that are auto-anchored, the PCRE2_ANCHORED bit is set in
the options returned for PCRE2_INFO_ALLOPTIONS.
PCRE2_INFO_BACKREFMAX
- Return the number of the highest backreference in the pattern. The
- third argument should point to an uint32_t variable. Named subpatterns
- acquire numbers as well as names, and these count towards the highest
- backreference. Backreferences such as \4 or \g{12} match the captured
- characters of the given group, but in addition, the check that a cap-
- turing group is set in a conditional subpattern such as (?(3)a|b) is
- also a backreference. Zero is returned if there are no backreferences.
+ Return the number of the highest backreference in the pattern. The
+ third argument should point to a uint32_t variable. Named capture
+ groups acquire numbers as well as names, and these count towards the
+ highest backreference. Backreferences such as \4 or \g{12} match the
+ captured characters of the given group, but in addition, the check that
+ a capture group is set in a conditional group such as (?(3)a|b) is also
+ a backreference. Zero is returned if there are no backreferences.
PCRE2_INFO_BSR
- The output is a uint32_t integer whose value indicates what character
- sequences the \R escape sequence matches. A value of PCRE2_BSR_UNICODE
- means that \R matches any Unicode line ending sequence; a value of
+ The output is a uint32_t integer whose value indicates what character
+ sequences the \R escape sequence matches. A value of PCRE2_BSR_UNICODE
+ means that \R matches any Unicode line ending sequence; a value of
PCRE2_BSR_ANYCRLF means that \R matches only CR, LF, or CRLF.
PCRE2_INFO_CAPTURECOUNT
- Return the highest capturing subpattern number in the pattern. In pat-
- terns where (?| is not used, this is also the total number of capturing
- subpatterns. The third argument should point to an uint32_t variable.
+ Return the highest capture group number in the pattern. In patterns
+ where (?| is not used, this is also the total number of capture groups.
+ The third argument should point to a uint32_t variable.
PCRE2_INFO_DEPTHLIMIT
- If the pattern set a backtracking depth limit by including an item of
- the form (*LIMIT_DEPTH=nnnn) at the start, the value is returned. The
+ If the pattern set a backtracking depth limit by including an item of
+ the form (*LIMIT_DEPTH=nnnn) at the start, the value is returned. The
third argument should point to a uint32_t integer. If no such value has
- been set, the call to pcre2_pattern_info() returns the error
- PCRE2_ERROR_UNSET. Note that this limit will only be used during match-
- ing if it is less than the limit set or defaulted by the caller of the
- match function.
+ been set, the call to pcre2_pattern_info() returns the error PCRE2_ER-
+ ROR_UNSET. Note that this limit will only be used during matching if it
+ is less than the limit set or defaulted by the caller of the match
+ function.
PCRE2_INFO_FIRSTBITMAP
- In the absence of a single first code unit for a non-anchored pattern,
- pcre2_compile() may construct a 256-bit table that defines a fixed set
- of values for the first code unit in any match. For example, a pattern
- that starts with [abc] results in a table with three bits set. When
- code unit values greater than 255 are supported, the flag bit for 255
- means "any code unit of value 255 or above". If such a table was con-
- structed, a pointer to it is returned. Otherwise NULL is returned. The
+ In the absence of a single first code unit for a non-anchored pattern,
+ pcre2_compile() may construct a 256-bit table that defines a fixed set
+ of values for the first code unit in any match. For example, a pattern
+ that starts with [abc] results in a table with three bits set. When
+ code unit values greater than 255 are supported, the flag bit for 255
+ means "any code unit of value 255 or above". If such a table was con-
+ structed, a pointer to it is returned. Otherwise NULL is returned. The
third argument should point to a const uint8_t * variable.
PCRE2_INFO_FIRSTCODETYPE
Return information about the first code unit of any matched string, for
- a non-anchored pattern. The third argument should point to an uint32_t
- variable. If there is a fixed first value, for example, the letter "c"
- from a pattern such as (cat|cow|coyote), 1 is returned, and the value
- can be retrieved using PCRE2_INFO_FIRSTCODEUNIT. If there is no fixed
- first value, but it is known that a match can occur only at the start
- of the subject or following a newline in the subject, 2 is returned.
+ a non-anchored pattern. The third argument should point to a uint32_t
+ variable. If there is a fixed first value, for example, the letter "c"
+ from a pattern such as (cat|cow|coyote), 1 is returned, and the value
+ can be retrieved using PCRE2_INFO_FIRSTCODEUNIT. If there is no fixed
+ first value, but it is known that a match can occur only at the start
+ of the subject or following a newline in the subject, 2 is returned.
Otherwise, and for anchored patterns, 0 is returned.
PCRE2_INFO_FIRSTCODEUNIT
- Return the value of the first code unit of any matched string for a
- pattern where PCRE2_INFO_FIRSTCODETYPE returns 1; otherwise return 0.
- The third argument should point to an uint32_t variable. In the 8-bit
- library, the value is always less than 256. In the 16-bit library the
- value can be up to 0xffff. In the 32-bit library in UTF-32 mode the
+ Return the value of the first code unit of any matched string for a
+ pattern where PCRE2_INFO_FIRSTCODETYPE returns 1; otherwise return 0.
+ The third argument should point to a uint32_t variable. In the 8-bit
+ library, the value is always less than 256. In the 16-bit library the
+ value can be up to 0xffff. In the 32-bit library in UTF-32 mode the
value can be up to 0x10ffff, and up to 0xffffffff when not using UTF-32
mode.
PCRE2_INFO_FRAMESIZE
Return the size (in bytes) of the data frames that are used to remember
- backtracking positions when the pattern is processed by pcre2_match()
- without the use of JIT. The third argument should point to a size_t
+ backtracking positions when the pattern is processed by pcre2_match()
+ without the use of JIT. The third argument should point to a size_t
variable. The frame size depends on the number of capturing parentheses
- in the pattern. Each additional capturing group adds two PCRE2_SIZE
- variables.
+ in the pattern. Each additional capture group adds two PCRE2_SIZE vari-
+ ables.
PCRE2_INFO_HASBACKSLASHC
- Return 1 if the pattern contains any instances of \C, otherwise 0. The
- third argument should point to an uint32_t variable.
+ Return 1 if the pattern contains any instances of \C, otherwise 0. The
+ third argument should point to a uint32_t variable.
PCRE2_INFO_HASCRORLF
- Return 1 if the pattern contains any explicit matches for CR or LF
- characters, otherwise 0. The third argument should point to an uint32_t
- variable. An explicit match is either a literal CR or LF character, or
- \r or \n or one of the equivalent hexadecimal or octal escape
- sequences.
+ Return 1 if the pattern contains any explicit matches for CR or LF
+ characters, otherwise 0. The third argument should point to a uint32_t
+ variable. An explicit match is either a literal CR or LF character, or
+ \r or \n or one of the equivalent hexadecimal or octal escape se-
+ quences.
PCRE2_INFO_HEAPLIMIT
If the pattern set a heap memory limit by including an item of the form
(*LIMIT_HEAP=nnnn) at the start, the value is returned. The third argu-
ment should point to a uint32_t integer. If no such value has been set,
- the call to pcre2_pattern_info() returns the error PCRE2_ERROR_UNSET.
- Note that this limit will only be used during matching if it is less
+ the call to pcre2_pattern_info() returns the error PCRE2_ERROR_UNSET.
+ Note that this limit will only be used during matching if it is less
than the limit set or defaulted by the caller of the match function.
PCRE2_INFO_JCHANGED
- Return 1 if the (?J) or (?-J) option setting is used in the pattern,
- otherwise 0. The third argument should point to an uint32_t variable.
- (?J) and (?-J) set and unset the local PCRE2_DUPNAMES option, respec-
+ Return 1 if the (?J) or (?-J) option setting is used in the pattern,
+ otherwise 0. The third argument should point to a uint32_t variable.
+ (?J) and (?-J) set and unset the local PCRE2_DUPNAMES option, respec-
tively.
PCRE2_INFO_JITSIZE
- If the compiled pattern was successfully processed by pcre2_jit_com-
- pile(), return the size of the JIT compiled code, otherwise return
+ If the compiled pattern was successfully processed by pcre2_jit_com-
+ pile(), return the size of the JIT compiled code, otherwise return
zero. The third argument should point to a size_t variable.
PCRE2_INFO_LASTCODETYPE
- Returns 1 if there is a rightmost literal code unit that must exist in
- any matched string, other than at its start. The third argument should
- point to an uint32_t variable. If there is no such value, 0 is
- returned. When 1 is returned, the code unit value itself can be
- retrieved using PCRE2_INFO_LASTCODEUNIT. For anchored patterns, a last
- literal value is recorded only if it follows something of variable
- length. For example, for the pattern /^a\d+z\d+/ the returned value is
- 1 (with "z" returned from PCRE2_INFO_LASTCODEUNIT), but for /^a\dz\d/
- the returned value is 0.
+ Returns 1 if there is a rightmost literal code unit that must exist in
+ any matched string, other than at its start. The third argument should
+ point to a uint32_t variable. If there is no such value, 0 is returned.
+ When 1 is returned, the code unit value itself can be retrieved using
+ PCRE2_INFO_LASTCODEUNIT. For anchored patterns, a last literal value is
+ recorded only if it follows something of variable length. For example,
+ for the pattern /^a\d+z\d+/ the returned value is 1 (with "z" returned
+ from PCRE2_INFO_LASTCODEUNIT), but for /^a\dz\d/ the returned value is
+ 0.
PCRE2_INFO_LASTCODEUNIT
- Return the value of the rightmost literal code unit that must exist in
- any matched string, other than at its start, for a pattern where
+ Return the value of the rightmost literal code unit that must exist in
+ any matched string, other than at its start, for a pattern where
PCRE2_INFO_LASTCODETYPE returns 1. Otherwise, return 0. The third argu-
- ment should point to an uint32_t variable.
+ ment should point to a uint32_t variable.
PCRE2_INFO_MATCHEMPTY
- Return 1 if the pattern might match an empty string, otherwise 0. The
- third argument should point to an uint32_t variable. When a pattern
- contains recursive subroutine calls it is not always possible to deter-
- mine whether or not it can match an empty string. PCRE2 takes a cau-
- tious approach and returns 1 in such cases.
+ Return 1 if the pattern might match an empty string, otherwise 0. The
+ third argument should point to a uint32_t variable. When a pattern con-
+ tains recursive subroutine calls it is not always possible to determine
+ whether or not it can match an empty string. PCRE2 takes a cautious ap-
+ proach and returns 1 in such cases.
PCRE2_INFO_MATCHLIMIT
- If the pattern set a match limit by including an item of the form
- (*LIMIT_MATCH=nnnn) at the start, the value is returned. The third
- argument should point to a uint32_t integer. If no such value has been
- set, the call to pcre2_pattern_info() returns the error
- PCRE2_ERROR_UNSET. Note that this limit will only be used during match-
- ing if it is less than the limit set or defaulted by the caller of the
- match function.
+ If the pattern set a match limit by including an item of the form
+ (*LIMIT_MATCH=nnnn) at the start, the value is returned. The third ar-
+ gument should point to a uint32_t integer. If no such value has been
+ set, the call to pcre2_pattern_info() returns the error PCRE2_ERROR_UN-
+ SET. Note that this limit will only be used during matching if it is
+ less than the limit set or defaulted by the caller of the match func-
+ tion.
PCRE2_INFO_MAXLOOKBEHIND
- Return the number of characters (not code units) in the longest lookbe-
- hind assertion in the pattern. The third argument should point to a
- uint32_t integer. This information is useful when doing multi-segment
- matching using the partial matching facilities. Note that the simple
- assertions \b and \B require a one-character lookbehind. \A also regis-
- ters a one-character lookbehind, though it does not actually inspect
- the previous character. This is to ensure that at least one character
- from the old segment is retained when a new segment is processed. Oth-
- erwise, if there are no lookbehinds in the pattern, \A might match
- incorrectly at the start of a second or subsequent segment.
+ A lookbehind assertion moves back a certain number of characters (not
+ code units) when it starts to process each of its branches. This re-
+ quest returns the largest of these backward moves. The third argument
+ should point to a uint32_t integer. The simple assertions \b and \B re-
+ quire a one-character lookbehind and cause PCRE2_INFO_MAXLOOKBEHIND to
+ return 1 in the absence of anything longer. \A also registers a one-
+ character lookbehind, though it does not actually inspect the previous
+ character.
+
+ Note that this information is useful for multi-segment matching only if
+ the pattern contains no nested lookbehinds. For example, the pattern
+ (?<=a(?<=ba)c) returns a maximum lookbehind of 2, but when it is pro-
+ cessed, the first lookbehind moves back by two characters, matches one
+ character, then the nested lookbehind also moves back by two charac-
+ ters. This puts the matching point three characters earlier than it was
+ at the start. PCRE2_INFO_MAXLOOKBEHIND is really only useful as a de-
+ bugging tool. See the pcre2partial documentation for a discussion of
+ multi-segment matching.
PCRE2_INFO_MINLENGTH
- If a minimum length for matching subject strings was computed, its
- value is returned. Otherwise the returned value is 0. The value is a
- number of characters, which in UTF mode may be different from the num-
- ber of code units. The third argument should point to an uint32_t
- variable. The value is a lower bound to the length of any matching
- string. There may not be any strings of that length that do actually
- match, but every string that does match is at least that long.
+ If a minimum length for matching subject strings was computed, its
+ value is returned. Otherwise the returned value is 0. This value is not
+ computed when PCRE2_NO_START_OPTIMIZE is set. The value is a number of
+ characters, which in UTF mode may be different from the number of code
+ units. The third argument should point to a uint32_t variable. The
+ value is a lower bound to the length of any matching string. There may
+ not be any strings of that length that do actually match, but every
+ string that does match is at least that long.
PCRE2_INFO_NAMECOUNT
PCRE2_INFO_NAMEENTRYSIZE
@@ -2199,8 +2275,8 @@ INFORMATION ABOUT A COMPILED PATTERN
strings by name. It is also possible to extract the data directly, by
first converting the name to a number in order to access the correct
pointers in the output vector (described with pcre2_match() below). To
- do the conversion, you need to use the name-to-number map, which is
- described by these three values.
+ do the conversion, you need to use the name-to-number map, which is de-
+ scribed by these three values.
The map consists of a number of fixed-size entries. PCRE2_INFO_NAME-
COUNT gives the number of entries, and PCRE2_INFO_NAMEENTRYSIZE gives
@@ -2208,35 +2284,36 @@ INFORMATION ABOUT A COMPILED PATTERN
value. The entry size depends on the length of the longest name.
PCRE2_INFO_NAMETABLE returns a pointer to the first entry of the table.
- This is a PCRE2_SPTR pointer to a block of code units. In the 8-bit
- library, the first two bytes of each entry are the number of the cap-
- turing parenthesis, most significant byte first. In the 16-bit library,
+ This is a PCRE2_SPTR pointer to a block of code units. In the 8-bit li-
+ brary, the first two bytes of each entry are the number of the captur-
+ ing parenthesis, most significant byte first. In the 16-bit library,
the pointer points to 16-bit code units, the first of which contains
the parenthesis number. In the 32-bit library, the pointer points to
32-bit code units, the first of which contains the parenthesis number.
The rest of the entry is the corresponding name, zero terminated.
The names are in alphabetical order. If (?| is used to create multiple
- groups with the same number, as described in the section on duplicate
- subpattern numbers in the pcre2pattern page, the groups may be given
+ capture groups with the same number, as described in the section on du-
+ plicate group numbers in the pcre2pattern page, the groups may be given
the same name, but there is only one entry in the table. Different
names for groups of the same number are not permitted.
- Duplicate names for subpatterns with different numbers are permitted,
- but only if PCRE2_DUPNAMES is set. They appear in the table in the
+ Duplicate names for capture groups with different numbers are permit-
+ ted, but only if PCRE2_DUPNAMES is set. They appear in the table in the
order in which they were found in the pattern. In the absence of (?|
this is the order of increasing number; when (?| is used this is not
- necessarily the case because later subpatterns may have lower numbers.
+ necessarily the case because later capture groups may have lower num-
+ bers.
- As a simple example of the name/number table, consider the following
- pattern after compilation by the 8-bit library (assume PCRE2_EXTENDED
+ As a simple example of the name/number table, consider the following
+ pattern after compilation by the 8-bit library (assume PCRE2_EXTENDED
is set, so white space - including newlines - is ignored):
(? (?(\d\d)?\d\d) -
(?\d\d) - (?\d\d) )
- There are four named subpatterns, so the table has four entries, and
- each entry in the table is eight bytes long. The table is as follows,
+ There are four named capture groups, so the table has four entries, and
+ each entry in the table is eight bytes long. The table is as follows,
with non-printing bytes shows in hexadecimal, and undefined bytes shown
as ??:
@@ -2245,8 +2322,8 @@ INFORMATION ABOUT A COMPILED PATTERN
00 04 m o n t h 00
00 02 y e a r 00 ??
- When writing code to extract data from named subpatterns using the
- name-to-number map, remember that the length of the entries is likely
+ When writing code to extract data from named capture groups using the
+ name-to-number map, remember that the length of the entries is likely
to be different for each compiled pattern.
PCRE2_INFO_NEWLINE
@@ -2265,15 +2342,15 @@ INFORMATION ABOUT A COMPILED PATTERN
PCRE2_INFO_SIZE
- Return the size of the compiled pattern in bytes (for all three
- libraries). The third argument should point to a size_t variable. This
- value includes the size of the general data block that precedes the
- code units of the compiled pattern itself. The value that is used when
- pcre2_compile() is getting memory in which to place the compiled pat-
- tern may be slightly larger than the value returned by this option,
- because there are cases where the code that calculates the size has to
- over-estimate. Processing a pattern with the JIT compiler does not
- alter the value returned by this option.
+ Return the size of the compiled pattern in bytes (for all three li-
+ braries). The third argument should point to a size_t variable. This
+ value includes the size of the general data block that precedes the
+ code units of the compiled pattern itself. The value that is used when
+ pcre2_compile() is getting memory in which to place the compiled pat-
+ tern may be slightly larger than the value returned by this option, be-
+ cause there are cases where the code that calculates the size has to
+ over-estimate. Processing a pattern with the JIT compiler does not al-
+ ter the value returned by this option.
INFORMATION ABOUT A PATTERN'S CALLOUTS
@@ -2283,30 +2360,30 @@ INFORMATION ABOUT A PATTERN'S CALLOUTS
void *user_data);
A script language that supports the use of string arguments in callouts
- might like to scan all the callouts in a pattern before running the
+ might like to scan all the callouts in a pattern before running the
match. This can be done by calling pcre2_callout_enumerate(). The first
- argument is a pointer to a compiled pattern, the second points to a
- callback function, and the third is arbitrary user data. The callback
- function is called for every callout in the pattern in the order in
+ argument is a pointer to a compiled pattern, the second points to a
+ callback function, and the third is arbitrary user data. The callback
+ function is called for every callout in the pattern in the order in
which they appear. Its first argument is a pointer to a callout enumer-
- ation block, and its second argument is the user_data value that was
- passed to pcre2_callout_enumerate(). The contents of the callout enu-
- meration block are described in the pcre2callout documentation, which
+ ation block, and its second argument is the user_data value that was
+ passed to pcre2_callout_enumerate(). The contents of the callout enu-
+ meration block are described in the pcre2callout documentation, which
also gives further details about callouts.
SERIALIZATION AND PRECOMPILING
- It is possible to save compiled patterns on disc or elsewhere, and
- reload them later, subject to a number of restrictions. The host on
- which the patterns are reloaded must be running the same version of
+ It is possible to save compiled patterns on disc or elsewhere, and
+ reload them later, subject to a number of restrictions. The host on
+ which the patterns are reloaded must be running the same version of
PCRE2, with the same code unit width, and must also have the same endi-
- anness, pointer width, and PCRE2_SIZE type. Before compiled patterns
- can be saved, they must be converted to a "serialized" form, which in
- the case of PCRE2 is really just a bytecode dump. The functions whose
- names begin with pcre2_serialize_ are used for converting to and from
- the serialized form. They are described in the pcre2serialize documen-
- tation. Note that PCRE2 serialization does not convert compiled pat-
+ anness, pointer width, and PCRE2_SIZE type. Before compiled patterns
+ can be saved, they must be converted to a "serialized" form, which in
+ the case of PCRE2 is really just a bytecode dump. The functions whose
+ names begin with pcre2_serialize_ are used for converting to and from
+ the serialized form. They are described in the pcre2serialize documen-
+ tation. Note that PCRE2 serialization does not convert compiled pat-
terns to an abstract format like Java or .NET serialization.
@@ -2320,54 +2397,55 @@ THE MATCH DATA BLOCK
void pcre2_match_data_free(pcre2_match_data *match_data);
- Information about a successful or unsuccessful match is placed in a
- match data block, which is an opaque structure that is accessed by
- function calls. In particular, the match data block contains a vector
- of offsets into the subject string that define the matched part of the
- subject and any substrings that were captured. This is known as the
+ Information about a successful or unsuccessful match is placed in a
+ match data block, which is an opaque structure that is accessed by
+ function calls. In particular, the match data block contains a vector
+ of offsets into the subject string that define the matched part of the
+ subject and any substrings that were captured. This is known as the
ovector.
- Before calling pcre2_match(), pcre2_dfa_match(), or pcre2_jit_match()
+ Before calling pcre2_match(), pcre2_dfa_match(), or pcre2_jit_match()
you must create a match data block by calling one of the creation func-
- tions above. For pcre2_match_data_create(), the first argument is the
- number of pairs of offsets in the ovector. One pair of offsets is
- required to identify the string that matched the whole pattern, with an
- additional pair for each captured substring. For example, a value of 4
- creates enough space to record the matched portion of the subject plus
- three captured substrings. A minimum of at least 1 pair is imposed by
+ tions above. For pcre2_match_data_create(), the first argument is the
+ number of pairs of offsets in the ovector. One pair of offsets is re-
+ quired to identify the string that matched the whole pattern, with an
+ additional pair for each captured substring. For example, a value of 4
+ creates enough space to record the matched portion of the subject plus
+ three captured substrings. A minimum of at least 1 pair is imposed by
pcre2_match_data_create(), so it is always possible to return the over-
all matched string.
The second argument of pcre2_match_data_create() is a pointer to a gen-
- eral context, which can specify custom memory management for obtaining
+ eral context, which can specify custom memory management for obtaining
the memory for the match data block. If you are not using custom memory
management, pass NULL, which causes malloc() to be used.
- For pcre2_match_data_create_from_pattern(), the first argument is a
+ For pcre2_match_data_create_from_pattern(), the first argument is a
pointer to a compiled pattern. The ovector is created to be exactly the
right size to hold all the substrings a pattern might capture. The sec-
- ond argument is again a pointer to a general context, but in this case
+ ond argument is again a pointer to a general context, but in this case
if NULL is passed, the memory is obtained using the same allocator that
was used for the compiled pattern (custom or default).
- A match data block can be used many times, with the same or different
- compiled patterns. You can extract information from a match data block
- after a match operation has finished, using functions that are
- described in the sections on matched strings and other match data
- below.
+ A match data block can be used many times, with the same or different
+ compiled patterns. You can extract information from a match data block
+ after a match operation has finished, using functions that are de-
+ scribed in the sections on matched strings and other match data below.
When a call of pcre2_match() fails, valid data is available in the
- match block only when the error is PCRE2_ERROR_NOMATCH,
- PCRE2_ERROR_PARTIAL, or one of the error codes for an invalid UTF
- string. Exactly what is available depends on the error, and is detailed
- below.
-
- When one of the matching functions is called, pointers to the compiled
- pattern and the subject string are set in the match data block so that
- they can be referenced by the extraction functions. After running a
- match, you must not free a compiled pattern or a subject string until
- after all operations on the match data block (for that match) have
- taken place.
+ match block only when the error is PCRE2_ERROR_NOMATCH, PCRE2_ER-
+ ROR_PARTIAL, or one of the error codes for an invalid UTF string. Ex-
+ actly what is available depends on the error, and is detailed below.
+
+ When one of the matching functions is called, pointers to the compiled
+ pattern and the subject string are set in the match data block so that
+ they can be referenced by the extraction functions after a successful
+ match. After running a match, you must not free a compiled pattern or a
+ subject string until after all operations on the match data block (for
+ that match) have taken place, unless, in the case of the subject
+ string, you have used the PCRE2_COPY_MATCHED_SUBJECT option, which is
+ described in the section entitled "Option bits for pcre2_match()" be-
+ low.
When a match data block itself is no longer needed, it should be freed
by calling pcre2_match_data_free(). If this function is called with a
@@ -2387,9 +2465,9 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
order to find multiple matches in the subject string or to match dif-
ferent subject strings with the same pattern.
- This function is the main matching facility of the library, and it
- operates in a Perl-like manner. For specialist use there is also an
- alternative matching function, which is described below in the section
+ This function is the main matching facility of the library, and it op-
+ erates in a Perl-like manner. For specialist use there is also an al-
+ ternative matching function, which is described below in the section
about the pcre2_dfa_match() function.
Here is an example of a simple call to pcre2_match():
@@ -2424,8 +2502,8 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
by far the most common case. In UTF-8 or UTF-16 mode, the starting off-
set must point to the start of a character, or to the end of the sub-
ject (in UTF-32 mode, one code unit equals one character, so all off-
- sets are valid). Like the pattern string, the subject may contain
- binary zeros.
+ sets are valid). Like the pattern string, the subject may contain bi-
+ nary zeros.
A non-zero starting offset is useful when searching for another match
in the same subject by calling pcre2_match() again after a previous
@@ -2439,8 +2517,8 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
only if the current position in the subject is not a word boundary.)
When applied to the string "Mississipi" the first call to pcre2_match()
finds the first occurrence. If pcre2_match() is called again with just
- the remainder of the subject, namely "issipi", it does not match,
- because \B is always false at the start of the subject, which is deemed
+ the remainder of the subject, namely "issipi", it does not match, be-
+ cause \B is always false at the start of the subject, which is deemed
to be a word boundary. However, if pcre2_match() is passed the entire
string again, but with startoffset set to 4, it finds the second occur-
rence of "iss" because it is able to look behind the starting point to
@@ -2467,25 +2545,43 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
Option bits for pcre2_match()
The unused bits of the options argument for pcre2_match() must be zero.
- The only bits that may be set are PCRE2_ANCHORED, PCRE2_ENDANCHORED,
- PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART,
- PCRE2_NO_JIT, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, and PCRE2_PAR-
- TIAL_SOFT. Their action is described below.
-
- Setting PCRE2_ANCHORED or PCRE2_ENDANCHORED at match time is not sup-
- ported by the just-in-time (JIT) compiler. If it is set, JIT matching
- is disabled and the interpretive code in pcre2_match() is run. Apart
- from PCRE2_NO_JIT (obviously), the remaining options are supported for
+ The only bits that may be set are PCRE2_ANCHORED,
+ PCRE2_COPY_MATCHED_SUBJECT, PCRE2_ENDANCHORED, PCRE2_NOTBOL, PCRE2_NO-
+ TEOL, PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_JIT,
+ PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, and PCRE2_PARTIAL_SOFT. Their
+ action is described below.
+
+ Setting PCRE2_ANCHORED or PCRE2_ENDANCHORED at match time is not sup-
+ ported by the just-in-time (JIT) compiler. If it is set, JIT matching
+ is disabled and the interpretive code in pcre2_match() is run. Apart
+ from PCRE2_NO_JIT (obviously), the remaining options are supported for
JIT matching.
PCRE2_ANCHORED
The PCRE2_ANCHORED option limits pcre2_match() to matching at the first
- matching position. If a pattern was compiled with PCRE2_ANCHORED, or
- turned out to be anchored by virtue of its contents, it cannot be made
- unachored at matching time. Note that setting the option at match time
+ matching position. If a pattern was compiled with PCRE2_ANCHORED, or
+ turned out to be anchored by virtue of its contents, it cannot be made
+ unachored at matching time. Note that setting the option at match time
disables JIT matching.
+ PCRE2_COPY_MATCHED_SUBJECT
+
+ By default, a pointer to the subject is remembered in the match data
+ block so that, after a successful match, it can be referenced by the
+ substring extraction functions. This means that the subject's memory
+ must not be freed until all such operations are complete. For some ap-
+ plications where the lifetime of the subject string is not guaranteed,
+ it may be necessary to make a copy of the subject string, but it is
+ wasteful to do this unless the match is successful. After a successful
+ match, if PCRE2_COPY_MATCHED_SUBJECT is set, the subject is copied and
+ the new pointer is remembered in the match data block instead of the
+ original subject pointer. The memory allocator that was used for the
+ match block itself is used. The copy is automatically freed when
+ pcre2_match_data_free() is called to free the match data block. It is
+ also automatically freed if the match data block is re-used for another
+ match operation.
+
PCRE2_ENDANCHORED
If the PCRE2_ENDANCHORED option is set, any string that pcre2_match()
@@ -2528,8 +2624,8 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
This is like PCRE2_NOTEMPTY, except that it locks out an empty string
match only at the first matching position, that is, at the start of the
subject plus the starting offset. An empty string match later in the
- subject is permitted. If the pattern is anchored, such a match can
- occur only if the pattern contains \K.
+ subject is permitted. If the pattern is anchored, such a match can oc-
+ cur only if the pattern contains \K.
PCRE2_NO_JIT
@@ -2541,46 +2637,56 @@ MATCHING A PATTERN: THE TRADITIONAL FUNCTION
PCRE2_NO_UTF_CHECK
When PCRE2_UTF is set at compile time, the validity of the subject as a
- UTF string is checked by default when pcre2_match() is subsequently
- called. If a non-zero starting offset is given, the check is applied
- only to that part of the subject that could be inspected during match-
- ing, and there is a check that the starting offset points to the first
- code unit of a character or to the end of the subject. If there are no
- lookbehind assertions in the pattern, the check starts at the starting
- offset. Otherwise, it starts at the length of the longest lookbehind
- before the starting offset, or at the start of the subject if there are
- not that many characters before the starting offset. Note that the
- sequences \b and \B are one-character lookbehinds.
+ UTF string is checked unless PCRE2_NO_UTF_CHECK is passed to
+ pcre2_match() or PCRE2_MATCH_INVALID_UTF was passed to pcre2_compile().
+ The latter special case is discussed in detail in the pcre2unicode doc-
+ umentation.
+
+ In the default case, if a non-zero starting offset is given, the check
+ is applied only to that part of the subject that could be inspected
+ during matching, and there is a check that the starting offset points
+ to the first code unit of a character or to the end of the subject. If
+ there are no lookbehind assertions in the pattern, the check starts at
+ the starting offset. Otherwise, it starts at the length of the longest
+ lookbehind before the starting offset, or at the start of the subject
+ if there are not that many characters before the starting offset. Note
+ that the sequences \b and \B are one-character lookbehinds.
The check is carried out before any other processing takes place, and a
negative error code is returned if the check fails. There are several
UTF error codes for each code unit width, corresponding to different
problems with the code unit sequence. There are discussions about the
validity of UTF-8 strings, UTF-16 strings, and UTF-32 strings in the
- pcre2unicode page.
+ pcre2unicode documentation.
- If you know that your subject is valid, and you want to skip these
- checks for performance reasons, you can set the PCRE2_NO_UTF_CHECK
- option when calling pcre2_match(). You might want to do this for the
- second and subsequent calls to pcre2_match() if you are making repeated
- calls to find other matches in the same subject string.
+ If you know that your subject is valid, and you want to skip this check
+ for performance reasons, you can set the PCRE2_NO_UTF_CHECK option when
+ calling pcre2_match(). You might want to do this for the second and
+ subsequent calls to pcre2_match() if you are making repeated calls to
+ find multiple matches in the same subject string.
- Warning: When PCRE2_NO_UTF_CHECK is set, the effect of passing an
- invalid string as a subject, or an invalid value of startoffset, is
- undefined. Your program may crash or loop indefinitely.
+ Warning: Unless PCRE2_MATCH_INVALID_UTF was set at compile time, when
+ PCRE2_NO_UTF_CHECK is set at match time the effect of passing an in-
+ valid string as a subject, or an invalid value of startoffset, is unde-
+ fined. Your program may crash or loop indefinitely or give wrong re-
+ sults.
PCRE2_PARTIAL_HARD
PCRE2_PARTIAL_SOFT
- These options turn on the partial matching feature. A partial match
- occurs if the end of the subject string is reached successfully, but
- there are not enough subject characters to complete the match. If this
- happens when PCRE2_PARTIAL_SOFT (but not PCRE2_PARTIAL_HARD) is set,
- matching continues by testing any remaining alternatives. Only if no
- complete match can be found is PCRE2_ERROR_PARTIAL returned instead of
- PCRE2_ERROR_NOMATCH. In other words, PCRE2_PARTIAL_SOFT specifies that
- the caller is prepared to handle a partial match, but only if no com-
- plete match can be found.
+ These options turn on the partial matching feature. A partial match oc-
+ curs if the end of the subject string is reached successfully, but
+ there are not enough subject characters to complete the match. In addi-
+ tion, either at least one character must have been inspected or the
+ pattern must contain a lookbehind, or the pattern must be one that
+ could match an empty string.
+
+ If this situation arises when PCRE2_PARTIAL_SOFT (but not PCRE2_PAR-
+ TIAL_HARD) is set, matching continues by testing any remaining alterna-
+ tives. Only if no complete match can be found is PCRE2_ERROR_PARTIAL
+ returned instead of PCRE2_ERROR_NOMATCH. In other words, PCRE2_PAR-
+ TIAL_SOFT specifies that the caller is prepared to handle a partial
+ match, but only if no complete match can be found.
If PCRE2_PARTIAL_HARD is set, it overrides PCRE2_PARTIAL_SOFT. In this
case, if a partial match is found, pcre2_match() immediately returns
@@ -2612,8 +2718,8 @@ NEWLINE HANDLING WHEN MATCHING
other words, to after the CRLF.
The above rule is a compromise that makes the most common cases work as
- expected. For example, if the pattern is .+A (and the PCRE2_DOTALL
- option is not set), it does not match the string "\r\nA" because, after
+ expected. For example, if the pattern is .+A (and the PCRE2_DOTALL op-
+ tion is not set), it does not match the string "\r\nA" because, after
failing at the start, it skips both the CR and the LF before retrying.
However, the pattern [\r\n]A does match that string, because it con-
tains an explicit CR or LF reference, and so advances only by one char-
@@ -2640,11 +2746,11 @@ HOW PCRE2_MATCH() RETURNS A STRING AND CAPTURED SUBSTRINGS
addition, further substrings from the subject may be picked out by
parenthesized parts of the pattern. Following the usage in Jeffrey
Friedl's book, this is called "capturing" in what follows, and the
- phrase "capturing subpattern" or "capturing group" is used for a frag-
- ment of a pattern that picks out a substring. PCRE2 supports several
- other kinds of parenthesized subpattern that do not cause substrings to
- be captured. The pcre2_pattern_info() function can be used to find out
- how many capturing subpatterns there are in a compiled pattern.
+ phrase "capture group" (Perl terminology) is used for a fragment of a
+ pattern that picks out a substring. PCRE2 supports several other kinds
+ of parenthesized group that do not cause substrings to be captured. The
+ pcre2_pattern_info() function can be used to find out how many capture
+ groups there are in a compiled pattern.
You can use auxiliary functions for accessing captured substrings by
number or by name, as described in sections below.
@@ -2660,8 +2766,8 @@ HOW PCRE2_MATCH() RETURNS A STRING AND CAPTURED SUBSTRINGS
set of the first code unit of a substring, and the second is set to the
offset of the first code unit after the end of a substring. These val-
ues are always code unit offsets, not character offsets. That is, they
- are byte offsets in the 8-bit library, 16-bit offsets in the 16-bit
- library, and 32-bit offsets in the 32-bit library.
+ are byte offsets in the 8-bit library, 16-bit offsets in the 16-bit li-
+ brary, and 32-bit offsets in the 32-bit library.
After a partial match (error return PCRE2_ERROR_PARTIAL), only the
first pair of offsets (that is, ovector[0] and ovector[1]) are set.
@@ -2682,9 +2788,9 @@ HOW PCRE2_MATCH() RETURNS A STRING AND CAPTURED SUBSTRINGS
the match. For example, if the pattern (?=ab\K) is matched against
"ab", the start and end offset values for the match are 2 and 0.
- If a capturing subpattern group is matched repeatedly within a single
- match operation, it is the last portion of the subject that it matched
- that is returned.
+ If a capture group is matched repeatedly within a single match opera-
+ tion, it is the last portion of the subject that it matched that is re-
+ turned.
If the ovector is too small to hold all the captured substring offsets,
as much as possible is filled in, and the function returns a value of
@@ -2692,20 +2798,20 @@ HOW PCRE2_MATCH() RETURNS A STRING AND CAPTURED SUBSTRINGS
called with a match data block whose ovector is of minimum length (that
is, one pair).
- It is possible for capturing subpattern number n+1 to match some part
- of the subject when subpattern n has not been used at all. For example,
- if the string "abc" is matched against the pattern (a|(z))(bc) the
- return from the function is 4, and subpatterns 1 and 3 are matched, but
- 2 is not. When this happens, both values in the offset pairs corre-
- sponding to unused subpatterns are set to PCRE2_UNSET.
-
- Offset values that correspond to unused subpatterns at the end of the
- expression are also set to PCRE2_UNSET. For example, if the string
- "abc" is matched against the pattern (abc)(x(yz)?)? subpatterns 2 and 3
- are not matched. The return from the function is 2, because the high-
- est used capturing subpattern number is 1. The offsets for for the sec-
- ond and third capturing subpatterns (assuming the vector is large
- enough, of course) are set to PCRE2_UNSET.
+ It is possible for capture group number n+1 to match some part of the
+ subject when group n has not been used at all. For example, if the
+ string "abc" is matched against the pattern (a|(z))(bc) the return from
+ the function is 4, and groups 1 and 3 are matched, but 2 is not. When
+ this happens, both values in the offset pairs corresponding to unused
+ groups are set to PCRE2_UNSET.
+
+ Offset values that correspond to unused groups at the end of the ex-
+ pression are also set to PCRE2_UNSET. For example, if the string "abc"
+ is matched against the pattern (abc)(x(yz)?)? groups 2 and 3 are not
+ matched. The return from the function is 2, because the highest used
+ capture group number is 1. The offsets for for the second and third
+ capture groupss (assuming the vector is large enough, of course) are
+ set to PCRE2_UNSET.
Elements in the ovector that do not correspond to capturing parentheses
in the pattern are never changed. That is, if a pattern contains n cap-
@@ -2727,22 +2833,22 @@ OTHER INFORMATION ABOUT A MATCH
times, the result is undefined.
After a successful match, a partial match (PCRE2_ERROR_PARTIAL), or a
- failure to match (PCRE2_ERROR_NOMATCH), a (*MARK), (*PRUNE), or (*THEN)
- name may be available. The function pcre2_get_mark() can be called to
- access this name. The same function applies to all three verbs. It
+ failure to match (PCRE2_ERROR_NOMATCH), a mark name may be available.
+ The function pcre2_get_mark() can be called to access this name, which
+ can be specified in the pattern by any of the backtracking control
+ verbs, not just (*MARK). The same function applies to all the verbs. It
returns a pointer to the zero-terminated name, which is within the com-
piled pattern. If no name is available, NULL is returned. The length of
- the name (excluding the terminating zero) is stored in the code unit
- that precedes the name. You should use this length instead of relying
+ the name (excluding the terminating zero) is stored in the code unit
+ that precedes the name. You should use this length instead of relying
on the terminating zero if the name might contain a binary zero.
- After a successful match, the name that is returned is the last
- (*MARK), (*PRUNE), or (*THEN) name encountered on the matching path
- through the pattern. Instances of (*PRUNE) and (*THEN) without names
- are ignored. Thus, for example, if the matching path contains
- (*MARK:A)(*PRUNE), the name "A" is returned. After a "no match" or a
- partial match, the last encountered name is returned. For example,
- consider this pattern:
+ After a successful match, the name that is returned is the last mark
+ name encountered on the matching path through the pattern. Instances of
+ backtracking verbs without names do not count. Thus, for example, if
+ the matching path contains (*MARK:A)(*PRUNE), the name "A" is returned.
+ After a "no match" or a partial match, the last encountered name is re-
+ turned. For example, consider this pattern:
^(*MARK:A)((*MARK:B)a|b)c
@@ -2754,10 +2860,10 @@ OTHER INFORMATION ABOUT A MATCH
Warning: By default, certain start-of-match optimizations are used to
give a fast "no match" result in some situations. For example, if the
anchoring is removed from the pattern above, there is an initial check
- for the presence of "c" in the subject before running the matching
- engine. This check fails for "bx", causing a match failure without see-
- ing any marks. You can disable the start-of-match optimizations by set-
- ting the PCRE2_NO_START_OPTIMIZE option for pcre2_compile() or starting
+ for the presence of "c" in the subject before running the matching en-
+ gine. This check fails for "bx", causing a match failure without seeing
+ any marks. You can disable the start-of-match optimizations by setting
+ the PCRE2_NO_START_OPTIMIZE option for pcre2_compile() or by starting
the pattern with (*NO_START_OPT).
After a successful match, a partial match, or one of the invalid UTF
@@ -2845,10 +2951,10 @@ ERROR RETURNS FROM pcre2_match()
PCRE2_ERROR_JIT_STACKLIMIT
- This error is returned when a pattern that was successfully studied
- using JIT is being matched, but the memory available for the just-in-
- time processing stack is not large enough. See the pcre2jit documenta-
- tion for more details.
+ This error is returned when a pattern that was successfully studied us-
+ ing JIT is being matched, but the memory available for the just-in-time
+ processing stack is not large enough. See the pcre2jit documentation
+ for more details.
PCRE2_ERROR_MATCHLIMIT
@@ -2860,7 +2966,8 @@ ERROR RETURNS FROM pcre2_match()
used to remember them. This error is given when the memory allocation
function (default or custom) fails. Note that a different error,
PCRE2_ERROR_HEAPLIMIT, is given if the amount of memory needed exceeds
- the heap limit.
+ the heap limit. PCRE2_ERROR_NOMEMORY is also returned if
+ PCRE2_COPY_MATCHED_SUBJECT is set and memory allocation fails.
PCRE2_ERROR_NULL
@@ -2868,13 +2975,13 @@ ERROR RETURNS FROM pcre2_match()
PCRE2_ERROR_RECURSELOOP
- This error is returned when pcre2_match() detects a recursion loop
- within the pattern. Specifically, it means that either the whole pat-
- tern or a subpattern has been called recursively for the second time at
- the same position in the subject string. Some simple patterns that
- might do this are detected and faulted at compile time, but more com-
- plicated cases, in particular mutual recursions between two different
- subpatterns, cannot be detected until matching is attempted.
+ This error is returned when pcre2_match() detects a recursion loop
+ within the pattern. Specifically, it means that either the whole pat-
+ tern or a capture group has been called recursively for the second time
+ at the same position in the subject string. Some simple patterns that
+ might do this are detected and faulted at compile time, but more com-
+ plicated cases, in particular mutual recursions between two different
+ groups, cannot be detected until matching is attempted.
OBTAINING A TEXTUAL ERROR MESSAGE
@@ -2882,21 +2989,21 @@ OBTAINING A TEXTUAL ERROR MESSAGE
int pcre2_get_error_message(int errorcode, PCRE2_UCHAR *buffer,
PCRE2_SIZE bufflen);
- A text message for an error code from any PCRE2 function (compile,
- match, or auxiliary) can be obtained by calling pcre2_get_error_mes-
- sage(). The code is passed as the first argument, with the remaining
- two arguments specifying a code unit buffer and its length in code
- units, into which the text message is placed. The message is returned
- in code units of the appropriate width for the library that is being
+ A text message for an error code from any PCRE2 function (compile,
+ match, or auxiliary) can be obtained by calling pcre2_get_error_mes-
+ sage(). The code is passed as the first argument, with the remaining
+ two arguments specifying a code unit buffer and its length in code
+ units, into which the text message is placed. The message is returned
+ in code units of the appropriate width for the library that is being
used.
- The returned message is terminated with a trailing zero, and the func-
- tion returns the number of code units used, excluding the trailing
- zero. If the error number is unknown, the negative error code
- PCRE2_ERROR_BADDATA is returned. If the buffer is too small, the mes-
- sage is truncated (but still with a trailing zero), and the negative
- error code PCRE2_ERROR_NOMEMORY is returned. None of the messages are
- very long; a buffer size of 120 code units is ample.
+ The returned message is terminated with a trailing zero, and the func-
+ tion returns the number of code units used, excluding the trailing
+ zero. If the error number is unknown, the negative error code PCRE2_ER-
+ ROR_BADDATA is returned. If the buffer is too small, the message is
+ truncated (but still with a trailing zero), and the negative error code
+ PCRE2_ERROR_NOMEMORY is returned. None of the messages are very long;
+ a buffer size of 120 code units is ample.
EXTRACTING CAPTURED SUBSTRINGS BY NUMBER
@@ -2914,40 +3021,40 @@ EXTRACTING CAPTURED SUBSTRINGS BY NUMBER
void pcre2_substring_free(PCRE2_UCHAR *buffer);
- Captured substrings can be accessed directly by using the ovector as
+ Captured substrings can be accessed directly by using the ovector as
described above. For convenience, auxiliary functions are provided for
- extracting captured substrings as new, separate, zero-terminated
+ extracting captured substrings as new, separate, zero-terminated
strings. A substring that contains a binary zero is correctly extracted
- and has a further zero added on the end, but the result is not, of
+ and has a further zero added on the end, but the result is not, of
course, a C string.
The functions in this section identify substrings by number. The number
zero refers to the entire matched substring, with higher numbers refer-
- ring to substrings captured by parenthesized groups. After a partial
- match, only substring zero is available. An attempt to extract any
- other substring gives the error PCRE2_ERROR_PARTIAL. The next section
+ ring to substrings captured by parenthesized groups. After a partial
+ match, only substring zero is available. An attempt to extract any
+ other substring gives the error PCRE2_ERROR_PARTIAL. The next section
describes similar functions for extracting captured substrings by name.
- If a pattern uses the \K escape sequence within a positive assertion,
+ If a pattern uses the \K escape sequence within a positive assertion,
the reported start of a successful match can be greater than the end of
- the match. For example, if the pattern (?=ab\K) is matched against
- "ab", the start and end offset values for the match are 2 and 0. In
- this situation, calling these functions with a zero substring number
+ the match. For example, if the pattern (?=ab\K) is matched against
+ "ab", the start and end offset values for the match are 2 and 0. In
+ this situation, calling these functions with a zero substring number
extracts a zero-length empty string.
- You can find the length in code units of a captured substring without
- extracting it by calling pcre2_substring_length_bynumber(). The first
- argument is a pointer to the match data block, the second is the group
- number, and the third is a pointer to a variable into which the length
- is placed. If you just want to know whether or not the substring has
+ You can find the length in code units of a captured substring without
+ extracting it by calling pcre2_substring_length_bynumber(). The first
+ argument is a pointer to the match data block, the second is the group
+ number, and the third is a pointer to a variable into which the length
+ is placed. If you just want to know whether or not the substring has
been captured, you can pass the third argument as NULL.
- The pcre2_substring_copy_bynumber() function copies a captured sub-
- string into a supplied buffer, whereas pcre2_substring_get_bynumber()
- copies it into new memory, obtained using the same memory allocation
- function that was used for the match data block. The first two argu-
- ments of these functions are a pointer to the match data block and a
- capturing group number.
+ The pcre2_substring_copy_bynumber() function copies a captured sub-
+ string into a supplied buffer, whereas pcre2_substring_get_bynumber()
+ copies it into new memory, obtained using the same memory allocation
+ function that was used for the match data block. The first two argu-
+ ments of these functions are a pointer to the match data block and a
+ capture group number.
The final arguments of pcre2_substring_copy_bynumber() are a pointer to
the buffer and a pointer to a variable that contains its length in code
@@ -2955,25 +3062,25 @@ EXTRACTING CAPTURED SUBSTRINGS BY NUMBER
for the extracted substring, excluding the terminating zero.
For pcre2_substring_get_bynumber() the third and fourth arguments point
- to variables that are updated with a pointer to the new memory and the
- number of code units that comprise the substring, again excluding the
- terminating zero. When the substring is no longer needed, the memory
+ to variables that are updated with a pointer to the new memory and the
+ number of code units that comprise the substring, again excluding the
+ terminating zero. When the substring is no longer needed, the memory
should be freed by calling pcre2_substring_free().
- The return value from all these functions is zero for success, or a
- negative error code. If the pattern match failed, the match failure
- code is returned. If a substring number greater than zero is used
- after a partial match, PCRE2_ERROR_PARTIAL is returned. Other possible
+ The return value from all these functions is zero for success, or a
+ negative error code. If the pattern match failed, the match failure
+ code is returned. If a substring number greater than zero is used af-
+ ter a partial match, PCRE2_ERROR_PARTIAL is returned. Other possible
error codes are:
PCRE2_ERROR_NOMEMORY
- The buffer was too small for pcre2_substring_copy_bynumber(), or the
+ The buffer was too small for pcre2_substring_copy_bynumber(), or the
attempt to get memory failed for pcre2_substring_get_bynumber().
PCRE2_ERROR_NOSUBSTRING
- There is no substring with that number in the pattern, that is, the
+ There is no substring with that number in the pattern, that is, the
number is greater than the number of capturing parentheses.
PCRE2_ERROR_UNAVAILABLE
@@ -2984,8 +3091,8 @@ EXTRACTING CAPTURED SUBSTRINGS BY NUMBER
PCRE2_ERROR_UNSET
- The substring did not participate in the match. For example, if the
- pattern is (abc)|(def) and the subject is "def", and the ovector con-
+ The substring did not participate in the match. For example, if the
+ pattern is (abc)|(def) and the subject is "def", and the ovector con-
tains at least two capturing slots, substring number 1 is unset.
@@ -2996,33 +3103,32 @@ EXTRACTING A LIST OF ALL CAPTURED SUBSTRINGS
void pcre2_substring_list_free(PCRE2_SPTR *list);
- The pcre2_substring_list_get() function extracts all available sub-
- strings and builds a list of pointers to them. It also (optionally)
- builds a second list that contains their lengths (in code units),
- excluding a terminating zero that is added to each of them. All this is
+ The pcre2_substring_list_get() function extracts all available sub-
+ strings and builds a list of pointers to them. It also (optionally)
+ builds a second list that contains their lengths (in code units), ex-
+ cluding a terminating zero that is added to each of them. All this is
done in a single block of memory that is obtained using the same memory
allocation function that was used to get the match data block.
- This function must be called only after a successful match. If called
+ This function must be called only after a successful match. If called
after a partial match, the error code PCRE2_ERROR_PARTIAL is returned.
- The address of the memory block is returned via listptr, which is also
+ The address of the memory block is returned via listptr, which is also
the start of the list of string pointers. The end of the list is marked
- by a NULL pointer. The address of the list of lengths is returned via
- lengthsptr. If your strings do not contain binary zeros and you do not
+ by a NULL pointer. The address of the list of lengths is returned via
+ lengthsptr. If your strings do not contain binary zeros and you do not
therefore need the lengths, you may supply NULL as the lengthsptr argu-
- ment to disable the creation of a list of lengths. The yield of the
- function is zero if all went well, or PCRE2_ERROR_NOMEMORY if the mem-
- ory block could not be obtained. When the list is no longer needed, it
+ ment to disable the creation of a list of lengths. The yield of the
+ function is zero if all went well, or PCRE2_ERROR_NOMEMORY if the mem-
+ ory block could not be obtained. When the list is no longer needed, it
should be freed by calling pcre2_substring_list_free().
If this function encounters a substring that is unset, which can happen
- when capturing subpattern number n+1 matches some part of the subject,
- but subpattern n has not been used at all, it returns an empty string.
- This can be distinguished from a genuine zero-length substring by
- inspecting the appropriate offset in the ovector, which contain
- PCRE2_UNSET for unset substrings, or by calling pcre2_sub-
- string_length_bynumber().
+ when capture group number n+1 matches some part of the subject, but
+ group n has not been used at all, it returns an empty string. This can
+ be distinguished from a genuine zero-length substring by inspecting the
+ appropriate offset in the ovector, which contain PCRE2_UNSET for unset
+ substrings, or by calling pcre2_substring_length_bynumber().
EXTRACTING CAPTURED SUBSTRINGS BY NAME
@@ -3046,34 +3152,35 @@ EXTRACTING CAPTURED SUBSTRINGS BY NAME
(a+)b(?\d+)...
- the number of the subpattern called "xxx" is 2. If the name is known to
- be unique (PCRE2_DUPNAMES was not set), you can find the number from
+ the number of the capture group called "xxx" is 2. If the name is known
+ to be unique (PCRE2_DUPNAMES was not set), you can find the number from
the name by calling pcre2_substring_number_from_name(). The first argu-
ment is the compiled pattern, and the second is the name. The yield of
- the function is the subpattern number, PCRE2_ERROR_NOSUBSTRING if there
- is no subpattern of that name, or PCRE2_ERROR_NOUNIQUESUBSTRING if
- there is more than one subpattern of that name. Given the number, you
- can extract the substring directly from the ovector, or use one of the
- "bynumber" functions described above.
+ the function is the group number, PCRE2_ERROR_NOSUBSTRING if there is
+ no group with that name, or PCRE2_ERROR_NOUNIQUESUBSTRING if there is
+ more than one group with that name. Given the number, you can extract
+ the substring directly from the ovector, or use one of the "bynumber"
+ functions described above.
For convenience, there are also "byname" functions that correspond to
- the "bynumber" functions, the only difference being that the second
- argument is a name instead of a number. If PCRE2_DUPNAMES is set and
+ the "bynumber" functions, the only difference being that the second ar-
+ gument is a name instead of a number. If PCRE2_DUPNAMES is set and
there are duplicate names, these functions scan all the groups with the
- given name, and return the first named string that is set.
-
- If there are no groups with the given name, PCRE2_ERROR_NOSUBSTRING is
- returned. If all groups with the name have numbers that are greater
- than the number of slots in the ovector, PCRE2_ERROR_UNAVAILABLE is
- returned. If there is at least one group with a slot in the ovector,
- but no group is found to be set, PCRE2_ERROR_UNSET is returned.
-
- Warning: If the pattern uses the (?| feature to set up multiple subpat-
- terns with the same number, as described in the section on duplicate
- subpattern numbers in the pcre2pattern page, you cannot use names to
- distinguish the different subpatterns, because names are not included
- in the compiled code. The matching process uses only numbers. For this
- reason, the use of different names for subpatterns of the same number
+ given name, and return the captured substring from the first named
+ group that is set.
+
+ If there are no groups with the given name, PCRE2_ERROR_NOSUBSTRING is
+ returned. If all groups with the name have numbers that are greater
+ than the number of slots in the ovector, PCRE2_ERROR_UNAVAILABLE is re-
+ turned. If there is at least one group with a slot in the ovector, but
+ no group is found to be set, PCRE2_ERROR_UNSET is returned.
+
+ Warning: If the pattern uses the (?| feature to set up multiple capture
+ groups with the same number, as described in the section on duplicate
+ group numbers in the pcre2pattern page, you cannot use names to distin-
+ guish the different capture groups, because names are not included in
+ the compiled code. The matching process uses only numbers. For this
+ reason, the use of different names for groups with the same number
causes an error at compile time.
@@ -3083,73 +3190,76 @@ CREATING A NEW STRING WITH SUBSTITUTIONS
PCRE2_SIZE length, PCRE2_SIZE startoffset,
uint32_t options, pcre2_match_data *match_data,
pcre2_match_context *mcontext, PCRE2_SPTR replacement,
- PCRE2_SIZE rlength, PCRE2_UCHAR *outputbufferP,
+ PCRE2_SIZE rlength, PCRE2_UCHAR *outputbuffer,
PCRE2_SIZE *outlengthptr);
- This function calls pcre2_match() and then makes a copy of the subject
- string in outputbuffer, replacing the part that was matched with the
- replacement string, whose length is supplied in rlength. This can be
- given as PCRE2_ZERO_TERMINATED for a zero-terminated string. Matches in
- which a \K item in a lookahead in the pattern causes the match to end
- before it starts are not supported, and give rise to an error return.
- For global replacements, matches in which \K in a lookbehind causes the
- match to start earlier than the point that was reached in the previous
- iteration are also not supported.
-
- The first seven arguments of pcre2_substitute() are the same as for
+ This function calls pcre2_match() and then makes a copy of the subject
+ string in outputbuffer, replacing one or more parts that were matched
+ with the replacement string, whose length is supplied in rlength. This
+ can be given as PCRE2_ZERO_TERMINATED for a zero-terminated string.
+ The default is to perform just one replacement, but there is an option
+ that requests multiple replacements (see PCRE2_SUBSTITUTE_GLOBAL below
+ for details).
+
+ Matches in which a \K item in a lookahead in the pattern causes the
+ match to end before it starts are not supported, and give rise to an
+ error return. For global replacements, matches in which \K in a lookbe-
+ hind causes the match to start earlier than the point that was reached
+ in the previous iteration are also not supported.
+
+ The first seven arguments of pcre2_substitute() are the same as for
pcre2_match(), except that the partial matching options are not permit-
- ted, and match_data may be passed as NULL, in which case a match data
- block is obtained and freed within this function, using memory manage-
- ment functions from the match context, if provided, or else those that
+ ted, and match_data may be passed as NULL, in which case a match data
+ block is obtained and freed within this function, using memory manage-
+ ment functions from the match context, if provided, or else those that
were used to allocate memory for the compiled code.
- If an external match_data block is provided, its contents afterwards
- are those set by the final call to pcre2_match(), which will have ended
- in a matching error. The contents of the ovector within the match data
- block may or may not have been changed.
+ If an external match_data block is provided, its contents afterwards
+ are those set by the final call to pcre2_match(). For global changes,
+ this will have ended in a matching error. The contents of the ovector
+ within the match data block may or may not have been changed.
- The outlengthptr argument must point to a variable that contains the
- length, in code units, of the output buffer. If the function is suc-
- cessful, the value is updated to contain the length of the new string,
+ The outlengthptr argument must point to a variable that contains the
+ length, in code units, of the output buffer. If the function is suc-
+ cessful, the value is updated to contain the length of the new string,
excluding the trailing zero that is automatically added.
- If the function is not successful, the value set via outlengthptr
- depends on the type of error. For syntax errors in the replacement
- string, the value is the offset in the replacement string where the
- error was detected. For other errors, the value is PCRE2_UNSET by
- default. This includes the case of the output buffer being too small,
- unless PCRE2_SUBSTITUTE_OVERFLOW_LENGTH is set (see below), in which
- case the value is the minimum length needed, including space for the
- trailing zero. Note that in order to compute the required length,
- pcre2_substitute() has to simulate all the matching and copying,
- instead of giving an error return as soon as the buffer overflows. Note
- also that the length is in code units, not bytes.
-
- In the replacement string, which is interpreted as a UTF string in UTF
- mode, and is checked for UTF validity unless the PCRE2_NO_UTF_CHECK
- option is set, a dollar character is an escape character that can spec-
- ify the insertion of characters from capturing groups or (*MARK),
- (*PRUNE), or (*THEN) items in the pattern. The following forms are
- always recognized:
+ If the function is not successful, the value set via outlengthptr de-
+ pends on the type of error. For syntax errors in the replacement
+ string, the value is the offset in the replacement string where the er-
+ ror was detected. For other errors, the value is PCRE2_UNSET by de-
+ fault. This includes the case of the output buffer being too small, un-
+ less PCRE2_SUBSTITUTE_OVERFLOW_LENGTH is set (see below), in which case
+ the value is the minimum length needed, including space for the trail-
+ ing zero. Note that in order to compute the required length, pcre2_sub-
+ stitute() has to simulate all the matching and copying, instead of giv-
+ ing an error return as soon as the buffer overflows. Note also that the
+ length is in code units, not bytes.
+
+ In the replacement string, which is interpreted as a UTF string in UTF
+ mode, and is checked for UTF validity unless the PCRE2_NO_UTF_CHECK op-
+ tion is set, a dollar character is an escape character that can specify
+ the insertion of characters from capture groups or names from (*MARK)
+ or other control verbs in the pattern. The following forms are always
+ recognized:
$$ insert a dollar character
$ or ${} insert the contents of group
- $*MARK or ${*MARK} insert a (*MARK), (*PRUNE), or (*THEN) name
+ $*MARK or ${*MARK} insert a control verb name
- Either a group number or a group name can be given for . Curly
- brackets are required only if the following character would be inter-
+ Either a group number or a group name can be given for . Curly
+ brackets are required only if the following character would be inter-
preted as part of the number or name. The number may be zero to include
- the entire matched string. For example, if the pattern a(b)c is
- matched with "=abc=" and the replacement string "+$1$0$1+", the result
+ the entire matched string. For example, if the pattern a(b)c is
+ matched with "=abc=" and the replacement string "+$1$0$1+", the result
is "=+babcb+=".
- $*MARK inserts the name from the last encountered (*MARK), (*PRUNE), or
- (*THEN) on the matching path that has a name. (*MARK) must always
- include a name, but (*PRUNE) and (*THEN) need not. For example, in the
- case of (*MARK:A)(*PRUNE) the name inserted is "A", but for
- (*MARK:A)(*PRUNE:B) the relevant name is "B". This facility can be
- used to perform simple simultaneous substitutions, as this pcre2test
- example shows:
+ $*MARK inserts the name from the last encountered backtracking control
+ verb on the matching path that has a name. (*MARK) must always include
+ a name, but the other verbs need not. For example, in the case of
+ (*MARK:A)(*PRUNE) the name inserted is "A", but for (*MARK:A)(*PRUNE:B)
+ the relevant name is "B". This facility can be used to perform simple
+ simultaneous substitutions, as this pcre2test example shows:
/(*MARK:pear)apple|(*MARK:orange)lemon/g,replace=${*MARK}
apple lemon
@@ -3188,8 +3298,8 @@ CREATING A NEW STRING WITH SUBSTITUTIONS
continues to go through the motions of matching and substituting (with-
out, of course, writing anything) in order to compute the size of buf-
fer that is needed. This value is passed back via the outlengthptr
- variable, with the result of the function still being
- PCRE2_ERROR_NOMEMORY.
+ variable, with the result of the function still being PCRE2_ER-
+ ROR_NOMEMORY.
Passing a buffer size of zero is a permitted way of finding out how
much memory is needed for given substitution. However, this does mean
@@ -3198,48 +3308,48 @@ CREATING A NEW STRING WITH SUBSTITUTIONS
the excess afterwards, instead of using PCRE2_SUBSTITUTE_OVER-
FLOW_LENGTH.
- PCRE2_SUBSTITUTE_UNKNOWN_UNSET causes references to capturing groups
- that do not appear in the pattern to be treated as unset groups. This
- option should be used with care, because it means that a typo in a
- group name or number no longer causes the PCRE2_ERROR_NOSUBSTRING
- error.
-
- PCRE2_SUBSTITUTE_UNSET_EMPTY causes unset capturing groups (including
- unknown groups when PCRE2_SUBSTITUTE_UNKNOWN_UNSET is set) to be
- treated as empty strings when inserted as described above. If this
- option is not set, an attempt to insert an unset group causes the
- PCRE2_ERROR_UNSET error. This option does not influence the extended
- substitution syntax described below.
-
- PCRE2_SUBSTITUTE_EXTENDED causes extra processing to be applied to the
- replacement string. Without this option, only the dollar character is
- special, and only the group insertion forms listed above are valid.
+ PCRE2_SUBSTITUTE_UNKNOWN_UNSET causes references to capture groups that
+ do not appear in the pattern to be treated as unset groups. This option
+ should be used with care, because it means that a typo in a group name
+ or number no longer causes the PCRE2_ERROR_NOSUBSTRING error.
+
+ PCRE2_SUBSTITUTE_UNSET_EMPTY causes unset capture groups (including un-
+ known groups when PCRE2_SUBSTITUTE_UNKNOWN_UNSET is set) to be treated
+ as empty strings when inserted as described above. If this option is
+ not set, an attempt to insert an unset group causes the PCRE2_ERROR_UN-
+ SET error. This option does not influence the extended substitution
+ syntax described below.
+
+ PCRE2_SUBSTITUTE_EXTENDED causes extra processing to be applied to the
+ replacement string. Without this option, only the dollar character is
+ special, and only the group insertion forms listed above are valid.
When PCRE2_SUBSTITUTE_EXTENDED is set, two things change:
- Firstly, backslash in a replacement string is interpreted as an escape
+ Firstly, backslash in a replacement string is interpreted as an escape
character. The usual forms such as \n or \x{ddd} can be used to specify
- particular character codes, and backslash followed by any non-alphanu-
- meric character quotes that character. Extended quoting can be coded
+ particular character codes, and backslash followed by any non-alphanu-
+ meric character quotes that character. Extended quoting can be coded
using \Q...\E, exactly as in pattern strings.
- There are also four escape sequences for forcing the case of inserted
- letters. The insertion mechanism has three states: no case forcing,
+ There are also four escape sequences for forcing the case of inserted
+ letters. The insertion mechanism has three states: no case forcing,
force upper case, and force lower case. The escape sequences change the
current state: \U and \L change to upper or lower case forcing, respec-
- tively, and \E (when not terminating a \Q quoted sequence) reverts to
- no case forcing. The sequences \u and \l force the next character (if
- it is a letter) to upper or lower case, respectively, and then the
+ tively, and \E (when not terminating a \Q quoted sequence) reverts to
+ no case forcing. The sequences \u and \l force the next character (if
+ it is a letter) to upper or lower case, respectively, and then the
state automatically reverts to no case forcing. Case forcing applies to
- all inserted characters, including those from captured groups and let-
+ all inserted characters, including those from capture groups and let-
ters within \Q...\E quoted sequences.
Note that case forcing sequences such as \U...\E do not nest. For exam-
- ple, the result of processing "\Uaa\LBB\Ecc\E" is "AAbbcc"; the final
- \E has no effect.
+ ple, the result of processing "\Uaa\LBB\Ecc\E" is "AAbbcc"; the final
+ \E has no effect. Note also that the PCRE2_ALT_BSUX and PCRE2_EX-
+ TRA_ALT_BSUX options do not apply to replacement strings.
The second effect of setting PCRE2_SUBSTITUTE_EXTENDED is to add more
- flexibility to group substitution. The syntax is similar to that used
- by Bash:
+ flexibility to capture group substitution. The syntax is similar to
+ that used by Bash:
${:-}
${:+:}
@@ -3265,11 +3375,11 @@ CREATING A NEW STRING WITH SUBSTITUTIONS
1: HELLO
The PCRE2_SUBSTITUTE_UNSET_EMPTY option does not affect these extended
- substitutions. However, PCRE2_SUBSTITUTE_UNKNOWN_UNSET does cause
- unknown groups in the extended syntax forms to be treated as unset.
+ substitutions. However, PCRE2_SUBSTITUTE_UNKNOWN_UNSET does cause un-
+ known groups in the extended syntax forms to be treated as unset.
- If successful, pcre2_substitute() returns the number of replacements
- that were made. This may be zero if no matches were found, and is never
+ If successful, pcre2_substitute() returns the number of successful
+ matches. This may be zero if no matches were found, and is never
greater than 1 unless PCRE2_SUBSTITUTE_GLOBAL is set.
In the event of an error, a negative error code is returned. Except for
@@ -3281,8 +3391,8 @@ CREATING A NEW STRING WITH SUBSTITUTIONS
PCRE2_ERROR_UNSET is returned for an unset substring insertion (includ-
ing an unknown substring when PCRE2_SUBSTITUTE_UNKNOWN_UNSET is set)
- when the simple (non-extended) syntax is used and PCRE2_SUBSTI-
- TUTE_UNSET_EMPTY is not set.
+ when the simple (non-extended) syntax is used and PCRE2_SUBSTITUTE_UN-
+ SET_EMPTY is not set.
PCRE2_ERROR_NOMEMORY is returned if the output buffer is not big
enough. If the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option is set, the size
@@ -3290,74 +3400,129 @@ CREATING A NEW STRING WITH SUBSTITUTIONS
does not happen by default.
PCRE2_ERROR_BADREPLACEMENT is used for miscellaneous syntax errors in
- the replacement string, with more particular errors being
- PCRE2_ERROR_BADREPESCAPE (invalid escape sequence), PCRE2_ERROR_REP-
- MISSINGBRACE (closing curly bracket not found), PCRE2_ERROR_BADSUBSTI-
- TUTION (syntax error in extended group substitution), and
- PCRE2_ERROR_BADSUBSPATTERN (the pattern match ended before it started
- or the match started earlier than the current position in the subject,
- which can happen if \K is used in an assertion).
+ the replacement string, with more particular errors being PCRE2_ER-
+ ROR_BADREPESCAPE (invalid escape sequence), PCRE2_ERROR_REPMISSINGBRACE
+ (closing curly bracket not found), PCRE2_ERROR_BADSUBSTITUTION (syntax
+ error in extended group substitution), and PCRE2_ERROR_BADSUBSPATTERN
+ (the pattern match ended before it started or the match started earlier
+ than the current position in the subject, which can happen if \K is
+ used in an assertion).
As for all PCRE2 errors, a text message that describes the error can be
- obtained by calling the pcre2_get_error_message() function (see
- "Obtaining a textual error message" above).
+ obtained by calling the pcre2_get_error_message() function (see "Ob-
+ taining a textual error message" above).
+ Substitution callouts
+
+ int pcre2_set_substitute_callout(pcre2_match_context *mcontext,
+ int (*callout_function)(pcre2_substitute_callout_block *, void *),
+ void *callout_data);
-DUPLICATE SUBPATTERN NAMES
+ The pcre2_set_substitution_callout() function can be used to specify a
+ callout function for pcre2_substitute(). This information is passed in
+ a match context. The callout function is called after each substitution
+ has been processed, but it can cause the replacement not to happen. The
+ callout function is not called for simulated substitutions that happen
+ as a result of the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option.
+
+ The first argument of the callout function is a pointer to a substitute
+ callout block structure, which contains the following fields, not nec-
+ essarily in this order:
+
+ uint32_t version;
+ uint32_t subscount;
+ PCRE2_SPTR input;
+ PCRE2_SPTR output;
+ PCRE2_SIZE *ovector;
+ uint32_t oveccount;
+ PCRE2_SIZE output_offsets[2];
+
+ The version field contains the version number of the block format. The
+ current version is 0. The version number will increase in future if
+ more fields are added, but the intention is never to remove any of the
+ existing fields.
+
+ The subscount field is the number of the current match. It is 1 for the
+ first callout, 2 for the second, and so on. The input and output point-
+ ers are copies of the values passed to pcre2_substitute().
+
+ The ovector field points to the ovector, which contains the result of
+ the most recent match. The oveccount field contains the number of pairs
+ that are set in the ovector, and is always greater than zero.
+
+ The output_offsets vector contains the offsets of the replacement in
+ the output string. This has already been processed for dollar and (if
+ requested) backslash substitutions as described above.
+
+ The second argument of the callout function is the value passed as
+ callout_data when the function was registered. The value returned by
+ the callout function is interpreted as follows:
+
+ If the value is zero, the replacement is accepted, and, if PCRE2_SUB-
+ STITUTE_GLOBAL is set, processing continues with a search for the next
+ match. If the value is not zero, the current replacement is not ac-
+ cepted. If the value is greater than zero, processing continues when
+ PCRE2_SUBSTITUTE_GLOBAL is set. Otherwise (the value is less than zero
+ or PCRE2_SUBSTITUTE_GLOBAL is not set), the the rest of the input is
+ copied to the output and the call to pcre2_substitute() exits, return-
+ ing the number of matches so far.
+
+
+DUPLICATE CAPTURE GROUP NAMES
int pcre2_substring_nametable_scan(const pcre2_code *code,
PCRE2_SPTR name, PCRE2_SPTR *first, PCRE2_SPTR *last);
- When a pattern is compiled with the PCRE2_DUPNAMES option, names for
- subpatterns are not required to be unique. Duplicate names are always
- allowed for subpatterns with the same number, created by using the (?|
- feature. Indeed, if such subpatterns are named, they are required to
- use the same names.
-
- Normally, patterns with duplicate names are such that in any one match,
- only one of the named subpatterns participates. An example is shown in
- the pcre2pattern documentation.
-
- When duplicates are present, pcre2_substring_copy_byname() and
- pcre2_substring_get_byname() return the first substring corresponding
- to the given name that is set. Only if none are set is
- PCRE2_ERROR_UNSET is returned. The pcre2_substring_number_from_name()
- function returns the error PCRE2_ERROR_NOUNIQUESUBSTRING when there are
- duplicate names.
-
- If you want to get full details of all captured substrings for a given
- name, you must use the pcre2_substring_nametable_scan() function. The
- first argument is the compiled pattern, and the second is the name. If
- the third and fourth arguments are NULL, the function returns a group
+ When a pattern is compiled with the PCRE2_DUPNAMES option, names for
+ capture groups are not required to be unique. Duplicate names are al-
+ ways allowed for groups with the same number, created by using the (?|
+ feature. Indeed, if such groups are named, they are required to use the
+ same names.
+
+ Normally, patterns that use duplicate names are such that in any one
+ match, only one of each set of identically-named groups participates.
+ An example is shown in the pcre2pattern documentation.
+
+ When duplicates are present, pcre2_substring_copy_byname() and
+ pcre2_substring_get_byname() return the first substring corresponding
+ to the given name that is set. Only if none are set is PCRE2_ERROR_UN-
+ SET is returned. The pcre2_substring_number_from_name() function re-
+ turns the error PCRE2_ERROR_NOUNIQUESUBSTRING when there are duplicate
+ names.
+
+ If you want to get full details of all captured substrings for a given
+ name, you must use the pcre2_substring_nametable_scan() function. The
+ first argument is the compiled pattern, and the second is the name. If
+ the third and fourth arguments are NULL, the function returns a group
number for a unique name, or PCRE2_ERROR_NOUNIQUESUBSTRING otherwise.
When the third and fourth arguments are not NULL, they must be pointers
- to variables that are updated by the function. After it has run, they
+ to variables that are updated by the function. After it has run, they
point to the first and last entries in the name-to-number table for the
- given name, and the function returns the length of each entry in code
- units. In both cases, PCRE2_ERROR_NOSUBSTRING is returned if there are
+ given name, and the function returns the length of each entry in code
+ units. In both cases, PCRE2_ERROR_NOSUBSTRING is returned if there are
no entries for the given name.
The format of the name table is described above in the section entitled
- Information about a pattern. Given all the relevant entries for the
- name, you can extract each of their numbers, and hence the captured
+ Information about a pattern. Given all the relevant entries for the
+ name, you can extract each of their numbers, and hence the captured
data.
FINDING ALL POSSIBLE MATCHES AT ONE POSITION
- The traditional matching function uses a similar algorithm to Perl,
- which stops when it finds the first match at a given point in the sub-
+ The traditional matching function uses a similar algorithm to Perl,
+ which stops when it finds the first match at a given point in the sub-
ject. If you want to find all possible matches, or the longest possible
- match at a given position, consider using the alternative matching
- function (see below) instead. If you cannot use the alternative func-
+ match at a given position, consider using the alternative matching
+ function (see below) instead. If you cannot use the alternative func-
tion, you can kludge it up by making use of the callout facility, which
is described in the pcre2callout documentation.
What you have to do is to insert a callout right at the end of the pat-
- tern. When your callout function is called, extract and save the cur-
- rent matched substring. Then return 1, which forces pcre2_match() to
- backtrack and try other alternatives. Ultimately, when it runs out of
+ tern. When your callout function is called, extract and save the cur-
+ rent matched substring. Then return 1, which forces pcre2_match() to
+ backtrack and try other alternatives. Ultimately, when it runs out of
matches, pcre2_match() will yield PCRE2_ERROR_NOMATCH.
@@ -3369,26 +3534,26 @@ MATCHING A PATTERN: THE ALTERNATIVE FUNCTION
pcre2_match_context *mcontext,
int *workspace, PCRE2_SIZE wscount);
- The function pcre2_dfa_match() is called to match a subject string
- against a compiled pattern, using a matching algorithm that scans the
+ The function pcre2_dfa_match() is called to match a subject string
+ against a compiled pattern, using a matching algorithm that scans the
subject string just once (not counting lookaround assertions), and does
- not backtrack. This has different characteristics to the normal algo-
- rithm, and is not compatible with Perl. Some of the features of PCRE2
- patterns are not supported. Nevertheless, there are times when this
- kind of matching can be useful. For a discussion of the two matching
+ not backtrack. This has different characteristics to the normal algo-
+ rithm, and is not compatible with Perl. Some of the features of PCRE2
+ patterns are not supported. Nevertheless, there are times when this
+ kind of matching can be useful. For a discussion of the two matching
algorithms, and a list of features that pcre2_dfa_match() does not sup-
port, see the pcre2matching documentation.
- The arguments for the pcre2_dfa_match() function are the same as for
+ The arguments for the pcre2_dfa_match() function are the same as for
pcre2_match(), plus two extras. The ovector within the match data block
is used in a different way, and this is described below. The other com-
- mon arguments are used in the same way as for pcre2_match(), so their
+ mon arguments are used in the same way as for pcre2_match(), so their
description is not repeated here.
- The two additional arguments provide workspace for the function. The
- workspace vector should contain at least 20 elements. It is used for
+ The two additional arguments provide workspace for the function. The
+ workspace vector should contain at least 20 elements. It is used for
keeping track of multiple paths through the pattern tree. More
- workspace is needed for patterns and subjects where there are a lot of
+ workspace is needed for patterns and subjects where there are a lot of
potential matches.
Here is an example of a simple call to pcre2_dfa_match():
@@ -3408,45 +3573,45 @@ MATCHING A PATTERN: THE ALTERNATIVE FUNCTION
Option bits for pcre_dfa_match()
- The unused bits of the options argument for pcre2_dfa_match() must be
- zero. The only bits that may be set are PCRE2_ANCHORED, PCRE2_ENDAN-
- CHORED, PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY,
- PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD,
- PCRE2_PARTIAL_SOFT, PCRE2_DFA_SHORTEST, and PCRE2_DFA_RESTART. All but
- the last four of these are exactly the same as for pcre2_match(), so
- their description is not repeated here.
+ The unused bits of the options argument for pcre2_dfa_match() must be
+ zero. The only bits that may be set are PCRE2_ANCHORED,
+ PCRE2_COPY_MATCHED_SUBJECT, PCRE2_ENDANCHORED, PCRE2_NOTBOL, PCRE2_NO-
+ TEOL, PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_UTF_CHECK,
+ PCRE2_PARTIAL_HARD, PCRE2_PARTIAL_SOFT, PCRE2_DFA_SHORTEST, and
+ PCRE2_DFA_RESTART. All but the last four of these are exactly the same
+ as for pcre2_match(), so their description is not repeated here.
PCRE2_PARTIAL_HARD
PCRE2_PARTIAL_SOFT
- These have the same general effect as they do for pcre2_match(), but
- the details are slightly different. When PCRE2_PARTIAL_HARD is set for
- pcre2_dfa_match(), it returns PCRE2_ERROR_PARTIAL if the end of the
+ These have the same general effect as they do for pcre2_match(), but
+ the details are slightly different. When PCRE2_PARTIAL_HARD is set for
+ pcre2_dfa_match(), it returns PCRE2_ERROR_PARTIAL if the end of the
subject is reached and there is still at least one matching possibility
that requires additional characters. This happens even if some complete
- matches have already been found. When PCRE2_PARTIAL_SOFT is set, the
- return code PCRE2_ERROR_NOMATCH is converted into PCRE2_ERROR_PARTIAL
- if the end of the subject is reached, there have been no complete
+ matches have already been found. When PCRE2_PARTIAL_SOFT is set, the
+ return code PCRE2_ERROR_NOMATCH is converted into PCRE2_ERROR_PARTIAL
+ if the end of the subject is reached, there have been no complete
matches, but there is still at least one matching possibility. The por-
- tion of the string that was inspected when the longest partial match
+ tion of the string that was inspected when the longest partial match
was found is set as the first matching string in both cases. There is a
- more detailed discussion of partial and multi-segment matching, with
+ more detailed discussion of partial and multi-segment matching, with
examples, in the pcre2partial documentation.
PCRE2_DFA_SHORTEST
- Setting the PCRE2_DFA_SHORTEST option causes the matching algorithm to
+ Setting the PCRE2_DFA_SHORTEST option causes the matching algorithm to
stop as soon as it has found one match. Because of the way the alterna-
- tive algorithm works, this is necessarily the shortest possible match
+ tive algorithm works, this is necessarily the shortest possible match
at the first possible matching point in the subject string.
PCRE2_DFA_RESTART
- When pcre2_dfa_match() returns a partial match, it is possible to call
+ When pcre2_dfa_match() returns a partial match, it is possible to call
it again, with additional subject characters, and have it continue with
the same match. The PCRE2_DFA_RESTART option requests this action; when
- it is set, the workspace and wscount options must reference the same
- vector as before because data about the match so far is left in them
+ it is set, the workspace and wscount options must reference the same
+ vector as before because data about the match so far is left in them
after a partial match. There is more discussion of this facility in the
pcre2partial documentation.
@@ -3454,8 +3619,8 @@ MATCHING A PATTERN: THE ALTERNATIVE FUNCTION
When pcre2_dfa_match() succeeds, it may have matched more than one sub-
string in the subject. Note, however, that all the matches from one run
- of the function start at the same point in the subject. The shorter
- matches are all initial substrings of the longer matches. For example,
+ of the function start at the same point in the subject. The shorter
+ matches are all initial substrings of the longer matches. For example,
if the pattern
<.*>
@@ -3470,61 +3635,68 @@ MATCHING A PATTERN: THE ALTERNATIVE FUNCTION
- On success, the yield of the function is a number greater than zero,
- which is the number of matched substrings. The offsets of the sub-
- strings are returned in the ovector, and can be extracted by number in
- the same way as for pcre2_match(), but the numbers bear no relation to
- any capturing groups that may exist in the pattern, because DFA match-
- ing does not support group capture.
+ On success, the yield of the function is a number greater than zero,
+ which is the number of matched substrings. The offsets of the sub-
+ strings are returned in the ovector, and can be extracted by number in
+ the same way as for pcre2_match(), but the numbers bear no relation to
+ any capture groups that may exist in the pattern, because DFA matching
+ does not support capturing.
- Calls to the convenience functions that extract substrings by name
- return the error PCRE2_ERROR_DFA_UFUNC (unsupported function) if used
- after a DFA match. The convenience functions that extract substrings by
+ Calls to the convenience functions that extract substrings by name re-
+ turn the error PCRE2_ERROR_DFA_UFUNC (unsupported function) if used af-
+ ter a DFA match. The convenience functions that extract substrings by
number never return PCRE2_ERROR_NOSUBSTRING.
- The matched strings are stored in the ovector in reverse order of
- length; that is, the longest matching string is first. If there were
- too many matches to fit into the ovector, the yield of the function is
+ The matched strings are stored in the ovector in reverse order of
+ length; that is, the longest matching string is first. If there were
+ too many matches to fit into the ovector, the yield of the function is
zero, and the vector is filled with the longest matches.
- NOTE: PCRE2's "auto-possessification" optimization usually applies to
- character repeats at the end of a pattern (as well as internally). For
- example, the pattern "a\d+" is compiled as if it were "a\d++". For DFA
- matching, this means that only one possible match is found. If you
- really do want multiple matches in such cases, either use an ungreedy
- repeat such as "a\d+?" or set the PCRE2_NO_AUTO_POSSESS option when
- compiling.
+ NOTE: PCRE2's "auto-possessification" optimization usually applies to
+ character repeats at the end of a pattern (as well as internally). For
+ example, the pattern "a\d+" is compiled as if it were "a\d++". For DFA
+ matching, this means that only one possible match is found. If you re-
+ ally do want multiple matches in such cases, either use an ungreedy re-
+ peat such as "a\d+?" or set the PCRE2_NO_AUTO_POSSESS option when com-
+ piling.
Error returns from pcre2_dfa_match()
The pcre2_dfa_match() function returns a negative number when it fails.
- Many of the errors are the same as for pcre2_match(), as described
+ Many of the errors are the same as for pcre2_match(), as described
above. There are in addition the following errors that are specific to
pcre2_dfa_match():
PCRE2_ERROR_DFA_UITEM
- This return is given if pcre2_dfa_match() encounters an item in the
- pattern that it does not support, for instance, the use of \C in a UTF
+ This return is given if pcre2_dfa_match() encounters an item in the
+ pattern that it does not support, for instance, the use of \C in a UTF
mode or a backreference.
PCRE2_ERROR_DFA_UCOND
- This return is given if pcre2_dfa_match() encounters a condition item
+ This return is given if pcre2_dfa_match() encounters a condition item
that uses a backreference for the condition, or a test for recursion in
- a specific group. These are not supported.
+ a specific capture group. These are not supported.
+
+ PCRE2_ERROR_DFA_UINVALID_UTF
+
+ This return is given if pcre2_dfa_match() is called for a pattern that
+ was compiled with PCRE2_MATCH_INVALID_UTF. This is not supported for
+ DFA matching.
PCRE2_ERROR_DFA_WSSIZE
- This return is given if pcre2_dfa_match() runs out of space in the
+ This return is given if pcre2_dfa_match() runs out of space in the
workspace vector.
PCRE2_ERROR_DFA_RECURSE
- When a recursive subpattern is processed, the matching function calls
- itself recursively, using private memory for the ovector and workspace.
- This error is given if the internal ovector is not large enough. This
- should be extremely rare, as a vector of size 1000 is used.
+ When a recursion or subroutine call is processed, the matching function
+ calls itself recursively, using private memory for the ovector and
+ workspace. This error is given if the internal ovector is not large
+ enough. This should be extremely rare, as a vector of size 1000 is
+ used.
PCRE2_ERROR_DFA_BADRESTART
@@ -3549,8 +3721,8 @@ AUTHOR
REVISION
- Last updated: 07 September 2018
- Copyright (c) 1997-2018 University of Cambridge.
+ Last updated: 02 September 2019
+ Copyright (c) 1997-2019 University of Cambridge.
------------------------------------------------------------------------------
@@ -3566,9 +3738,9 @@ BUILDING PCRE2
PCRE2 is distributed with a configure script that can be used to build
the library in Unix-like environments using the applications known as
Autotools. Also in the distribution are files to support building using
- CMake instead of configure. The text file README contains general
- information about building with Autotools (some of which is repeated
- below), and also has some comments about building on various operating
+ CMake instead of configure. The text file README contains general in-
+ formation about building with Autotools (some of which is repeated be-
+ low), and also has some comments about building on various operating
systems. There is a lot more information about building PCRE2 without
using Autotools (including information about using CMake and building
"by hand") in the text file called NON-AUTOTOOLS-BUILD. You should
@@ -3591,8 +3763,8 @@ PCRE2 BUILD-TIME OPTIONS
compiler, as described in NON-AUTOTOOLS-BUILD.
The complete list of options for configure (which includes the standard
- ones such as the selection of the installation directory) can be
- obtained by running
+ ones such as the selection of the installation directory) can be ob-
+ tained by running
./configure --help
@@ -3649,8 +3821,8 @@ UNICODE AND UTF SUPPORT
--disable-unicode
to the configure command. This setting applies to all three libraries.
- It is not possible to build one library with Unicode support, and
- another without, in the same configuration.
+ It is not possible to build one library with Unicode support, and an-
+ other without, in the same configuration.
Of itself, Unicode support does not make PCRE2 treat strings as UTF-8,
UTF-16 or UTF-32. To do that, applications that use the library can set
@@ -3676,8 +3848,8 @@ DISABLING THE USE OF \C
The \C escape sequence, which matches a single code unit, even in a UTF
mode, can cause unpredictable behaviour because it may leave the cur-
rent matching point in the middle of a multi-code-unit character. The
- application can lock it out by setting the PCRE2_NEVER_BACKSLASH_C
- option when calling pcre2_compile(). There is also a build-time option
+ application can lock it out by setting the PCRE2_NEVER_BACKSLASH_C op-
+ tion when calling pcre2_compile(). There is also a build-time option
--enable-never-backslash-C
@@ -3723,8 +3895,8 @@ NEWLINE RECOGNITION
--enable-newline-is-cr
- to the configure command. There is also an --enable-newline-is-lf
- option, which explicitly specifies linefeed as the newline character.
+ to the configure command. There is also an --enable-newline-is-lf op-
+ tion, which explicitly specifies linefeed as the newline character.
Alternatively, you can specify that line endings are to be indicated by
the two-character sequence CRLF (CR immediately followed by LF). If you
@@ -3836,8 +4008,8 @@ LIMITING PCRE2 RESOURCE USAGE
used, but because the size of each backtracking "frame" depends on the
number of capturing parentheses in a pattern, the amount of heap that
is used before the limit is reached varies from pattern to pattern.
- This limit was more useful in versions before 10.30, where function
- recursion was used for backtracking.
+ This limit was more useful in versions before 10.30, where function re-
+ cursion was used for backtracking.
As well as applying to pcre2_match(), the depth limit also controls the
depth of recursive function calls in pcre2_dfa_match(). These are used
@@ -3873,8 +4045,8 @@ USING EBCDIC CODE
--enable-ebcdic --disable-unicode
to the configure command. This setting implies --enable-rebuild-charta-
- bles. You should only use it if you know that you are in an EBCDIC
- environment (for example, an IBM mainframe operating system).
+ bles. You should only use it if you know that you are in an EBCDIC en-
+ vironment (for example, an IBM mainframe operating system).
It is not possible to support both EBCDIC and UTF-8 codes in the same
version of the library. Consequently, --enable-unicode and --enable-
@@ -3898,45 +4070,48 @@ USING EBCDIC CODE
PCRE2GREP SUPPORT FOR EXTERNAL SCRIPTS
- By default, on non-Windows systems, pcre2grep supports the use of call-
- outs with string arguments within the patterns it is matching, in order
- to run external scripts. For details, see the pcre2grep documentation.
- This support can be disabled by adding --disable-pcre2grep-callout to
- the configure command.
+ By default pcre2grep supports the use of callouts with string arguments
+ within the patterns it is matching. There are two kinds: one that gen-
+ erates output using local code, and another that calls an external pro-
+ gram or script. If --disable-pcre2grep-callout-fork is added to the
+ configure command, only the first kind of callout is supported; if
+ --disable-pcre2grep-callout is used, all callouts are completely ig-
+ nored. For more details of pcre2grep callouts, see the pcre2grep docu-
+ mentation.
PCRE2GREP OPTIONS FOR COMPRESSED FILE SUPPORT
- By default, pcre2grep reads all files as plain text. You can build it
- so that it recognizes files whose names end in .gz or .bz2, and reads
+ By default, pcre2grep reads all files as plain text. You can build it
+ so that it recognizes files whose names end in .gz or .bz2, and reads
them with libz or libbz2, respectively, by adding one or both of
--enable-pcre2grep-libz
--enable-pcre2grep-libbz2
to the configure command. These options naturally require that the rel-
- evant libraries are installed on your system. Configuration will fail
+ evant libraries are installed on your system. Configuration will fail
if they are not.
PCRE2GREP BUFFER SIZE
- pcre2grep uses an internal buffer to hold a "window" on the file it is
+ pcre2grep uses an internal buffer to hold a "window" on the file it is
scanning, in order to be able to output "before" and "after" lines when
it finds a match. The default starting size of the buffer is 20KiB. The
- buffer itself is three times this size, but because of the way it is
+ buffer itself is three times this size, but because of the way it is
used for holding "before" lines, the longest line that is guaranteed to
be processable is the notional buffer size. If a longer line is encoun-
- tered, pcre2grep automatically expands the buffer, up to a specified
- maximum size, whose default is 1MiB or the starting size, whichever is
- the larger. You can change the default parameter values by adding, for
+ tered, pcre2grep automatically expands the buffer, up to a specified
+ maximum size, whose default is 1MiB or the starting size, whichever is
+ the larger. You can change the default parameter values by adding, for
example,
--with-pcre2grep-bufsize=51200
--with-pcre2grep-max-bufsize=2097152
- to the configure command. The caller of pcre2grep can override these
- values by using --buffer-size and --max-buffer-size on the command
+ to the configure command. The caller of pcre2grep can override these
+ values by using --buffer-size and --max-buffer-size on the command
line.
@@ -3947,26 +4122,26 @@ PCRE2TEST OPTION FOR LIBREADLINE SUPPORT
--enable-pcre2test-libreadline
--enable-pcre2test-libedit
- to the configure command, pcre2test is linked with the libreadline
- orlibedit library, respectively, and when its input is from a terminal,
- it reads it using the readline() function. This provides line-editing
- and history facilities. Note that libreadline is GPL-licensed, so if
- you distribute a binary of pcre2test linked in this way, there may be
+ to the configure command, pcre2test is linked with the libreadline or-
+ libedit library, respectively, and when its input is from a terminal,
+ it reads it using the readline() function. This provides line-editing
+ and history facilities. Note that libreadline is GPL-licensed, so if
+ you distribute a binary of pcre2test linked in this way, there may be
licensing issues. These can be avoided by linking instead with libedit,
which has a BSD licence.
- Setting --enable-pcre2test-libreadline causes the -lreadline option to
- be added to the pcre2test build. In many operating environments with a
- sytem-installed readline library this is sufficient. However, in some
+ Setting --enable-pcre2test-libreadline causes the -lreadline option to
+ be added to the pcre2test build. In many operating environments with a
+ sytem-installed readline library this is sufficient. However, in some
environments (e.g. if an unmodified distribution version of readline is
- in use), some extra configuration may be necessary. The INSTALL file
+ in use), some extra configuration may be necessary. The INSTALL file
for libreadline says this:
"Readline uses the termcap functions, but does not link with
the termcap or curses library itself, allowing applications
which link with readline the to choose an appropriate library."
- If your environment has not been set up so that an appropriate library
+ If your environment has not been set up so that an appropriate library
is automatically included, you may need to add something like
LIBS="-ncurses"
@@ -3980,7 +4155,7 @@ INCLUDING DEBUGGING CODE
--enable-debug
- to the configure command, additional debugging code is included in the
+ to the configure command, additional debugging code is included in the
build. This feature is intended for use by the PCRE2 maintainers.
@@ -3990,10 +4165,9 @@ DEBUGGING WITH VALGRIND SUPPORT
--enable-valgrind
- to the configure command, PCRE2 will use valgrind annotations to mark
- certain memory regions as unaddressable. This allows it to detect
- invalid memory accesses, and is mostly useful for debugging PCRE2
- itself.
+ to the configure command, PCRE2 will use valgrind annotations to mark
+ certain memory regions as unaddressable. This allows it to detect in-
+ valid memory accesses, and is mostly useful for debugging PCRE2 itself.
CODE COVERAGE REPORTING
@@ -4052,6 +4226,21 @@ CODE COVERAGE REPORTING
mentation.
+DISABLING THE Z AND T FORMATTING MODIFIERS
+
+ The C99 standard defines formatting modifiers z and t for size_t and
+ ptrdiff_t values, respectively. By default, PCRE2 uses these modifiers
+ in environments other than Microsoft Visual Studio when __STDC_VER-
+ SION__ is defined and has a value greater than or equal to 199901L (in-
+ dicating C99). However, there is at least one environment that claims
+ to be C99 but does not support these modifiers. If
+
+ --disable-percent-zt
+
+ is specified, no use is made of the z or t modifiers. Instead or %td or
+ %zu, %lu is used, with a cast for size_t values.
+
+
SUPPORT FOR FUZZERS
There is a special option for use by people who want to run fuzzing
@@ -4060,8 +4249,8 @@ SUPPORT FOR FUZZERS
--enable-fuzz-support
At present this applies only to the 8-bit library. If set, it causes an
- extra library called libpcre2-fuzzsupport.a to be built, but not
- installed. This contains a single function called LLVMFuzzerTestOneIn-
+ extra library called libpcre2-fuzzsupport.a to be built, but not in-
+ stalled. This contains a single function called LLVMFuzzerTestOneIn-
put() whose arguments are a pointer to a string and the length of the
string. When called, this function tries to compile the string as a
pattern, and if that succeeds, to match it. This is done both with no
@@ -4104,8 +4293,8 @@ AUTHOR
REVISION
- Last updated: 26 April 2018
- Copyright (c) 1997-2018 University of Cambridge.
+ Last updated: 03 March 2019
+ Copyright (c) 1997-2019 University of Cambridge.
------------------------------------------------------------------------------
@@ -4135,21 +4324,26 @@ DESCRIPTION
its entry point in a match context (see pcre2_set_callout() in the
pcre2api documentation).
- Within a regular expression, (?C) indicates a point at which the
- external function is to be called. Different callout points can be
- identified by putting a number less than 256 after the letter C. The
- default value is zero. Alternatively, the argument may be a delimited
- string. The starting delimiter must be one of ` ' " ^ % # $ { and the
+ When using the pcre2_substitute() function, an additional callout fea-
+ ture is available. This does a callout after each change to the subject
+ string and is described in the pcre2api documentation; the rest of this
+ document is concerned with callouts during pattern matching.
+
+ Within a regular expression, (?C) indicates a point at which the
+ external function is to be called. Different callout points can be
+ identified by putting a number less than 256 after the letter C. The
+ default value is zero. Alternatively, the argument may be a delimited
+ string. The starting delimiter must be one of ` ' " ^ % # $ { and the
ending delimiter is the same as the start, except for {, where the end-
- ing delimiter is }. If the ending delimiter is needed within the
- string, it must be doubled. For example, this pattern has two callout
+ ing delimiter is }. If the ending delimiter is needed within the
+ string, it must be doubled. For example, this pattern has two callout
points:
(?C1)abc(?C"some ""arbitrary"" text")def
If the PCRE2_AUTO_CALLOUT option bit is set when a pattern is compiled,
- PCRE2 automatically inserts callouts, all with number 255, before each
- item in the pattern except for immediately before or after an explicit
+ PCRE2 automatically inserts callouts, all with number 255, before each
+ item in the pattern except for immediately before or after an explicit
callout. For example, if PCRE2_AUTO_CALLOUT is used with the pattern
A(?C3)B
@@ -4166,36 +4360,36 @@ DESCRIPTION
(?C255)A(?C255)((?C255)\d{2}(?C255)|(?C255)-(?C255)-(?C255))(?C255)
- Notice that there is a callout before and after each parenthesis and
+ Notice that there is a callout before and after each parenthesis and
alternation bar. If the pattern contains a conditional group whose con-
- dition is an assertion, an automatic callout is inserted immediately
- before the condition. Such a callout may also be inserted explicitly,
+ dition is an assertion, an automatic callout is inserted immediately
+ before the condition. Such a callout may also be inserted explicitly,
for example:
(?(?C9)(?=a)ab|de) (?(?C%text%)(?!=d)ab|de)
- This applies only to assertion conditions (because they are themselves
+ This applies only to assertion conditions (because they are themselves
independent groups).
- Callouts can be useful for tracking the progress of pattern matching.
+ Callouts can be useful for tracking the progress of pattern matching.
The pcre2test program has a pattern qualifier (/auto_callout) that sets
- automatic callouts. When any callouts are present, the output from
- pcre2test indicates how the pattern is being matched. This is useful
- information when you are trying to optimize the performance of a par-
+ automatic callouts. When any callouts are present, the output from
+ pcre2test indicates how the pattern is being matched. This is useful
+ information when you are trying to optimize the performance of a par-
ticular pattern.
MISSING CALLOUTS
- You should be aware that, because of optimizations in the way PCRE2
+ You should be aware that, because of optimizations in the way PCRE2
compiles and matches patterns, callouts sometimes do not happen exactly
as you might expect.
Auto-possessification
At compile time, PCRE2 "auto-possessifies" repeated items when it knows
- that what follows cannot be part of the repeat. For example, a+[bc] is
- compiled as if it were a++[bc]. The pcre2test output when this pattern
+ that what follows cannot be part of the repeat. For example, a+[bc] is
+ compiled as if it were a++[bc]. The pcre2test output when this pattern
is compiled with PCRE2_ANCHORED and PCRE2_AUTO_CALLOUT and then applied
to the string "aaaa" is:
@@ -4204,11 +4398,11 @@ MISSING CALLOUTS
+2 ^ ^ [bc]
No match
- This indicates that when matching [bc] fails, there is no backtracking
+ This indicates that when matching [bc] fails, there is no backtracking
into a+ (because it is being treated as a++) and therefore the callouts
- that would be taken for the backtracks do not occur. You can disable
- the auto-possessify feature by passing PCRE2_NO_AUTO_POSSESS to
- pcre2_compile(), or starting the pattern with (*NO_AUTO_POSSESS). In
+ that would be taken for the backtracks do not occur. You can disable
+ the auto-possessify feature by passing PCRE2_NO_AUTO_POSSESS to
+ pcre2_compile(), or starting the pattern with (*NO_AUTO_POSSESS). In
this case, the output changes to this:
--->aaaa
@@ -4225,19 +4419,19 @@ MISSING CALLOUTS
Automatic .* anchoring
By default, an optimization is applied when .* is the first significant
- item in a pattern. If PCRE2_DOTALL is set, so that the dot can match
- any character, the pattern is automatically anchored. If PCRE2_DOTALL
- is not set, a match can start only after an internal newline or at the
+ item in a pattern. If PCRE2_DOTALL is set, so that the dot can match
+ any character, the pattern is automatically anchored. If PCRE2_DOTALL
+ is not set, a match can start only after an internal newline or at the
beginning of the subject, and pcre2_compile() remembers this. If a pat-
- tern has more than one top-level branch, automatic anchoring occurs if
+ tern has more than one top-level branch, automatic anchoring occurs if
all branches are anchorable.
- This optimization is disabled, however, if .* is in an atomic group or
- if there is a backreference to the capturing group in which it appears.
- It is also disabled if the pattern contains (*PRUNE) or (*SKIP). How-
+ This optimization is disabled, however, if .* is in an atomic group or
+ if there is a backreference to the capture group in which it appears.
+ It is also disabled if the pattern contains (*PRUNE) or (*SKIP). How-
ever, the presence of callouts does not affect it.
- For example, if the pattern .*\d is compiled with PCRE2_AUTO_CALLOUT
+ For example, if the pattern .*\d is compiled with PCRE2_AUTO_CALLOUT
and applied to the string "aa", the pcre2test output is:
--->aa
@@ -4247,10 +4441,10 @@ MISSING CALLOUTS
+2 ^ \d
No match
- This shows that all match attempts start at the beginning of the sub-
- ject. In other words, the pattern is anchored. You can disable this
- optimization by passing PCRE2_NO_DOTSTAR_ANCHOR to pcre2_compile(), or
- starting the pattern with (*NO_DOTSTAR_ANCHOR). In this case, the out-
+ This shows that all match attempts start at the beginning of the sub-
+ ject. In other words, the pattern is anchored. You can disable this op-
+ timization by passing PCRE2_NO_DOTSTAR_ANCHOR to pcre2_compile(), or
+ starting the pattern with (*NO_DOTSTAR_ANCHOR). In this case, the out-
put changes to:
--->aa
@@ -4263,42 +4457,42 @@ MISSING CALLOUTS
+2 ^ \d
No match
- This shows more match attempts, starting at the second subject charac-
- ter. Another optimization, described in the next section, means that
+ This shows more match attempts, starting at the second subject charac-
+ ter. Another optimization, described in the next section, means that
there is no subsequent attempt to match with an empty subject.
Other optimizations
- Other optimizations that provide fast "no match" results also affect
+ Other optimizations that provide fast "no match" results also affect
callouts. For example, if the pattern is
ab(?C4)cd
- PCRE2 knows that any matching string must contain the letter "d". If
- the subject string is "abyz", the lack of "d" means that matching
- doesn't ever start, and the callout is never reached. However, with
+ PCRE2 knows that any matching string must contain the letter "d". If
+ the subject string is "abyz", the lack of "d" means that matching
+ doesn't ever start, and the callout is never reached. However, with
"abyd", though the result is still no match, the callout is obeyed.
- For most patterns PCRE2 also knows the minimum length of a matching
- string, and will immediately give a "no match" return without actually
- running a match if the subject is not long enough, or, for unanchored
+ For most patterns PCRE2 also knows the minimum length of a matching
+ string, and will immediately give a "no match" return without actually
+ running a match if the subject is not long enough, or, for unanchored
patterns, if it has been scanned far enough.
You can disable these optimizations by passing the PCRE2_NO_START_OPTI-
- MIZE option to pcre2_compile(), or by starting the pattern with
- (*NO_START_OPT). This slows down the matching process, but does ensure
+ MIZE option to pcre2_compile(), or by starting the pattern with
+ (*NO_START_OPT). This slows down the matching process, but does ensure
that callouts such as the example above are obeyed.
THE CALLOUT INTERFACE
- During matching, when PCRE2 reaches a callout point, if an external
- function is provided in the match context, it is called. This applies
- to both normal, DFA, and JIT matching. The first argument to the call-
+ During matching, when PCRE2 reaches a callout point, if an external
+ function is provided in the match context, it is called. This applies
+ to both normal, DFA, and JIT matching. The first argument to the call-
out function is a pointer to a pcre2_callout block. The second argument
- is the void * callout data that was supplied when the callout was set
+ is the void * callout data that was supplied when the callout was set
up by calling pcre2_set_callout() (see the pcre2api documentation). The
- callout block structure contains the following fields, not necessarily
+ callout block structure contains the following fields, not necessarily
in this order:
uint32_t version;
@@ -4318,118 +4512,118 @@ THE CALLOUT INTERFACE
PCRE2_SIZE callout_string_length;
PCRE2_SPTR callout_string;
- The version field contains the version number of the block format. The
- current version is 2; the three callout string fields were added for
- version 1, and the callout_flags field for version 2. If you are writ-
- ing an application that might use an earlier release of PCRE2, you
- should check the version number before accessing any of these fields.
- The version number will increase in future if more fields are added,
+ The version field contains the version number of the block format. The
+ current version is 2; the three callout string fields were added for
+ version 1, and the callout_flags field for version 2. If you are writ-
+ ing an application that might use an earlier release of PCRE2, you
+ should check the version number before accessing any of these fields.
+ The version number will increase in future if more fields are added,
but the intention is never to remove any of the existing fields.
Fields for numerical callouts
- For a numerical callout, callout_string is NULL, and callout_number
- contains the number of the callout, in the range 0-255. This is the
- number that follows (?C for callouts that part of the pattern; it is
+ For a numerical callout, callout_string is NULL, and callout_number
+ contains the number of the callout, in the range 0-255. This is the
+ number that follows (?C for callouts that part of the pattern; it is
255 for automatically generated callouts.
Fields for string callouts
- For callouts with string arguments, callout_number is always zero, and
- callout_string points to the string that is contained within the com-
+ For callouts with string arguments, callout_number is always zero, and
+ callout_string points to the string that is contained within the com-
piled pattern. Its length is given by callout_string_length. Duplicated
ending delimiters that were present in the original pattern string have
been turned into single characters, but there is no other processing of
- the callout string argument. An additional code unit containing binary
- zero is present after the string, but is not included in the length.
- The delimiter that was used to start the string is also stored within
- the pattern, immediately before the string itself. You can access this
+ the callout string argument. An additional code unit containing binary
+ zero is present after the string, but is not included in the length.
+ The delimiter that was used to start the string is also stored within
+ the pattern, immediately before the string itself. You can access this
delimiter as callout_string[-1] if you need it.
The callout_string_offset field is the code unit offset to the start of
the callout argument string within the original pattern string. This is
- provided for the benefit of applications such as script languages that
+ provided for the benefit of applications such as script languages that
might need to report errors in the callout string within the pattern.
Fields for all callouts
- The remaining fields in the callout block are the same for both kinds
+ The remaining fields in the callout block are the same for both kinds
of callout.
- The offset_vector field is a pointer to a vector of capturing offsets
+ The offset_vector field is a pointer to a vector of capturing offsets
(the "ovector"). You may read the elements in this vector, but you must
not change any of them.
- For calls to pcre2_match(), the offset_vector field is not (since
- release 10.30) a pointer to the actual ovector that was passed to the
- matching function in the match data block. Instead it points to an
- internal ovector of a size large enough to hold all possible captured
+ For calls to pcre2_match(), the offset_vector field is not (since re-
+ lease 10.30) a pointer to the actual ovector that was passed to the
+ matching function in the match data block. Instead it points to an in-
+ ternal ovector of a size large enough to hold all possible captured
substrings in the pattern. Note that whenever a recursion or subroutine
- call within a pattern completes, the capturing state is reset to what
+ call within a pattern completes, the capturing state is reset to what
it was before.
- The capture_last field contains the number of the most recently cap-
- tured substring, and the capture_top field contains one more than the
- number of the highest numbered captured substring so far. If no sub-
- strings have yet been captured, the value of capture_last is 0 and the
- value of capture_top is 1. The values of these fields do not always
- differ by one; for example, when the callout in the pattern
+ The capture_last field contains the number of the most recently cap-
+ tured substring, and the capture_top field contains one more than the
+ number of the highest numbered captured substring so far. If no sub-
+ strings have yet been captured, the value of capture_last is 0 and the
+ value of capture_top is 1. The values of these fields do not always
+ differ by one; for example, when the callout in the pattern
((a)(b))(?C2) is taken, capture_last is 1 but capture_top is 4.
- The contents of ovector[2] to ovector[*2-1] can be
- inspected in order to extract substrings that have been matched so far,
- in the same way as extracting substrings after a match has completed.
- The values in ovector[0] and ovector[1] are always PCRE2_UNSET because
- the match is by definition not complete. Substrings that have not been
- captured but whose numbers are less than capture_top also have both of
+ The contents of ovector[2] to ovector[*2-1] can be in-
+ spected in order to extract substrings that have been matched so far,
+ in the same way as extracting substrings after a match has completed.
+ The values in ovector[0] and ovector[1] are always PCRE2_UNSET because
+ the match is by definition not complete. Substrings that have not been
+ captured but whose numbers are less than capture_top also have both of
their ovector slots set to PCRE2_UNSET.
- For DFA matching, the offset_vector field points to the ovector that
- was passed to the matching function in the match data block for call-
+ For DFA matching, the offset_vector field points to the ovector that
+ was passed to the matching function in the match data block for call-
outs at the top level, but to an internal ovector during the processing
- of pattern recursions, lookarounds, and atomic groups. However, these
- ovectors hold no useful information because pcre2_dfa_match() does not
- support substring capturing. The value of capture_top is always 1 and
+ of pattern recursions, lookarounds, and atomic groups. However, these
+ ovectors hold no useful information because pcre2_dfa_match() does not
+ support substring capturing. The value of capture_top is always 1 and
the value of capture_last is always 0 for DFA matching.
The subject and subject_length fields contain copies of the values that
were passed to the matching function.
- The start_match field normally contains the offset within the subject
- at which the current match attempt started. However, if the escape
- sequence \K has been encountered, this value is changed to reflect the
- modified starting point. If the pattern is not anchored, the callout
+ The start_match field normally contains the offset within the subject
+ at which the current match attempt started. However, if the escape se-
+ quence \K has been encountered, this value is changed to reflect the
+ modified starting point. If the pattern is not anchored, the callout
function may be called several times from the same point in the pattern
for different starting points in the subject.
- The current_position field contains the offset within the subject of
+ The current_position field contains the offset within the subject of
the current match pointer.
The pattern_position field contains the offset in the pattern string to
the next item to be matched.
- The next_item_length field contains the length of the next item to be
- processed in the pattern string. When the callout is at the end of the
- pattern, the length is zero. When the callout precedes an opening
+ The next_item_length field contains the length of the next item to be
+ processed in the pattern string. When the callout is at the end of the
+ pattern, the length is zero. When the callout precedes an opening
parenthesis, the length includes meta characters that follow the paren-
- thesis. For example, in a callout before an assertion such as (?=ab)
- the length is 3. For an an alternation bar or a closing parenthesis,
- the length is one, unless a closing parenthesis is followed by a quan-
+ thesis. For example, in a callout before an assertion such as (?=ab)
+ the length is 3. For an an alternation bar or a closing parenthesis,
+ the length is one, unless a closing parenthesis is followed by a quan-
tifier, in which case its length is included. (This changed in release
- 10.23. In earlier releases, before an opening parenthesis the length
- was that of the entire subpattern, and before an alternation bar or a
- closing parenthesis the length was zero.)
+ 10.23. In earlier releases, before an opening parenthesis the length
+ was that of the entire group, and before an alternation bar or a clos-
+ ing parenthesis the length was zero.)
- The pattern_position and next_item_length fields are intended to help
- in distinguishing between different automatic callouts, which all have
- the same callout number. However, they are set for all callouts, and
+ The pattern_position and next_item_length fields are intended to help
+ in distinguishing between different automatic callouts, which all have
+ the same callout number. However, they are set for all callouts, and
are used by pcre2test to show the next item to be matched when display-
ing callout information.
In callouts from pcre2_match() the mark field contains a pointer to the
- zero-terminated name of the most recently passed (*MARK), (*PRUNE), or
- (*THEN) item in the match, or NULL if no such items have been passed.
- Instances of (*PRUNE) or (*THEN) without a name do not obliterate a
+ zero-terminated name of the most recently passed (*MARK), (*PRUNE), or
+ (*THEN) item in the match, or NULL if no such items have been passed.
+ Instances of (*PRUNE) or (*THEN) without a name do not obliterate a
previous (*MARK). In callouts from the DFA matching function this field
always contains NULL.
@@ -4439,25 +4633,25 @@ THE CALLOUT INTERFACE
PCRE2_CALLOUT_STARTMATCH
- This is set for the first callout after the start of matching for each
+ This is set for the first callout after the start of matching for each
new starting position in the subject.
PCRE2_CALLOUT_BACKTRACK
- This is set if there has been a matching backtrack since the previous
- callout, or since the start of matching if this is the first callout
+ This is set if there has been a matching backtrack since the previous
+ callout, or since the start of matching if this is the first callout
from a pcre2_match() run.
- Both bits are set when a backtrack has caused a "bumpalong" to a new
- starting position in the subject. Output from pcre2test does not indi-
- cate the presence of these bits unless the callout_extra modifier is
+ Both bits are set when a backtrack has caused a "bumpalong" to a new
+ starting position in the subject. Output from pcre2test does not indi-
+ cate the presence of these bits unless the callout_extra modifier is
set.
The information in the callout_flags field is provided so that applica-
- tions can track and tell their users how matching with backtracking is
- done. This can be useful when trying to optimize patterns, or just to
- understand how PCRE2 works. There is no support in pcre2_dfa_match()
- because there is no backtracking in DFA matching, and there is no sup-
+ tions can track and tell their users how matching with backtracking is
+ done. This can be useful when trying to optimize patterns, or just to
+ understand how PCRE2 works. There is no support in pcre2_dfa_match()
+ because there is no backtracking in DFA matching, and there is no sup-
port in JIT because JIT is all about maximimizing matching performance.
In both these cases the callout_flags field is always zero.
@@ -4465,17 +4659,16 @@ THE CALLOUT INTERFACE
RETURN VALUES FROM CALLOUTS
The external callout function returns an integer to PCRE2. If the value
- is zero, matching proceeds as normal. If the value is greater than
- zero, matching fails at the current point, but the testing of other
+ is zero, matching proceeds as normal. If the value is greater than
+ zero, matching fails at the current point, but the testing of other
matching possibilities goes ahead, just as if a lookahead assertion had
failed. If the value is less than zero, the match is abandoned, and the
matching function returns the negative value.
- Negative values should normally be chosen from the set of
- PCRE2_ERROR_xxx values. In particular, PCRE2_ERROR_NOMATCH forces a
- standard "no match" failure. The error number PCRE2_ERROR_CALLOUT is
- reserved for use by callout functions; it will never be used by PCRE2
- itself.
+ Negative values should normally be chosen from the set of PCRE2_ER-
+ ROR_xxx values. In particular, PCRE2_ERROR_NOMATCH forces a standard
+ "no match" failure. The error number PCRE2_ERROR_CALLOUT is reserved
+ for use by callout functions; it will never be used by PCRE2 itself.
CALLOUT ENUMERATION
@@ -4530,8 +4723,8 @@ AUTHOR
REVISION
- Last updated: 26 April 2018
- Copyright (c) 1997-2018 University of Cambridge.
+ Last updated: 03 February 2019
+ Copyright (c) 1997-2019 University of Cambridge.
------------------------------------------------------------------------------
@@ -4545,25 +4738,25 @@ NAME
DIFFERENCES BETWEEN PCRE2 AND PERL
This document describes the differences in the ways that PCRE2 and Perl
- handle regular expressions. The differences described here are with
- respect to Perl versions 5.26, but as both Perl and PCRE2 are continu-
- ally changing, the information may sometimes be out of date.
+ handle regular expressions. The differences described here are with re-
+ spect to Perl versions 5.26, but as both Perl and PCRE2 are continually
+ changing, the information may sometimes be out of date.
1. PCRE2 has only a subset of Perl's Unicode support. Details of what
it does have are given in the pcre2unicode page.
2. Like Perl, PCRE2 allows repeat quantifiers on parenthesized asser-
tions, but they do not mean what you might think. For example, (?!a){3}
- does not assert that the next three characters are not "a". It just
- asserts that the next character is not "a" three times (in principle;
+ does not assert that the next three characters are not "a". It just as-
+ serts that the next character is not "a" three times (in principle;
PCRE2 optimizes this to run the assertion just once). Perl allows some
repeat quantifiers on other assertions, for example, \b* (but not
\b{3}), but these do not seem to have any use.
- 3. Capturing subpatterns that occur inside negative lookaround asser-
- tions are counted, but their entries in the offsets vector are set only
- when a negative assertion is a condition that has a matching branch
- (that is, the condition is false).
+ 3. Capture groups that occur inside negative lookaround assertions are
+ counted, but their entries in the offsets vector are set only when a
+ negative assertion is a condition that has a matching branch (that is,
+ the condition is false).
4. The following Perl escape sequences are not supported: \F, \l, \L,
\u, \U, and \N when followed by a character name. \N on its own, match-
@@ -4571,28 +4764,29 @@ DIFFERENCES BETWEEN PCRE2 AND PERL
point, are supported. The escapes that modify the case of following
letters are implemented by Perl's general string-handling and are not
part of its pattern matching engine. If any of these are encountered by
- PCRE2, an error is generated by default. However, if the PCRE2_ALT_BSUX
- option is set, \U and \u are interpreted as ECMAScript interprets them.
+ PCRE2, an error is generated by default. However, if either of the
+ PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX options is set, \U and \u are
+ interpreted as ECMAScript interprets them.
5. The Perl escape sequences \p, \P, and \X are supported only if PCRE2
is built with Unicode support (the default). The properties that can be
- tested with \p and \P are limited to the general category properties
- such as Lu and Nd, script names such as Greek or Han, and the derived
+ tested with \p and \P are limited to the general category properties
+ such as Lu and Nd, script names such as Greek or Han, and the derived
properties Any and L&. PCRE2 does support the Cs (surrogate) property,
- which Perl does not; the Perl documentation says "Because Perl hides
+ which Perl does not; the Perl documentation says "Because Perl hides
the need for the user to understand the internal representation of Uni-
- code characters, there is no need to implement the somewhat messy con-
+ code characters, there is no need to implement the somewhat messy con-
cept of surrogates."
6. PCRE2 supports the \Q...\E escape for quoting substrings. Characters
in between are treated as literals. However, this is slightly different
- from Perl in that $ and @ are also handled as literals inside the
+ from Perl in that $ and @ are also handled as literals inside the
quotes. In Perl, they cause variable interpolation (but of course PCRE2
- does not have variables). Also, Perl does "double-quotish backslash
- interpolation" on any backslashes between \Q and \E which, its documen-
- tation says, "may lead to confusing results". PCRE2 treats a backslash
- between \Q and \E just like any other character. Note the following
- examples:
+ does not have variables). Also, Perl does "double-quotish backslash in-
+ terpolation" on any backslashes between \Q and \E which, its documenta-
+ tion says, "may lead to confusing results". PCRE2 treats a backslash
+ between \Q and \E just like any other character. Note the following ex-
+ amples:
Pattern PCRE2 matches Perl matches
@@ -4603,55 +4797,54 @@ DIFFERENCES BETWEEN PCRE2 AND PERL
\QA\B\E A\B A\B
\Q\\E \ \\E
- The \Q...\E sequence is recognized both inside and outside character
+ The \Q...\E sequence is recognized both inside and outside character
classes.
- 7. Fairly obviously, PCRE2 does not support the (?{code}) and
+ 7. Fairly obviously, PCRE2 does not support the (?{code}) and
(??{code}) constructions. However, PCRE2 does have a "callout" feature,
which allows an external function to be called during pattern matching.
See the pcre2callout documentation for details.
- 8. Subroutine calls (whether recursive or not) were treated as atomic
- groups up to PCRE2 release 10.23, but from release 10.30 this changed,
+ 8. Subroutine calls (whether recursive or not) were treated as atomic
+ groups up to PCRE2 release 10.23, but from release 10.30 this changed,
and backtracking into subroutine calls is now supported, as in Perl.
- 9. If any of the backtracking control verbs are used in a subpattern
- that is called as a subroutine (whether or not recursively), their
- effect is confined to that subpattern; it does not extend to the sur-
- rounding pattern. This is not always the case in Perl. In particular,
- if (*THEN) is present in a group that is called as a subroutine, its
- action is limited to that group, even if the group does not contain any
- | characters. Note that such subpatterns are processed as anchored at
- the point where they are tested.
-
- 10. If a pattern contains more than one backtracking control verb, the
- first one that is backtracked onto acts. For example, in the pattern
- A(*COMMIT)B(*PRUNE)C a failure in B triggers (*COMMIT), but a failure
+ 9. If any of the backtracking control verbs are used in a group that is
+ called as a subroutine (whether or not recursively), their effect is
+ confined to that group; it does not extend to the surrounding pattern.
+ This is not always the case in Perl. In particular, if (*THEN) is
+ present in a group that is called as a subroutine, its action is lim-
+ ited to that group, even if the group does not contain any | charac-
+ ters. Note that such groups are processed as anchored at the point
+ where they are tested.
+
+ 10. If a pattern contains more than one backtracking control verb, the
+ first one that is backtracked onto acts. For example, in the pattern
+ A(*COMMIT)B(*PRUNE)C a failure in B triggers (*COMMIT), but a failure
in C triggers (*PRUNE). Perl's behaviour is more complex; in many cases
it is the same as PCRE2, but there are cases where it differs.
- 11. Most backtracking verbs in assertions have their normal actions.
+ 11. Most backtracking verbs in assertions have their normal actions.
They are not confined to the assertion.
- 12. There are some differences that are concerned with the settings of
- captured strings when part of a pattern is repeated. For example,
- matching "aba" against the pattern /^(a(b)?)+$/ in Perl leaves $2
- unset, but in PCRE2 it is set to "b".
-
- 13. PCRE2's handling of duplicate subpattern numbers and duplicate sub-
- pattern names is not as general as Perl's. This is a consequence of the
- fact the PCRE2 works internally just with numbers, using an external
- table to translate between numbers and names. In particular, a pattern
- such as (?|(?A)|(?B), where the two capturing parentheses have
- the same number but different names, is not supported, and causes an
- error at compile time. If it were allowed, it would not be possible to
- distinguish which parentheses matched, because both names map to cap-
- turing subpattern number 1. To avoid this confusing situation, an error
- is given at compile time.
+ 12. There are some differences that are concerned with the settings of
+ captured strings when part of a pattern is repeated. For example,
+ matching "aba" against the pattern /^(a(b)?)+$/ in Perl leaves $2 un-
+ set, but in PCRE2 it is set to "b".
+
+ 13. PCRE2's handling of duplicate capture group numbers and names is
+ not as general as Perl's. This is a consequence of the fact the PCRE2
+ works internally just with numbers, using an external table to trans-
+ late between numbers and names. In particular, a pattern such as
+ (?|(?A)|(?B), where the two capture groups have the same number
+ but different names, is not supported, and causes an error at compile
+ time. If it were allowed, it would not be possible to distinguish which
+ group matched, because both names map to capture group number 1. To
+ avoid this confusing situation, an error is given at compile time.
14. Perl used to recognize comments in some places that PCRE2 does not,
- for example, between the ( and ? at the start of a subpattern. If the
- /x modifier is set, Perl allowed white space between ( and ? though the
+ for example, between the ( and ? at the start of a group. If the /x
+ modifier is set, Perl allowed white space between ( and ? though the
latest Perls give an error (for a while it was just deprecated). There
may still be some cases where Perl behaves differently.
@@ -4667,10 +4860,10 @@ DIFFERENCES BETWEEN PCRE2 AND PERL
\p{Ll} match all letters, regardless of case, when case independence is
specified.
- 17. PCRE2 provides some extensions to the Perl regular expression
- facilities. Perl 5.10 includes new features that are not in earlier
- versions of Perl, some of which (such as named parentheses) were in
- PCRE2 for some time before. This list is with respect to Perl 5.26:
+ 17. PCRE2 provides some extensions to the Perl regular expression fa-
+ cilities. Perl 5.10 includes new features that are not in earlier ver-
+ sions of Perl, some of which (such as named parentheses) were in PCRE2
+ for some time before. This list is with respect to Perl 5.26:
(a) Although lookbehind assertions in PCRE2 must match fixed length
strings, each alternative branch of a lookbehind assertion can match a
@@ -4713,9 +4906,13 @@ DIFFERENCES BETWEEN PCRE2 AND PERL
at the start of a pattern that set overall options that cannot be
changed within the pattern.
+ (m) PCRE2 supports non-atomic positive lookaround assertions. This is
+ an extension to the lookaround facilities. The default, Perl-compatible
+ lookarounds are atomic.
+
18. The Perl /a modifier restricts /d numbers to pure ascii, and the
- /aa modifier restricts /i case-insensitive matching to pure ascii,
- ignoring Unicode rules. This separation cannot be represented with
+ /aa modifier restricts /i case-insensitive matching to pure ascii, ig-
+ noring Unicode rules. This separation cannot be represented with
PCRE2_UCP.
19. Perl has different limits than PCRE2. See the pcre2limit documenta-
@@ -4735,8 +4932,8 @@ AUTHOR
REVISION
- Last updated: 28 July 2018
- Copyright (c) 1997-2018 University of Cambridge.
+ Last updated: 13 July 2019
+ Copyright (c) 1997-2019 University of Cambridge.
------------------------------------------------------------------------------
@@ -4808,8 +5005,8 @@ SIMPLE USE OF JIT
There is a limit to the size of pattern that JIT supports, imposed by
the size of machine stack that it uses. The exact rules are not docu-
- mented because they may change at any time, in particular, when new
- optimizations are introduced. If a pattern is too big, a call to
+ mented because they may change at any time, in particular, when new op-
+ timizations are introduced. If a pattern is too big, a call to
pcre2_jit_compile() returns PCRE2_ERROR_NOMEMORY.
PCRE2_JIT_COMPLETE requests the JIT compiler to generate code for com-
@@ -4835,8 +5032,8 @@ SIMPLE USE OF JIT
the entire compiled pattern is freed by calling pcre2_code_free().
In some circumstances you may need to call additional functions. These
- are described in the section entitled "Controlling the JIT stack"
- below.
+ are described in the section entitled "Controlling the JIT stack" be-
+ low.
There are some pcre2_match() options that are not supported by JIT, and
there are also some pattern items that JIT cannot handle. Details are
@@ -4851,39 +5048,65 @@ SIMPLE USE OF JIT
If the JIT compiler finds an unsupported item, no JIT data is gener-
ated. You can find out if JIT matching is available after compiling a
- pattern by calling pcre2_pattern_info() with the PCRE2_INFO_JITSIZE
- option. A non-zero result means that JIT compilation was successful. A
+ pattern by calling pcre2_pattern_info() with the PCRE2_INFO_JITSIZE op-
+ tion. A non-zero result means that JIT compilation was successful. A
result of 0 means that JIT support is not available, or the pattern was
not processed by pcre2_jit_compile(), or the JIT compiler was not able
to handle the pattern.
+MATCHING SUBJECTS CONTAINING INVALID UTF
+
+ When a pattern is compiled with the PCRE2_UTF option, subject strings
+ are normally expected to be a valid sequence of UTF code units. By de-
+ fault, this is checked at the start of matching and an error is gener-
+ ated if invalid UTF is detected. The PCRE2_NO_UTF_CHECK option can be
+ passed to pcre2_match() to skip the check (for improved performance) if
+ you are sure that a subject string is valid. If this option is used
+ with an invalid string, the result is undefined.
+
+ However, a way of running matches on strings that may contain invalid
+ UTF sequences is available. Calling pcre2_compile() with the
+ PCRE2_MATCH_INVALID_UTF option has two effects: it tells the inter-
+ preter in pcre2_match() to support invalid UTF, and, if pcre2_jit_com-
+ pile() is called, the compiled JIT code also supports invalid UTF. De-
+ tails of how this support works, in both the JIT and the interpretive
+ cases, is given in the pcre2unicode documentation.
+
+ There is also an obsolete option for pcre2_jit_compile() called
+ PCRE2_JIT_INVALID_UTF, which currently exists only for backward compat-
+ ibility. It is superseded by the pcre2_compile() option
+ PCRE2_MATCH_INVALID_UTF and should no longer be used. It may be removed
+ in future.
+
+
UNSUPPORTED OPTIONS AND PATTERN ITEMS
The pcre2_match() options that are supported for JIT matching are
- PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART,
- PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, and PCRE2_PARTIAL_SOFT. The
- PCRE2_ANCHORED option is not supported at match time.
+ PCRE2_COPY_MATCHED_SUBJECT, PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY,
+ PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, and
+ PCRE2_PARTIAL_SOFT. The PCRE2_ANCHORED and PCRE2_ENDANCHORED options
+ are not supported at match time.
- If the PCRE2_NO_JIT option is passed to pcre2_match() it disables the
+ If the PCRE2_NO_JIT option is passed to pcre2_match() it disables the
use of JIT, forcing matching by the interpreter code.
- The only unsupported pattern items are \C (match a single data unit)
- when running in a UTF mode, and a callout immediately before an asser-
+ The only unsupported pattern items are \C (match a single data unit)
+ when running in a UTF mode, and a callout immediately before an asser-
tion condition in a conditional group.
RETURN VALUES FROM JIT MATCHING
When a pattern is matched using JIT matching, the return values are the
- same as those given by the interpretive pcre2_match() code, with the
- addition of one new error code: PCRE2_ERROR_JIT_STACKLIMIT. This means
- that the memory used for the JIT stack was insufficient. See "Control-
+ same as those given by the interpretive pcre2_match() code, with the
+ addition of one new error code: PCRE2_ERROR_JIT_STACKLIMIT. This means
+ that the memory used for the JIT stack was insufficient. See "Control-
ling the JIT stack" below for a discussion of JIT stack usage.
- The error code PCRE2_ERROR_MATCHLIMIT is returned by the JIT code if
- searching a very large pattern tree goes on for too long, as it is in
- the same circumstance when JIT is not used, but the details of exactly
+ The error code PCRE2_ERROR_MATCHLIMIT is returned by the JIT code if
+ searching a very large pattern tree goes on for too long, as it is in
+ the same circumstance when JIT is not used, but the details of exactly
what is counted are not the same. The PCRE2_ERROR_DEPTHLIMIT error code
is never returned when JIT matching is used.
@@ -4891,25 +5114,25 @@ RETURN VALUES FROM JIT MATCHING
CONTROLLING THE JIT STACK
When the compiled JIT code runs, it needs a block of memory to use as a
- stack. By default, it uses 32KiB on the machine stack. However, some
- large or complicated patterns need more than this. The error
- PCRE2_ERROR_JIT_STACKLIMIT is given when there is not enough stack.
- Three functions are provided for managing blocks of memory for use as
- JIT stacks. There is further discussion about the use of JIT stacks in
- the section entitled "JIT stack FAQ" below.
-
- The pcre2_jit_stack_create() function creates a JIT stack. Its argu-
- ments are a starting size, a maximum size, and a general context (for
- memory allocation functions, or NULL for standard memory allocation).
+ stack. By default, it uses 32KiB on the machine stack. However, some
+ large or complicated patterns need more than this. The error PCRE2_ER-
+ ROR_JIT_STACKLIMIT is given when there is not enough stack. Three func-
+ tions are provided for managing blocks of memory for use as JIT stacks.
+ There is further discussion about the use of JIT stacks in the section
+ entitled "JIT stack FAQ" below.
+
+ The pcre2_jit_stack_create() function creates a JIT stack. Its argu-
+ ments are a starting size, a maximum size, and a general context (for
+ memory allocation functions, or NULL for standard memory allocation).
It returns a pointer to an opaque structure of type pcre2_jit_stack, or
- NULL if there is an error. The pcre2_jit_stack_free() function is used
+ NULL if there is an error. The pcre2_jit_stack_free() function is used
to free a stack that is no longer needed. If its argument is NULL, this
- function returns immediately, without doing anything. (For the techni-
- cally minded: the address space is allocated by mmap or VirtualAlloc.)
- A maximum stack size of 512KiB to 1MiB should be more than enough for
+ function returns immediately, without doing anything. (For the techni-
+ cally minded: the address space is allocated by mmap or VirtualAlloc.)
+ A maximum stack size of 512KiB to 1MiB should be more than enough for
any pattern.
- The pcre2_jit_stack_assign() function specifies which stack JIT code
+ The pcre2_jit_stack_assign() function specifies which stack JIT code
should use. Its arguments are as follows:
pcre2_match_context *mcontext
@@ -4919,7 +5142,7 @@ CONTROLLING THE JIT STACK
The first argument is a pointer to a match context. When this is subse-
quently passed to a matching function, its information determines which
JIT stack is used. If this argument is NULL, the function returns imme-
- diately, without doing anything. There are three cases for the values
+ diately, without doing anything. There are three cases for the values
of the other two options:
(1) If callback is NULL and data is NULL, an internal 32KiB block
@@ -4937,34 +5160,34 @@ CONTROLLING THE JIT STACK
return value must be a valid JIT stack, the result of calling
pcre2_jit_stack_create().
- A callback function is obeyed whenever JIT code is about to be run; it
+ A callback function is obeyed whenever JIT code is about to be run; it
is not obeyed when pcre2_match() is called with options that are incom-
- patible for JIT matching. A callback function can therefore be used to
- determine whether a match operation was executed by JIT or by the
- interpreter.
+ patible for JIT matching. A callback function can therefore be used to
+ determine whether a match operation was executed by JIT or by the in-
+ terpreter.
You may safely use the same JIT stack for more than one pattern (either
- by assigning directly or by callback), as long as the patterns are
+ by assigning directly or by callback), as long as the patterns are
matched sequentially in the same thread. Currently, the only way to set
- up non-sequential matches in one thread is to use callouts: if a call-
- out function starts another match, that match must use a different JIT
+ up non-sequential matches in one thread is to use callouts: if a call-
+ out function starts another match, that match must use a different JIT
stack to the one used for currently suspended match(es).
- In a multithread application, if you do not specify a JIT stack, or if
- you assign or pass back NULL from a callback, that is thread-safe,
- because each thread has its own machine stack. However, if you assign
- or pass back a non-NULL JIT stack, this must be a different stack for
- each thread so that the application is thread-safe.
-
- Strictly speaking, even more is allowed. You can assign the same non-
- NULL stack to a match context that is used by any number of patterns,
- as long as they are not used for matching by multiple threads at the
- same time. For example, you could use the same stack in all compiled
- patterns, with a global mutex in the callback to wait until the stack
+ In a multithread application, if you do not specify a JIT stack, or if
+ you assign or pass back NULL from a callback, that is thread-safe, be-
+ cause each thread has its own machine stack. However, if you assign or
+ pass back a non-NULL JIT stack, this must be a different stack for each
+ thread so that the application is thread-safe.
+
+ Strictly speaking, even more is allowed. You can assign the same non-
+ NULL stack to a match context that is used by any number of patterns,
+ as long as they are not used for matching by multiple threads at the
+ same time. For example, you could use the same stack in all compiled
+ patterns, with a global mutex in the callback to wait until the stack
is available for use. However, this is an inefficient solution, and not
recommended.
- This is a suggestion for how a multithreaded program that needs to set
+ This is a suggestion for how a multithreaded program that needs to set
up non-default JIT stacks might operate:
During thread initalization
@@ -4976,7 +5199,7 @@ CONTROLLING THE JIT STACK
Use a one-line callback function
return thread_local_var
- All the functions described in this section do nothing if JIT is not
+ All the functions described in this section do nothing if JIT is not
available.
@@ -4985,20 +5208,20 @@ JIT STACK FAQ
(1) Why do we need JIT stacks?
PCRE2 (and JIT) is a recursive, depth-first engine, so it needs a stack
- where the local data of the current node is pushed before checking its
+ where the local data of the current node is pushed before checking its
child nodes. Allocating real machine stack on some platforms is diffi-
cult. For example, the stack chain needs to be updated every time if we
- extend the stack on PowerPC. Although it is possible, its updating
+ extend the stack on PowerPC. Although it is possible, its updating
time overhead decreases performance. So we do the recursion in memory.
(2) Why don't we simply allocate blocks of memory with malloc()?
- Modern operating systems have a nice feature: they can reserve an
- address space instead of allocating memory. We can safely allocate mem-
- ory pages inside this address space, so the stack could grow without
- moving memory data (this is important because of pointers). Thus we can
- allocate 1MiB address space, and use only a single memory page (usually
- 4KiB) if that is enough. However, we can still grow up to 1MiB anytime
+ Modern operating systems have a nice feature: they can reserve an ad-
+ dress space instead of allocating memory. We can safely allocate memory
+ pages inside this address space, so the stack could grow without moving
+ memory data (this is important because of pointers). Thus we can allo-
+ cate 1MiB address space, and use only a single memory page (usually
+ 4KiB) if that is enough. However, we can still grow up to 1MiB anytime
if needed.
(3) Who "owns" a JIT stack?
@@ -5006,8 +5229,8 @@ JIT STACK FAQ
The owner of the stack is the user program, not the JIT studied pattern
or anything else. The user program must ensure that if a stack is being
used by pcre2_match(), (that is, it is assigned to a match context that
- is passed to the pattern currently running), that stack must not be
- used by any other threads (to avoid overwriting the same memory area).
+ is passed to the pattern currently running), that stack must not be
+ used by any other threads (to avoid overwriting the same memory area).
The best practice for multithreaded programs is to allocate a stack for
each thread, and return this stack through the JIT callback function.
@@ -5015,36 +5238,36 @@ JIT STACK FAQ
You can free a JIT stack at any time, as long as it will not be used by
pcre2_match() again. When you assign the stack to a match context, only
- a pointer is set. There is no reference counting or any other magic.
+ a pointer is set. There is no reference counting or any other magic.
You can free compiled patterns, contexts, and stacks in any order, any-
- time. Just do not call pcre2_match() with a match context pointing to
+ time. Just do not call pcre2_match() with a match context pointing to
an already freed stack, as that will cause SEGFAULT. (Also, do not free
- a stack currently used by pcre2_match() in another thread). You can
- also replace the stack in a context at any time when it is not in use.
+ a stack currently used by pcre2_match() in another thread). You can
+ also replace the stack in a context at any time when it is not in use.
You should free the previous stack before assigning a replacement.
- (5) Should I allocate/free a stack every time before/after calling
+ (5) Should I allocate/free a stack every time before/after calling
pcre2_match()?
- No, because this is too costly in terms of resources. However, you
- could implement some clever idea which release the stack if it is not
- used in let's say two minutes. The JIT callback can help to achieve
+ No, because this is too costly in terms of resources. However, you
+ could implement some clever idea which release the stack if it is not
+ used in let's say two minutes. The JIT callback can help to achieve
this without keeping a list of patterns.
- (6) OK, the stack is for long term memory allocation. But what happens
- if a pattern causes stack overflow with a stack of 1MiB? Is that 1MiB
+ (6) OK, the stack is for long term memory allocation. But what happens
+ if a pattern causes stack overflow with a stack of 1MiB? Is that 1MiB
kept until the stack is freed?
- Especially on embedded sytems, it might be a good idea to release mem-
- ory sometimes without freeing the stack. There is no API for this at
- the moment. Probably a function call which returns with the currently
- allocated memory for any stack and another which allows releasing mem-
+ Especially on embedded sytems, it might be a good idea to release mem-
+ ory sometimes without freeing the stack. There is no API for this at
+ the moment. Probably a function call which returns with the currently
+ allocated memory for any stack and another which allows releasing mem-
ory (shrinking the stack) would be a good idea if someone needs this.
(7) This is too much of a headache. Isn't there any better solution for
JIT stack handling?
- No, thanks to Windows. If POSIX threads were used everywhere, we could
+ No, thanks to Windows. If POSIX threads were used everywhere, we could
throw out this complicated API.
@@ -5053,18 +5276,18 @@ FREEING JIT SPECULATIVE MEMORY
void pcre2_jit_free_unused_memory(pcre2_general_context *gcontext);
The JIT executable allocator does not free all memory when it is possi-
- ble. It expects new allocations, and keeps some free memory around to
- improve allocation speed. However, in low memory conditions, it might
- be better to free all possible memory. You can cause this to happen by
- calling pcre2_jit_free_unused_memory(). Its argument is a general con-
+ ble. It expects new allocations, and keeps some free memory around to
+ improve allocation speed. However, in low memory conditions, it might
+ be better to free all possible memory. You can cause this to happen by
+ calling pcre2_jit_free_unused_memory(). Its argument is a general con-
text, for custom memory management, or NULL for standard memory manage-
ment.
EXAMPLE CODE
- This is a single-threaded example that specifies a JIT stack without
- using a callback. A real program should include error checking after
+ This is a single-threaded example that specifies a JIT stack without
+ using a callback. A real program should include error checking after
all the function calls.
int rc;
@@ -5092,29 +5315,31 @@ EXAMPLE CODE
JIT FAST PATH API
Because the API described above falls back to interpreted matching when
- JIT is not available, it is convenient for programs that are written
+ JIT is not available, it is convenient for programs that are written
for general use in many environments. However, calling JIT via
pcre2_match() does have a performance impact. Programs that are written
- for use where JIT is known to be available, and which need the best
- possible performance, can instead use a "fast path" API to call JIT
- matching directly instead of calling pcre2_match() (obviously only for
+ for use where JIT is known to be available, and which need the best
+ possible performance, can instead use a "fast path" API to call JIT
+ matching directly instead of calling pcre2_match() (obviously only for
patterns that have been successfully processed by pcre2_jit_compile()).
- The fast path function is called pcre2_jit_match(), and it takes
- exactly the same arguments as pcre2_match(). The return values are also
- the same, plus PCRE2_ERROR_JIT_BADOPTION if a matching mode (partial or
- complete) is requested that was not compiled. Unsupported option bits
- (for example, PCRE2_ANCHORED) are ignored, as is the PCRE2_NO_JIT
- option.
+ The fast path function is called pcre2_jit_match(), and it takes ex-
+ actly the same arguments as pcre2_match(). However, the subject string
+ must be specified with a length; PCRE2_ZERO_TERMINATED is not sup-
+ ported. Unsupported option bits (for example, PCRE2_ANCHORED, PCRE2_EN-
+ DANCHORED and PCRE2_COPY_MATCHED_SUBJECT) are ignored, as is the
+ PCRE2_NO_JIT option. The return values are also the same as for
+ pcre2_match(), plus PCRE2_ERROR_JIT_BADOPTION if a matching mode (par-
+ tial or complete) is requested that was not compiled.
- When you call pcre2_match(), as well as testing for invalid options, a
+ When you call pcre2_match(), as well as testing for invalid options, a
number of other sanity checks are performed on the arguments. For exam-
ple, if the subject pointer is NULL, an immediate error is given. Also,
- unless PCRE2_NO_UTF_CHECK is set, a UTF subject string is tested for
- validity. In the interests of speed, these checks do not happen on the
+ unless PCRE2_NO_UTF_CHECK is set, a UTF subject string is tested for
+ validity. In the interests of speed, these checks do not happen on the
JIT fast path, and if invalid data is passed, the result is undefined.
- Bypassing the sanity checks and the pcre2_match() wrapping can give
+ Bypassing the sanity checks and the pcre2_match() wrapping can give
speedups of more than 10%.
@@ -5132,8 +5357,8 @@ AUTHOR
REVISION
- Last updated: 28 June 2018
- Copyright (c) 1997-2018 University of Cambridge.
+ Last updated: 23 May 2019
+ Copyright (c) 1997-2019 University of Cambridge.
------------------------------------------------------------------------------
@@ -5151,46 +5376,45 @@ SIZE AND OTHER LIMITATIONS
The maximum size of a compiled pattern is approximately 64 thousand
code units for the 8-bit and 16-bit libraries if PCRE2 is compiled with
- the default internal linkage size, which is 2 bytes for these
- libraries. If you want to process regular expressions that are truly
+ the default internal linkage size, which is 2 bytes for these li-
+ braries. If you want to process regular expressions that are truly
enormous, you can compile PCRE2 with an internal linkage size of 3 or 4
(when building the 16-bit library, 3 is rounded up to 4). See the
README file in the source distribution and the pcre2build documentation
for details. In these cases the limit is substantially larger. How-
- ever, the speed of execution is slower. In the 32-bit library, the
- internal linkage size is always 4.
+ ever, the speed of execution is slower. In the 32-bit library, the in-
+ ternal linkage size is always 4.
The maximum length of a source pattern string is essentially unlimited;
it is the largest number a PCRE2_SIZE variable can hold. However, the
program that calls pcre2_compile() can specify a smaller limit.
The maximum length (in code units) of a subject string is one less than
- the largest number a PCRE2_SIZE variable can hold. PCRE2_SIZE is an
- unsigned integer type, usually defined as size_t. Its maximum value
- (that is ~(PCRE2_SIZE)0) is reserved as a special indicator for zero-
- terminated strings and unset offsets.
+ the largest number a PCRE2_SIZE variable can hold. PCRE2_SIZE is an un-
+ signed integer type, usually defined as size_t. Its maximum value (that
+ is ~(PCRE2_SIZE)0) is reserved as a special indicator for zero-termi-
+ nated strings and unset offsets.
All values in repeating quantifiers must be less than 65536.
The maximum length of a lookbehind assertion is 65535 characters.
- There is no limit to the number of parenthesized subpatterns, but there
- can be no more than 65535 capturing subpatterns. There is, however, a
- limit to the depth of nesting of parenthesized subpatterns of all
- kinds. This is imposed in order to limit the amount of system stack
- used at compile time. The default limit can be specified when PCRE2 is
- built; if not, the default is set to 250. An application can change
- this limit by calling pcre2_set_parens_nest_limit() to set the limit in
- a compile context.
+ There is no limit to the number of parenthesized groups, but there can
+ be no more than 65535 capture groups, and there is a limit to the depth
+ of nesting of parenthesized subpatterns of all kinds. This is imposed
+ in order to limit the amount of system stack used at compile time. The
+ default limit can be specified when PCRE2 is built; if not, the default
+ is set to 250. An application can change this limit by calling
+ pcre2_set_parens_nest_limit() to set the limit in a compile context.
- The maximum length of name for a named subpattern is 32 code units, and
- the maximum number of named subpatterns is 10000.
+ The maximum length of name for a named capture group is 32 code units,
+ and the maximum number of such groups is 10000.
- The maximum length of a name in a (*MARK), (*PRUNE), (*SKIP), or
- (*THEN) verb is 255 code units for the 8-bit library and 65535 code
+ The maximum length of a name in a (*MARK), (*PRUNE), (*SKIP), or
+ (*THEN) verb is 255 code units for the 8-bit library and 65535 code
units for the 16-bit and 32-bit libraries.
- The maximum length of a string argument to a callout is the largest
+ The maximum length of a string argument to a callout is the largest
number a 32-bit unsigned integer can hold.
@@ -5203,8 +5427,8 @@ AUTHOR
REVISION
- Last updated: 30 March 2017
- Copyright (c) 1997-2017 University of Cambridge.
+ Last updated: 02 February 2019
+ Copyright (c) 1997-2019 University of Cambridge.
------------------------------------------------------------------------------
@@ -5227,8 +5451,8 @@ PCRE2 MATCHING ALGORITHMS
An alternative algorithm is provided by the pcre2_dfa_match() function;
it operates in a different way, and is not Perl-compatible. This alter-
- native has advantages and disadvantages compared with the standard
- algorithm, and these are described below.
+ native has advantages and disadvantages compared with the standard al-
+ gorithm, and these are described below.
When there is only one possible way in which a given subject string can
match a pattern, the two algorithms give the same answer. A difference
@@ -5296,8 +5520,8 @@ THE ALTERNATIVE MATCHING ALGORITHM
Although the general principle of this matching algorithm is that it
scans the subject string only once, without backtracking, there is one
exception: when a lookaround assertion is encountered, the characters
- following or preceding the current point have to be independently
- inspected.
+ following or preceding the current point have to be independently in-
+ spected.
The scan continues until either the end of the subject is reached, or
there are no more unterminated paths. At this point, terminated paths
@@ -5328,12 +5552,12 @@ THE ALTERNATIVE MATCHING ALGORITHM
SESS option when compiling.
There are a number of features of PCRE2 regular expressions that are
- not supported by the alternative matching algorithm. They are as fol-
- lows:
+ not supported or behave differently in the alternative matching func-
+ tion. Those that are not supported cause an error if encountered.
- 1. Because the algorithm finds all possible matches, the greedy or
- ungreedy nature of repetition quantifiers is not relevant (though it
- may affect auto-possessification, as just described). During matching,
+ 1. Because the algorithm finds all possible matches, the greedy or un-
+ greedy nature of repetition quantifiers is not relevant (though it may
+ affect auto-possessification, as just described). During matching,
greedy and ungreedy quantifiers are treated in exactly the same way.
However, possessive quantifiers can make a difference when what follows
could also match what is quantified, for example in a pattern like
@@ -5354,30 +5578,34 @@ THE ALTERNATIVE MATCHING ALGORITHM
strings are available.
3. Because no substrings are captured, backreferences within the pat-
- tern are not supported, and cause errors if encountered.
+ tern are not supported.
4. For the same reason, conditional expressions that use a backrefer-
ence as the condition or test for a specific group recursion are not
supported.
- 5. Because many paths through the tree may be active, the \K escape
- sequence, which resets the start of the match when encountered (but may
- be on some paths and not on others), is not supported. It causes an
- error if encountered.
+ 5. Again for the same reason, script runs are not supported.
+
+ 6. Because many paths through the tree may be active, the \K escape se-
+ quence, which resets the start of the match when encountered (but may
+ be on some paths and not on others), is not supported.
- 6. Callouts are supported, but the value of the capture_top field is
+ 7. Callouts are supported, but the value of the capture_top field is
always 1, and the value of the capture_last field is always 0.
- 7. The \C escape sequence, which (in the standard algorithm) always
- matches a single code unit, even in a UTF mode, is not supported in
- these modes, because the alternative algorithm moves through the sub-
- ject string one character (not code unit) at a time, for all active
+ 8. The \C escape sequence, which (in the standard algorithm) always
+ matches a single code unit, even in a UTF mode, is not supported in
+ these modes, because the alternative algorithm moves through the sub-
+ ject string one character (not code unit) at a time, for all active
paths through the tree.
- 8. Except for (*FAIL), the backtracking control verbs such as (*PRUNE)
- are not supported. (*FAIL) is supported, and behaves like a failing
+ 9. Except for (*FAIL), the backtracking control verbs such as (*PRUNE)
+ are not supported. (*FAIL) is supported, and behaves like a failing
negative assertion.
+ 10. The PCRE2_MATCH_INVALID_UTF option for pcre2_compile() is not sup-
+ ported by pcre2_dfa_match().
+
ADVANTAGES OF THE ALTERNATIVE ALGORITHM
@@ -5407,7 +5635,8 @@ DISADVANTAGES OF THE ALTERNATIVE ALGORITHM
partly because it has to search for all possible matches, but is also
because it is less susceptible to optimization.
- 2. Capturing parentheses and backreferences are not supported.
+ 2. Capturing parentheses, backreferences, script runs, and matching
+ within invalid UTF string are not supported.
3. Although atomic groups are supported, their use does not provide the
performance advantage that it does for the standard algorithm.
@@ -5422,8 +5651,8 @@ AUTHOR
REVISION
- Last updated: 29 September 2014
- Copyright (c) 1997-2014 University of Cambridge.
+ Last updated: 23 May 2019
+ Copyright (c) 1997-2019 University of Cambridge.
------------------------------------------------------------------------------
@@ -5436,66 +5665,109 @@ NAME
PARTIAL MATCHING IN PCRE2
- In normal use of PCRE2, if the subject string that is passed to a
- matching function matches as far as it goes, but is too short to match
- the entire pattern, PCRE2_ERROR_NOMATCH is returned. There are circum-
- stances where it might be helpful to distinguish this case from other
- cases in which there is no match.
-
- Consider, for example, an application where a human is required to type
- in data for a field with specific formatting requirements. An example
- might be a date in the form ddmmmyy, defined by this pattern:
-
- ^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$
-
- If the application sees the user's keystrokes one by one, and can check
- that what has been typed so far is potentially valid, it is able to
- raise an error as soon as a mistake is made, by beeping and not
- reflecting the character that has been typed, for example. This immedi-
- ate feedback is likely to be a better user interface than a check that
- is delayed until the entire string has been entered. Partial matching
- can also be useful when the subject string is very long and is not all
- available at once.
-
- PCRE2 supports partial matching by means of the PCRE2_PARTIAL_SOFT and
- PCRE2_PARTIAL_HARD options, which can be set when calling a matching
- function. The difference between the two options is whether or not a
- partial match is preferred to an alternative complete match, though the
- details differ between the two types of matching function. If both
- options are set, PCRE2_PARTIAL_HARD takes precedence.
-
- If you want to use partial matching with just-in-time optimized code,
- you must call pcre2_jit_compile() with one or both of these options:
+ In normal use of PCRE2, if there is a match up to the end of a subject
+ string, but more characters are needed to match the entire pattern,
+ PCRE2_ERROR_NOMATCH is returned, just like any other failing match.
+ There are circumstances where it might be helpful to distinguish this
+ "partial match" case.
+
+ One example is an application where the subject string is very long,
+ and not all available at once. The requirement here is to be able to do
+ the matching segment by segment, but special action is needed when a
+ matched substring spans the boundary between two segments.
+
+ Another example is checking a user input string as it is typed, to en-
+ sure that it conforms to a required format. Invalid characters can be
+ immediately diagnosed and rejected, giving instant feedback.
+
+ Partial matching is a PCRE2-specific feature; it is not Perl-compati-
+ ble. It is requested by setting one of the PCRE2_PARTIAL_HARD or
+ PCRE2_PARTIAL_SOFT options when calling a matching function. The dif-
+ ference between the two options is whether or not a partial match is
+ preferred to an alternative complete match, though the details differ
+ between the two types of matching function. If both options are set,
+ PCRE2_PARTIAL_HARD takes precedence.
+
+ If you want to use partial matching with just-in-time optimized code,
+ as well as setting a partial match option for the matching function,
+ you must also call pcre2_jit_compile() with one or both of these op-
+ tions:
- PCRE2_JIT_PARTIAL_SOFT
PCRE2_JIT_PARTIAL_HARD
+ PCRE2_JIT_PARTIAL_SOFT
+
+ PCRE2_JIT_COMPLETE should also be set if you are going to run non-par-
+ tial matches on the same pattern. Separate code is compiled for each
+ mode. If the appropriate JIT mode has not been compiled, interpretive
+ matching code is used.
+
+ Setting a partial matching option disables two of PCRE2's standard op-
+ timization hints. PCRE2 remembers the last literal code unit in a pat-
+ tern, and abandons matching immediately if it is not present in the
+ subject string. This optimization cannot be used for a subject string
+ that might match only partially. PCRE2 also remembers a minimum length
+ of a matching string, and does not bother to run the matching function
+ on shorter strings. This optimization is also disabled for partial
+ matching.
+
+
+REQUIREMENTS FOR A PARTIAL MATCH
+
+ A possible partial match occurs during matching when the end of the
+ subject string is reached successfully, but either more characters are
+ needed to complete the match, or the addition of more characters might
+ change what is matched.
+
+ Example 1: if the pattern is /abc/ and the subject is "ab", more char-
+ acters are definitely needed to complete a match. In this case both
+ hard and soft matching options yield a partial match.
+
+ Example 2: if the pattern is /ab+/ and the subject is "ab", a complete
+ match can be found, but the addition of more characters might change
+ what is matched. In this case, only PCRE2_PARTIAL_HARD returns a par-
+ tial match; PCRE2_PARTIAL_SOFT returns the complete match.
+
+ On reaching the end of the subject, when PCRE2_PARTIAL_HARD is set, if
+ the next pattern item is \z, \Z, \b, \B, or $ there is always a partial
+ match. Otherwise, for both options, the next pattern item must be one
+ that inspects a character, and at least one of the following must be
+ true:
+
+ (1) At least one character has already been inspected. An inspected
+ character need not form part of the final matched string; lookbehind
+ assertions and the \K escape sequence provide ways of inspecting char-
+ acters before the start of a matched string.
- PCRE2_JIT_COMPLETE should also be set if you are going to run non-par-
- tial matches on the same pattern. If the appropriate JIT mode has not
- been compiled, interpretive matching code is used.
+ (2) The pattern contains one or more lookbehind assertions. This condi-
+ tion exists in case there is a lookbehind that inspects characters be-
+ fore the start of the match.
- Setting a partial matching option disables two of PCRE2's standard
- optimizations. PCRE2 remembers the last literal code unit in a pattern,
- and abandons matching immediately if it is not present in the subject
- string. This optimization cannot be used for a subject string that
- might match only partially. PCRE2 also knows the minimum length of a
- matching string, and does not bother to run the matching function on
- shorter strings. This optimization is also disabled for partial match-
- ing.
+ (3) There is a special case when the whole pattern can match an empty
+ string. When the starting point is at the end of the subject, the
+ empty string match is a possibility, and if PCRE2_PARTIAL_SOFT is set
+ and neither of the above conditions is true, it is returned. However,
+ because adding more characters might result in a non-empty match,
+ PCRE2_PARTIAL_HARD returns a partial match, which in this case means
+ "there is going to be a match at this point, but until some more char-
+ acters are added, we do not know if it will be an empty string or some-
+ thing longer".
PARTIAL MATCHING USING pcre2_match()
- A partial match occurs during a call to pcre2_match() when the end of
- the subject string is reached successfully, but matching cannot con-
- tinue because more characters are needed. However, at least one charac-
- ter in the subject must have been inspected. This character need not
- form part of the final matched string; lookbehind assertions and the \K
- escape sequence provide ways of inspecting characters before the start
- of a matched string. The requirement for inspecting at least one char-
- acter exists because an empty string can always be matched; without
- such a restriction there would always be a partial match of an empty
- string at the end of the subject.
+ When a partial matching option is set, the result of calling
+ pcre2_match() can be one of the following:
+
+ A successful match
+ A complete match has been found, starting and ending within this sub-
+ ject.
+
+ PCRE2_ERROR_NOMATCH
+ No match can start anywhere in this subject.
+
+ PCRE2_ERROR_PARTIAL
+ Adding more characters may result in a complete match that uses one
+ or more characters from the end of this subject.
When a partial match is returned, the first two elements in the ovector
point to the portion of the subject that was matched, but the values in
@@ -5505,29 +5777,12 @@ PARTIAL MATCHING USING pcre2_match()
/abc\K123/
If it is matched against "456abc123xyz" the result is a complete match,
- and the ovector defines the matched string as "123", because \K resets
- the "start of match" point. However, if a partial match is requested
- and the subject string is "456abc12", a partial match is found for the
- string "abc12", because all these characters are needed for a subse-
+ and the ovector defines the matched string as "123", because \K resets
+ the "start of match" point. However, if a partial match is requested
+ and the subject string is "456abc12", a partial match is found for the
+ string "abc12", because all these characters are needed for a subse-
quent re-match with additional characters.
- What happens when a partial match is identified depends on which of the
- two partial matching options are set.
-
- PCRE2_PARTIAL_SOFT WITH pcre2_match()
-
- If PCRE2_PARTIAL_SOFT is set when pcre2_match() identifies a partial
- match, the partial match is remembered, but matching continues as nor-
- mal, and other alternatives in the pattern are tried. If no complete
- match can be found, PCRE2_ERROR_PARTIAL is returned instead of
- PCRE2_ERROR_NOMATCH.
-
- This option is "soft" because it prefers a complete match over a par-
- tial match. All the various matching items in a pattern behave as if
- the subject string is potentially complete. For example, \z, \Z, and $
- match at the end of the subject, as normal, and for \b and \B the end
- of the subject is treated as a non-alphanumeric.
-
If there is more than one partial match, the first one that was found
provides the data that is returned. Consider this pattern:
@@ -5536,23 +5791,31 @@ PARTIAL MATCHING USING pcre2_match()
If this is matched against the subject string "abc123dog", both alter-
natives fail to match, but the end of the subject is reached during
matching, so PCRE2_ERROR_PARTIAL is returned. The offsets are set to 3
- and 9, identifying "123dog" as the first partial match that was found.
- (In this example, there are two partial matches, because "dog" on its
- own partially matches the second alternative.)
-
- PCRE2_PARTIAL_HARD WITH pcre2_match()
+ and 9, identifying "123dog" as the first partial match. (In this exam-
+ ple, there are two partial matches, because "dog" on its own partially
+ matches the second alternative.)
- If PCRE2_PARTIAL_HARD is set for pcre2_match(), PCRE2_ERROR_PARTIAL is
- returned as soon as a partial match is found, without continuing to
- search for possible complete matches. This option is "hard" because it
- prefers an earlier partial match over a later complete match. For this
- reason, the assumption is made that the end of the supplied subject
- string may not be the true end of the available data, and so, if \z,
- \Z, \b, \B, or $ are encountered at the end of the subject, the result
- is PCRE2_ERROR_PARTIAL, provided that at least one character in the
- subject has been inspected.
+ How a partial match is processed by pcre2_match()
- Comparing hard and soft partial matching
+ What happens when a partial match is identified depends on which of the
+ two partial matching options is set.
+
+ If PCRE2_PARTIAL_HARD is set, PCRE2_ERROR_PARTIAL is returned as soon
+ as a partial match is found, without continuing to search for possible
+ complete matches. This option is "hard" because it prefers an earlier
+ partial match over a later complete match. For this reason, the assump-
+ tion is made that the end of the supplied subject string is not the
+ true end of the available data, which is why \z, \Z, \b, \B, and $ al-
+ ways give a partial match.
+
+ If PCRE2_PARTIAL_SOFT is set, the partial match is remembered, but
+ matching continues as normal, and other alternatives in the pattern are
+ tried. If no complete match can be found, PCRE2_ERROR_PARTIAL is re-
+ turned instead of PCRE2_ERROR_NOMATCH. This option is "soft" because it
+ prefers a complete match over a partial match. All the various matching
+ items in a pattern behave as if the subject string is potentially com-
+ plete; \z, \Z, and $ match at the end of the subject, as normal, and
+ for \b and \B the end of the subject is treated as a non-alphanumeric.
The difference between the two partial matching options can be illus-
trated by a pattern such as:
@@ -5579,89 +5842,150 @@ PARTIAL MATCHING USING pcre2_match()
The second pattern will never match "dogsbody", because it will always
find the shorter match first.
+ Example of partial matching using pcre2test
-PARTIAL MATCHING USING pcre2_dfa_match()
+ The pcre2test data modifiers partial_hard (or ph) and partial_soft (or
+ ps) set PCRE2_PARTIAL_HARD and PCRE2_PARTIAL_SOFT, respectively, when
+ calling pcre2_match(). Here is a run of pcre2test using a pattern that
+ matches the whole subject in the form of a date:
- The DFA functions move along the subject string character by character,
- without backtracking, searching for all possible matches simultane-
- ously. If the end of the subject is reached before the end of the pat-
- tern, there is the possibility of a partial match, again provided that
- at least one character has been inspected.
+ re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
+ data> 25dec3\=ph
+ Partial match: 23dec3
+ data> 3ju\=ph
+ Partial match: 3ju
+ data> 3juj\=ph
+ No match
- When PCRE2_PARTIAL_SOFT is set, PCRE2_ERROR_PARTIAL is returned only if
- there have been no complete matches. Otherwise, the complete matches
- are returned. However, if PCRE2_PARTIAL_HARD is set, a partial match
- takes precedence over any complete matches. The portion of the string
- that was matched when the longest partial match was found is set as the
- first matching string.
+ This example gives the same results for both hard and soft partial
+ matching options. Here is an example where there is a difference:
- Because the DFA functions always search for all possible matches, and
- there is no difference between greedy and ungreedy repetition, their
- behaviour is different from the standard functions when PCRE2_PAR-
- TIAL_HARD is set. Consider the string "dog" matched against the
- ungreedy pattern shown above:
+ re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
+ data> 25jun04\=ps
+ 0: 25jun04
+ 1: jun
+ data> 25jun04\=ph
+ Partial match: 25jun04
- /dog(sbody)??/
+ With PCRE2_PARTIAL_SOFT, the subject is matched completely. For
+ PCRE2_PARTIAL_HARD, however, the subject is assumed not to be complete,
+ so there is only a partial match.
- Whereas the standard function stops as soon as it finds the complete
- match for "dog", the DFA function also finds the partial match for
- "dogsbody", and so returns that when PCRE2_PARTIAL_HARD is set.
+MULTI-SEGMENT MATCHING WITH pcre2_match()
-PARTIAL MATCHING AND WORD BOUNDARIES
+ PCRE was not originally designed with multi-segment matching in mind.
+ However, over time, features (including partial matching) that make
+ multi-segment matching possible have been added. A very long string can
+ be searched segment by segment by calling pcre2_match() repeatedly,
+ with the aim of achieving the same results that would happen if the en-
+ tire string was available for searching all the time. Normally, the
+ strings that are being sought are much shorter than each individual
+ segment, and are in the middle of very long strings, so the pattern is
+ normally not anchored.
+
+ Special logic must be implemented to handle a matched substring that
+ spans a segment boundary. PCRE2_PARTIAL_HARD should be used, because it
+ returns a partial match at the end of a segment whenever there is the
+ possibility of changing the match by adding more characters. The
+ PCRE2_NOTBOL option should also be set for all but the first segment.
+
+ When a partial match occurs, the next segment must be added to the cur-
+ rent subject and the match re-run, using the startoffset argument of
+ pcre2_match() to begin at the point where the partial match started.
+ For example:
- If a pattern ends with one of sequences \b or \B, which test for word
- boundaries, partial matching with PCRE2_PARTIAL_SOFT can give counter-
- intuitive results. Consider this pattern:
+ re> /\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d/
+ data> ...the date is 23ja\=ph
+ Partial match: 23ja
+ data> ...the date is 23jan19 and on that day...\=offset=15
+ 0: 23jan19
+ 1: jan
+
+ Note the use of the offset modifier to start the new match where the
+ partial match was found. In this example, the next segment was added to
+ the one in which the partial match was found. This is the most
+ straightforward approach, typically using a memory buffer that is twice
+ the size of each segment. After a partial match, the first half of the
+ buffer is discarded, the second half is moved to the start of the buf-
+ fer, and a new segment is added before repeating the match as in the
+ example above. After a no match, the entire buffer can be discarded.
+
+ If there are memory constraints, you may want to discard text that pre-
+ cedes a partial match before adding the next segment. Unfortunately,
+ this is not at present straightforward. In cases such as the above,
+ where the pattern does not contain any lookbehinds, it is sufficient to
+ retain only the partially matched substring. However, if the pattern
+ contains a lookbehind assertion, characters that precede the start of
+ the partial match may have been inspected during the matching process.
+ When pcre2test displays a partial match, it indicates these characters
+ with '<' if the allusedtext modifier is set:
- /\bcat\b/
+ re> "(?<=123)abc"
+ data> xx123ab\=ph,allusedtext
+ Partial match: 123ab
+ <<<
- This matches "cat", provided there is a word boundary at either end. If
- the subject string is "the cat", the comparison of the final "t" with a
- following character cannot take place, so a partial match is found.
- However, normal matching carries on, and \b matches at the end of the
- subject when the last character is a letter, so a complete match is
- found. The result, therefore, is not PCRE2_ERROR_PARTIAL. Using
- PCRE2_PARTIAL_HARD in this case does yield PCRE2_ERROR_PARTIAL, because
- then the partial match takes precedence.
+ However, the allusedtext modifier is not available for JIT matching,
+ because JIT matching does not record the first (or last) consulted
+ characters. For this reason, this information is not available via the
+ API. It is therefore not possible in general to obtain the exact number
+ of characters that must be retained in order to get the right match re-
+ sult. If you cannot retain the entire segment, you must find some
+ heuristic way of choosing.
+
+ If you know the approximate length of the matching substrings, you can
+ use that to decide how much text to retain. The only lookbehind infor-
+ mation that is currently available via the API is the length of the
+ longest individual lookbehind in a pattern, but this can be misleading
+ if there are nested lookbehinds. The value returned by calling
+ pcre2_pattern_info() with the PCRE2_INFO_MAXLOOKBEHIND option is the
+ maximum number of characters (not code units) that any individual look-
+ behind moves back when it is processed. A pattern such as
+ "(?<=(? /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
- data> 25jun04\=ps
- 0: 25jun04
- 1: jun
- data> 25dec3\=ps
- Partial match: 23dec3
- data> 3ju\=ps
- Partial match: 3ju
- data> 3juj\=ps
- No match
- data> j\=ps
- No match
+ When PCRE2_PARTIAL_SOFT is set, PCRE2_ERROR_PARTIAL is returned only if
+ there have been no complete matches. Otherwise, the complete matches
+ are returned. If PCRE2_PARTIAL_HARD is set, a partial match takes
+ precedence over any complete matches. The portion of the string that
+ was matched when the longest partial match was found is set as the
+ first matching string.
- The first data string is matched completely, so pcre2test shows the
- matched substrings. The remaining four strings do not match the com-
- plete pattern, but the first two are partial matches. Similar output is
- obtained if DFA matching is used.
+ Because the DFA function always searches for all possible matches, and
+ there is no difference between greedy and ungreedy repetition, its be-
+ haviour is different from the pcre2_match(). Consider the string "dog"
+ matched against this ungreedy pattern:
- If the partial_hard (or ph) modifier is present on a pcre2test data
- line, the PCRE2_PARTIAL_HARD option is set for the match.
+ /dog(sbody)??/
+
+ Whereas the standard function stops as soon as it finds the complete
+ match for "dog", the DFA function also finds the partial match for
+ "dogsbody", and so returns that when PCRE2_PARTIAL_HARD is set.
MULTI-SEGMENT MATCHING WITH pcre2_dfa_match()
- When a partial match has been found using a DFA matching function, it
+ When a partial match has been found using the DFA matching function, it
is possible to continue the match by providing additional subject data
and calling the function again with the same compiled regular expres-
sion, this time setting the PCRE2_DFA_RESTART option. You must pass the
same working space as before, because this is where details of the pre-
- vious partial match are stored. Here is an example using pcre2test:
+ vious partial match are stored. You can set the PCRE2_PARTIAL_SOFT or
+ PCRE2_PARTIAL_HARD options with PCRE2_DFA_RESTART to continue partial
+ matching over multiple segments. Here is an example using pcre2test:
re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
data> 23ja\=dfa,ps
@@ -5674,152 +5998,10 @@ MULTI-SEGMENT MATCHING WITH pcre2_dfa_match()
(restarted) match. Notice that when the match is complete, only the
last part is shown; PCRE2 does not retain the previously partially-
matched string. It is up to the calling program to do that if it needs
- to.
-
- That means that, for an unanchored pattern, if a continued match fails,
- it is not possible to try again at a new starting point. All this
- facility is capable of doing is continuing with the previous match
- attempt. In the previous example, if the second set of data is "ug23"
- the result is no match, even though there would be a match for "aug23"
- if the entire string were given at once. Depending on the application,
- this may or may not be what you want. The only way to allow for start-
- ing again at the next character is to retain the matched part of the
- subject and try a new complete match.
-
- You can set the PCRE2_PARTIAL_SOFT or PCRE2_PARTIAL_HARD options with
- PCRE2_DFA_RESTART to continue partial matching over multiple segments.
- This facility can be used to pass very long subject strings to the DFA
- matching functions.
-
-
-MULTI-SEGMENT MATCHING WITH pcre2_match()
-
- Unlike the DFA function, it is not possible to restart the previous
- match with a new segment of data when using pcre2_match(). Instead, new
- data must be added to the previous subject string, and the entire match
- re-run, starting from the point where the partial match occurred. Ear-
- lier data can be discarded.
-
- It is best to use PCRE2_PARTIAL_HARD in this situation, because it does
- not treat the end of a segment as the end of the subject when matching
- \z, \Z, \b, \B, and $. Consider an unanchored pattern that matches
- dates:
-
- re> /\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d/
- data> The date is 23ja\=ph
- Partial match: 23ja
-
- At this stage, an application could discard the text preceding "23ja",
- add on text from the next segment, and call the matching function
- again. Unlike the DFA matching function, the entire matching string
- must always be available, and the complete matching process occurs for
- each call, so more memory and more processing time is needed.
-
-
-ISSUES WITH MULTI-SEGMENT MATCHING
-
- Certain types of pattern may give problems with multi-segment matching,
- whichever matching function is used.
-
- 1. If the pattern contains a test for the beginning of a line, you need
- to pass the PCRE2_NOTBOL option when the subject string for any call
- does start at the beginning of a line. There is also a PCRE2_NOTEOL
- option, but in practice when doing multi-segment matching you should be
- using PCRE2_PARTIAL_HARD, which includes the effect of PCRE2_NOTEOL.
-
- 2. If a pattern contains a lookbehind assertion, characters that pre-
- cede the start of the partial match may have been inspected during the
- matching process. When using pcre2_match(), sufficient characters must
- be retained for the next match attempt. You can ensure that enough
- characters are retained by doing the following:
-
- Before doing any matching, find the length of the longest lookbehind in
- the pattern by calling pcre2_pattern_info() with the
- PCRE2_INFO_MAXLOOKBEHIND option. Note that the resulting count is in
- characters, not code units. After a partial match, moving back from the
- ovector[0] offset in the subject by the number of characters given for
- the maximum lookbehind gets you to the earliest character that must be
- retained. In a non-UTF or a 32-bit situation, moving back is just a
- subtraction, but in UTF-8 or UTF-16 you have to count characters while
- moving back through the code units.
-
- Characters before the point you have now reached can be discarded, and
- after the next segment has been added to what is retained, you should
- run the next match with the startoffset argument set so that the match
- begins at the same point as before.
-
- For example, if the pattern "(?<=123)abc" is partially matched against
- the string "xx123ab", the ovector offsets are 5 and 7 ("ab"). The maxi-
- mum lookbehind count is 3, so all characters before offset 2 can be
- discarded. The value of startoffset for the next match should be 3.
- When pcre2test displays a partial match, it indicates the lookbehind
- characters with '<' characters:
-
- re> "(?<=123)abc"
- data> xx123ab\=ph
- Partial match: 123ab
- <<<
-
- 3. Because a partial match must always contain at least one character,
- what might be considered a partial match of an empty string actually
- gives a "no match" result. For example:
-
- re> /c(?<=abc)x/
- data> ab\=ps
- No match
-
- If the next segment begins "cx", a match should be found, but this will
- only happen if characters from the previous segment are retained. For
- this reason, a "no match" result should be interpreted as "partial
- match of an empty string" when the pattern contains lookbehinds.
-
- 4. Matching a subject string that is split into multiple segments may
- not always produce exactly the same result as matching over one single
- long string, especially when PCRE2_PARTIAL_SOFT is used. The section
- "Partial Matching and Word Boundaries" above describes an issue that
- arises if the pattern ends with \b or \B. Another kind of difference
- may occur when there are multiple matching possibilities, because (for
- PCRE2_PARTIAL_SOFT) a partial match result is given only when there are
- no completed matches. This means that as soon as the shortest match has
- been found, continuation to a new subject segment is no longer possi-
- ble. Consider this pcre2test example:
-
- re> /dog(sbody)?/
- data> dogsb\=ps
- 0: dog
- data> do\=ps,dfa
- Partial match: do
- data> gsb\=ps,dfa,dfa_restart
- 0: g
- data> dogsbody\=dfa
- 0: dogsbody
- 1: dog
-
- The first data line passes the string "dogsb" to a standard matching
- function, setting the PCRE2_PARTIAL_SOFT option. Although the string is
- a partial match for "dogsbody", the result is not PCRE2_ERROR_PARTIAL,
- because the shorter string "dog" is a complete match. Similarly, when
- the subject is presented to a DFA matching function in several parts
- ("do" and "gsb" being the first two) the match stops when "dog" has
- been found, and it is not possible to continue. On the other hand, if
- "dogsbody" is presented as a single string, a DFA matching function
- finds both matches.
-
- Because of these problems, it is best to use PCRE2_PARTIAL_HARD when
- matching multi-segment data. The example above then behaves differ-
- ently:
-
- re> /dog(sbody)?/
- data> dogsb\=ph
- Partial match: dogsb
- data> do\=ps,dfa
- Partial match: do
- data> gsb\=ph,dfa,dfa_restart
- Partial match: gsb
-
- 5. Patterns that contain alternatives at the top level which do not all
- start with the same pattern item may not work as expected when
- PCRE2_DFA_RESTART is used. For example, consider this pattern:
+ to. This means that, for an unanchored pattern, if a continued match
+ fails, it is not possible to try again at a new starting point. All
+ this facility is capable of doing is continuing with the previous match
+ attempt. For example, consider this pattern:
1234|3789
@@ -5828,29 +6010,16 @@ ISSUES WITH MULTI-SEGMENT MATCHING
the second alternative, because such a match does not start at the same
point in the subject string. Attempting to continue with the string
"7890" does not yield a match because only those alternatives that
- match at one point in the subject are remembered. The problem arises
- because the start of the second alternative matches within the first
- alternative. There is no problem with anchored patterns or patterns
- such as:
-
- 1234|ABCD
-
- where no string can be a partial match for both alternatives. This is
- not a problem if a standard matching function is used, because the
- entire match has to be rerun each time:
-
- re> /1234|3789/
- data> ABC123\=ph
- Partial match: 123
- data> 1237890
- 0: 3789
+ match at one point in the subject are remembered. Depending on the ap-
+ plication, this may or may not be what you want.
- Of course, instead of using PCRE2_DFA_RESTART, the same technique of
- re-running the entire match can also be used with the DFA matching
- function. Another possibility is to work with two buffers. If a partial
- match at offset n in the first buffer is followed by "no match" when
- PCRE2_DFA_RESTART is used on the second buffer, you can then try a new
- match starting at offset n+1 in the first buffer.
+ If you do want to allow for starting again at the next character, one
+ way of doing it is to retain some or all of the segment and try a new
+ complete match, as described for pcre2_match() above. Another possibil-
+ ity is to work with two buffers. If a partial match at offset n in the
+ first buffer is followed by "no match" when PCRE2_DFA_RESTART is used
+ on the second buffer, you can then try a new match starting at offset
+ n+1 in the first buffer.
AUTHOR
@@ -5862,8 +6031,8 @@ AUTHOR
REVISION
- Last updated: 22 December 2014
- Copyright (c) 1997-2014 University of Cambridge.
+ Last updated: 04 September 2019
+ Copyright (c) 1997-2019 University of Cambridge.
------------------------------------------------------------------------------
@@ -5886,114 +6055,115 @@ PCRE2 REGULAR EXPRESSION DETAILS
Perl's regular expressions are described in its own documentation, and
regular expressions in general are covered in a number of books, some
- of which have copious examples. Jeffrey Friedl's "Mastering Regular
- Expressions", published by O'Reilly, covers regular expressions in
- great detail. This description of PCRE2's regular expressions is
- intended as reference material.
+ of which have copious examples. Jeffrey Friedl's "Mastering Regular Ex-
+ pressions", published by O'Reilly, covers regular expressions in great
+ detail. This description of PCRE2's regular expressions is intended as
+ reference material.
- This document discusses the patterns that are supported by PCRE2 when
- its main matching function, pcre2_match(), is used. PCRE2 also has an
- alternative matching function, pcre2_dfa_match(), which matches using a
- different algorithm that is not Perl-compatible. Some of the features
- discussed below are not available when DFA matching is used. The advan-
- tages and disadvantages of the alternative function, and how it differs
- from the normal function, are discussed in the pcre2matching page.
+ This document discusses the regular expression patterns that are sup-
+ ported by PCRE2 when its main matching function, pcre2_match(), is
+ used. PCRE2 also has an alternative matching function,
+ pcre2_dfa_match(), which matches using a different algorithm that is
+ not Perl-compatible. Some of the features discussed below are not
+ available when DFA matching is used. The advantages and disadvantages
+ of the alternative function, and how it differs from the normal func-
+ tion, are discussed in the pcre2matching page.
SPECIAL START-OF-PATTERN ITEMS
- A number of options that can be passed to pcre2_compile() can also be
+ A number of options that can be passed to pcre2_compile() can also be
set by special items at the start of a pattern. These are not Perl-com-
- patible, but are provided to make these options accessible to pattern
- writers who are not able to change the program that processes the pat-
- tern. Any number of these items may appear, but they must all be
- together right at the start of the pattern string, and the letters must
+ patible, but are provided to make these options accessible to pattern
+ writers who are not able to change the program that processes the pat-
+ tern. Any number of these items may appear, but they must all be to-
+ gether right at the start of the pattern string, and the letters must
be in upper case.
UTF support
In the 8-bit and 16-bit PCRE2 libraries, characters may be coded either
as single code units, or as multiple UTF-8 or UTF-16 code units. UTF-32
- can be specified for the 32-bit library, in which case it constrains
- the character values to valid Unicode code points. To process UTF
- strings, PCRE2 must be built to include Unicode support (which is the
- default). When using UTF strings you must either call the compiling
- function with the PCRE2_UTF option, or the pattern must start with the
- special sequence (*UTF), which is equivalent to setting the relevant
- option. How setting a UTF mode affects pattern matching is mentioned in
- several places below. There is also a summary of features in the
- pcre2unicode page.
+ can be specified for the 32-bit library, in which case it constrains
+ the character values to valid Unicode code points. To process UTF
+ strings, PCRE2 must be built to include Unicode support (which is the
+ default). When using UTF strings you must either call the compiling
+ function with one or both of the PCRE2_UTF or PCRE2_MATCH_INVALID_UTF
+ options, or the pattern must start with the special sequence (*UTF),
+ which is equivalent to setting the relevant PCRE2_UTF. How setting a
+ UTF mode affects pattern matching is mentioned in several places below.
+ There is also a summary of features in the pcre2unicode page.
Some applications that allow their users to supply patterns may wish to
- restrict them to non-UTF data for security reasons. If the
- PCRE2_NEVER_UTF option is passed to pcre2_compile(), (*UTF) is not
- allowed, and its appearance in a pattern causes an error.
+ restrict them to non-UTF data for security reasons. If the
+ PCRE2_NEVER_UTF option is passed to pcre2_compile(), (*UTF) is not al-
+ lowed, and its appearance in a pattern causes an error.
Unicode property support
- Another special sequence that may appear at the start of a pattern is
- (*UCP). This has the same effect as setting the PCRE2_UCP option: it
- causes sequences such as \d and \w to use Unicode properties to deter-
+ Another special sequence that may appear at the start of a pattern is
+ (*UCP). This has the same effect as setting the PCRE2_UCP option: it
+ causes sequences such as \d and \w to use Unicode properties to deter-
mine character types, instead of recognizing only characters with codes
less than 256 via a lookup table.
Some applications that allow their users to supply patterns may wish to
- restrict them for security reasons. If the PCRE2_NEVER_UCP option is
+ restrict them for security reasons. If the PCRE2_NEVER_UCP option is
passed to pcre2_compile(), (*UCP) is not allowed, and its appearance in
a pattern causes an error.
Locking out empty string matching
Starting a pattern with (*NOTEMPTY) or (*NOTEMPTY_ATSTART) has the same
- effect as passing the PCRE2_NOTEMPTY or PCRE2_NOTEMPTY_ATSTART option
+ effect as passing the PCRE2_NOTEMPTY or PCRE2_NOTEMPTY_ATSTART option
to whichever matching function is subsequently called to match the pat-
- tern. These options lock out the matching of empty strings, either
- entirely, or only at the start of the subject.
+ tern. These options lock out the matching of empty strings, either en-
+ tirely, or only at the start of the subject.
Disabling auto-possessification
- If a pattern starts with (*NO_AUTO_POSSESS), it has the same effect as
- setting the PCRE2_NO_AUTO_POSSESS option. This stops PCRE2 from making
- quantifiers possessive when what follows cannot match the repeated
+ If a pattern starts with (*NO_AUTO_POSSESS), it has the same effect as
+ setting the PCRE2_NO_AUTO_POSSESS option. This stops PCRE2 from making
+ quantifiers possessive when what follows cannot match the repeated
item. For example, by default a+b is treated as a++b. For more details,
see the pcre2api documentation.
Disabling start-up optimizations
- If a pattern starts with (*NO_START_OPT), it has the same effect as
+ If a pattern starts with (*NO_START_OPT), it has the same effect as
setting the PCRE2_NO_START_OPTIMIZE option. This disables several opti-
- mizations for quickly reaching "no match" results. For more details,
+ mizations for quickly reaching "no match" results. For more details,
see the pcre2api documentation.
Disabling automatic anchoring
- If a pattern starts with (*NO_DOTSTAR_ANCHOR), it has the same effect
- as setting the PCRE2_NO_DOTSTAR_ANCHOR option. This disables optimiza-
+ If a pattern starts with (*NO_DOTSTAR_ANCHOR), it has the same effect
+ as setting the PCRE2_NO_DOTSTAR_ANCHOR option. This disables optimiza-
tions that apply to patterns whose top-level branches all start with .*
- (match any number of arbitrary characters). For more details, see the
+ (match any number of arbitrary characters). For more details, see the
pcre2api documentation.
Disabling JIT compilation
- If a pattern that starts with (*NO_JIT) is successfully compiled, an
- attempt by the application to apply the JIT optimization by calling
+ If a pattern that starts with (*NO_JIT) is successfully compiled, an
+ attempt by the application to apply the JIT optimization by calling
pcre2_jit_compile() is ignored.
Setting match resource limits
The pcre2_match() function contains a counter that is incremented every
time it goes round its main loop. The caller of pcre2_match() can set a
- limit on this counter, which therefore limits the amount of computing
+ limit on this counter, which therefore limits the amount of computing
resource used for a match. The maximum depth of nested backtracking can
- also be limited; this indirectly restricts the amount of heap memory
- that is used, but there is also an explicit memory limit that can be
+ also be limited; this indirectly restricts the amount of heap memory
+ that is used, but there is also an explicit memory limit that can be
set.
- These facilities are provided to catch runaway matches that are pro-
- voked by patterns with huge matching trees (a typical example is a pat-
- tern with nested unlimited repeats applied to a long string that does
- not match). When one of these limits is reached, pcre2_match() gives an
- error return. The limits can also be set by items at the start of the
+ These facilities are provided to catch runaway matches that are pro-
+ voked by patterns with huge matching trees. A common example is a pat-
+ tern with nested unlimited repeats applied to a long string that does
+ not match. When one of these limits is reached, pcre2_match() gives an
+ error return. The limits can also be set by items at the start of the
pattern of the form
(*LIMIT_HEAP=d)
@@ -6001,35 +6171,35 @@ SPECIAL START-OF-PATTERN ITEMS
(*LIMIT_DEPTH=d)
where d is any number of decimal digits. However, the value of the set-
- ting must be less than the value set (or defaulted) by the caller of
- pcre2_match() for it to have any effect. In other words, the pattern
- writer can lower the limits set by the programmer, but not raise them.
- If there is more than one setting of one of these limits, the lower
- value is used. The heap limit is specified in kibibytes (units of 1024
+ ting must be less than the value set (or defaulted) by the caller of
+ pcre2_match() for it to have any effect. In other words, the pattern
+ writer can lower the limits set by the programmer, but not raise them.
+ If there is more than one setting of one of these limits, the lower
+ value is used. The heap limit is specified in kibibytes (units of 1024
bytes).
- Prior to release 10.30, LIMIT_DEPTH was called LIMIT_RECURSION. This
+ Prior to release 10.30, LIMIT_DEPTH was called LIMIT_RECURSION. This
name is still recognized for backwards compatibility.
The heap limit applies only when the pcre2_match() or pcre2_dfa_match()
interpreters are used for matching. It does not apply to JIT. The match
- limit is used (but in a different way) when JIT is being used, or when
+ limit is used (but in a different way) when JIT is being used, or when
pcre2_dfa_match() is called, to limit computing resource usage by those
- matching functions. The depth limit is ignored by JIT but is relevant
- for DFA matching, which uses function recursion for recursions within
- the pattern and for lookaround assertions and atomic groups. In this
+ matching functions. The depth limit is ignored by JIT but is relevant
+ for DFA matching, which uses function recursion for recursions within
+ the pattern and for lookaround assertions and atomic groups. In this
case, the depth limit controls the depth of such recursion.
Newline conventions
- PCRE2 supports six different conventions for indicating line breaks in
- strings: a single CR (carriage return) character, a single LF (line-
+ PCRE2 supports six different conventions for indicating line breaks in
+ strings: a single CR (carriage return) character, a single LF (line-
feed) character, the two-character sequence CRLF, any of the three pre-
- ceding, any Unicode newline sequence, or the NUL character (binary
- zero). The pcre2api page has further discussion about newlines, and
+ ceding, any Unicode newline sequence, or the NUL character (binary
+ zero). The pcre2api page has further discussion about newlines, and
shows how to set the newline convention when calling pcre2_compile().
- It is also possible to specify a newline convention by starting a pat-
+ It is also possible to specify a newline convention by starting a pat-
tern string with one of the following sequences:
(*CR) carriage return
@@ -6040,8 +6210,8 @@ SPECIAL START-OF-PATTERN ITEMS
(*NUL) the NUL character (binary zero)
These override the default and the options given to the compiling func-
- tion. For example, on a Unix system where LF is the default newline
- sequence, the pattern
+ tion. For example, on a Unix system where LF is the default newline se-
+ quence, the pattern
(*CR)a.b
@@ -6049,39 +6219,39 @@ SPECIAL START-OF-PATTERN ITEMS
no longer a newline. If more than one of these settings is present, the
last one is used.
- The newline convention affects where the circumflex and dollar asser-
+ The newline convention affects where the circumflex and dollar asser-
tions are true. It also affects the interpretation of the dot metachar-
- acter when PCRE2_DOTALL is not set, and the behaviour of \N when not
- followed by an opening brace. However, it does not affect what the \R
- escape sequence matches. By default, this is any Unicode newline
- sequence, for Perl compatibility. However, this can be changed; see the
+ acter when PCRE2_DOTALL is not set, and the behaviour of \N when not
+ followed by an opening brace. However, it does not affect what the \R
+ escape sequence matches. By default, this is any Unicode newline se-
+ quence, for Perl compatibility. However, this can be changed; see the
next section and the description of \R in the section entitled "Newline
- sequences" below. A change of \R setting can be combined with a change
+ sequences" below. A change of \R setting can be combined with a change
of newline convention.
Specifying what \R matches
It is possible to restrict \R to match only CR, LF, or CRLF (instead of
- the complete set of Unicode line endings) by setting the option
- PCRE2_BSR_ANYCRLF at compile time. This effect can also be achieved by
- starting a pattern with (*BSR_ANYCRLF). For completeness, (*BSR_UNI-
+ the complete set of Unicode line endings) by setting the option
+ PCRE2_BSR_ANYCRLF at compile time. This effect can also be achieved by
+ starting a pattern with (*BSR_ANYCRLF). For completeness, (*BSR_UNI-
CODE) is also recognized, corresponding to PCRE2_BSR_UNICODE.
EBCDIC CHARACTER CODES
- PCRE2 can be compiled to run in an environment that uses EBCDIC as its
- character code instead of ASCII or Unicode (typically a mainframe sys-
- tem). In the sections below, character code values are ASCII or Uni-
+ PCRE2 can be compiled to run in an environment that uses EBCDIC as its
+ character code instead of ASCII or Unicode (typically a mainframe sys-
+ tem). In the sections below, character code values are ASCII or Uni-
code; in an EBCDIC environment these characters may have different code
values, and there are no code points greater than 255.
CHARACTERS AND METACHARACTERS
- A regular expression is a pattern that is matched against a subject
- string from left to right. Most characters stand for themselves in a
- pattern, and match the corresponding characters in the subject. As a
+ A regular expression is a pattern that is matched against a subject
+ string from left to right. Most characters stand for themselves in a
+ pattern, and match the corresponding characters in the subject. As a
trivial example, the pattern
The quick brown fox
@@ -6090,10 +6260,11 @@ CHARACTERS AND METACHARACTERS
caseless matching is specified (the PCRE2_CASELESS option), letters are
matched independently of case.
- The power of regular expressions comes from the ability to include
- alternatives and repetitions in the pattern. These are encoded in the
- pattern by the use of metacharacters, which do not stand for themselves
- but instead are interpreted in some special way.
+ The power of regular expressions comes from the ability to include wild
+ cards, character classes, alternatives, and repetitions in the pattern.
+ These are encoded in the pattern by the use of metacharacters, which do
+ not stand for themselves but instead are interpreted in some special
+ way.
There are two different sets of metacharacters: those that are recog-
nized anywhere in the pattern except within square brackets, and those
@@ -6106,14 +6277,11 @@ CHARACTERS AND METACHARACTERS
. match any character except newline (by default)
[ start character class definition
| start of alternative branch
- ( start subpattern
- ) end subpattern
- ? extends the meaning of (
- also 0 or 1 quantifier
- also quantifier minimizer
+ ( start group or control verb
+ ) end group or control verb
* 0 or more quantifier
- + 1 or more quantifier
- also "possessive quantifier"
+ + 1 or more quantifier; also "possessive quantifier"
+ ? 0 or 1 quantifier; also quantifier minimizer
{ start min/max quantifier
Part of a pattern that is in square brackets is called a "character
@@ -6122,8 +6290,7 @@ CHARACTERS AND METACHARACTERS
\ general escape character
^ negate the class, but only if the first character
- indicates character range
- [ POSIX character class (only if followed by POSIX
- syntax)
+ [ POSIX character class (if followed by POSIX syntax)
] terminates the character class
The following sections describe the use of each of the metacharacters.
@@ -6132,7 +6299,7 @@ CHARACTERS AND METACHARACTERS
BACKSLASH
The backslash character has several uses. Firstly, if it is followed by
- a character that is not a number or a letter, it takes away any special
+ a character that is not a digit or a letter, it takes away any special
meaning that character may have. This use of backslash as an escape
character applies both inside and outside character classes.
@@ -6143,7 +6310,7 @@ BACKSLASH
that it stands for itself. In particular, if you want to match a back-
slash, you write \\.
- In a UTF mode, only ASCII numbers and letters have any special meaning
+ In a UTF mode, only ASCII digits and letters have any special meaning
after a backslash. All other characters (in particular, those whose
code points are greater than 127) are treated as literals.
@@ -6153,14 +6320,14 @@ BACKSLASH
are ignored. An escaping backslash can be used to include a white space
or # character as part of the pattern.
- If you want to remove the special meaning from a sequence of charac-
- ters, you can do so by putting them between \Q and \E. This is differ-
- ent from Perl in that $ and @ are handled as literals in \Q...\E
- sequences in PCRE2, whereas in Perl, $ and @ cause variable interpola-
- tion. Also, Perl does "double-quotish backslash interpolation" on any
- backslashes between \Q and \E which, its documentation says, "may lead
- to confusing results". PCRE2 treats a backslash between \Q and \E just
- like any other character. Note the following examples:
+ If you want to treat all characters in a sequence as literals, you can
+ do so by putting them between \Q and \E. This is different from Perl in
+ that $ and @ are handled as literals in \Q...\E sequences in PCRE2,
+ whereas in Perl, $ and @ cause variable interpolation. Also, Perl does
+ "double-quotish backslash interpolation" on any backslashes between \Q
+ and \E which, its documentation says, "may lead to confusing results".
+ PCRE2 treats a backslash between \Q and \E just like any other charac-
+ ter. Note the following examples:
Pattern PCRE2 matches Perl matches
@@ -6185,15 +6352,16 @@ BACKSLASH
acters in patterns in a visible manner. There is no restriction on the
appearance of non-printing characters in a pattern, but when a pattern
is being prepared by text editing, it is often easier to use one of the
- following escape sequences than the binary character it represents. In
- an ASCII or Unicode environment, these escapes are as follows:
+ following escape sequences instead of the binary character it repre-
+ sents. In an ASCII or Unicode environment, these escapes are as fol-
+ lows:
\a alarm, that is, the BEL character (hex 07)
\cx "control-x", where x is any printable ASCII character
\e escape (hex 1B)
\f form feed (hex 0C)
\n linefeed (hex 0A)
- \r carriage return (hex 0D)
+ \r carriage return (hex 0D) (but see below)
\t tab (hex 09)
\0dd character with octal code 0dd
\ddd character with octal code ddd, or backreference
@@ -6201,55 +6369,84 @@ BACKSLASH
\xhh character with hex code hh
\x{hhh..} character with hex code hhh..
\N{U+hhh..} character with Unicode hex code point hhh..
- \uhhhh character with hex code hhhh (when PCRE2_ALT_BSUX is set)
- The \N{U+hhh..} escape sequence is recognized only when the PCRE2_UTF
- option is set, that is, when PCRE2 is operating in a Unicode mode. Perl
- also uses \N{name} to specify characters by Unicode name; PCRE2 does
- not support this. Note that when \N is not followed by an opening
- brace (curly bracket) it has an entirely different meaning, matching
- any character that is not a newline.
+ By default, after \x that is not followed by {, from zero to two hexa-
+ decimal digits are read (letters can be in upper or lower case). Any
+ number of hexadecimal digits may appear between \x{ and }. If a charac-
+ ter other than a hexadecimal digit appears between \x{ and }, or if
+ there is no terminating }, an error occurs.
- The precise effect of \cx on ASCII characters is as follows: if x is a
- lower case letter, it is converted to upper case. Then bit 6 of the
+ Characters whose code points are less than 256 can be defined by either
+ of the two syntaxes for \x or by an octal sequence. There is no differ-
+ ence in the way they are handled. For example, \xdc is exactly the same
+ as \x{dc} or \334. However, using the braced versions does make such
+ sequences easier to read.
+
+ Support is available for some ECMAScript (aka JavaScript) escape se-
+ quences via two compile-time options. If PCRE2_ALT_BSUX is set, the se-
+ quence \x followed by { is not recognized. Only if \x is followed by
+ two hexadecimal digits is it recognized as a character escape. Other-
+ wise it is interpreted as a literal "x" character. In this mode, sup-
+ port for code points greater than 256 is provided by \u, which must be
+ followed by four hexadecimal digits; otherwise it is interpreted as a
+ literal "u" character.
+
+ PCRE2_EXTRA_ALT_BSUX has the same effect as PCRE2_ALT_BSUX and, in ad-
+ dition, \u{hhh..} is recognized as the character specified by hexadeci-
+ mal code point. There may be any number of hexadecimal digits. This
+ syntax is from ECMAScript 6.
+
+ The \N{U+hhh..} escape sequence is recognized only when PCRE2 is oper-
+ ating in UTF mode. Perl also uses \N{name} to specify characters by
+ Unicode name; PCRE2 does not support this. Note that when \N is not
+ followed by an opening brace (curly bracket) it has an entirely differ-
+ ent meaning, matching any character that is not a newline.
+
+ There are some legacy applications where the escape sequence \r is ex-
+ pected to match a newline. If the PCRE2_EXTRA_ESCAPED_CR_IS_LF option
+ is set, \r in a pattern is converted to \n so that it matches a LF
+ (linefeed) instead of a CR (carriage return) character.
+
+ The precise effect of \cx on ASCII characters is as follows: if x is a
+ lower case letter, it is converted to upper case. Then bit 6 of the
character (hex 40) is inverted. Thus \cA to \cZ become hex 01 to hex 1A
- (A is 41, Z is 5A), but \c{ becomes hex 3B ({ is 7B), and \c; becomes
- hex 7B (; is 3B). If the code unit following \c has a value less than
+ (A is 41, Z is 5A), but \c{ becomes hex 3B ({ is 7B), and \c; becomes
+ hex 7B (; is 3B). If the code unit following \c has a value less than
32 or greater than 126, a compile-time error occurs.
- When PCRE2 is compiled in EBCDIC mode, \N{U+hhh..} is not supported.
+ When PCRE2 is compiled in EBCDIC mode, \N{U+hhh..} is not supported.
\a, \e, \f, \n, \r, and \t generate the appropriate EBCDIC code values.
The \c escape is processed as specified for Perl in the perlebcdic doc-
- ument. The only characters that are allowed after \c are A-Z, a-z, or
- one of @, [, \, ], ^, _, or ?. Any other character provokes a compile-
- time error. The sequence \c@ encodes character code 0; after \c the
- letters (in either case) encode characters 1-26 (hex 01 to hex 1A); [,
- \, ], ^, and _ encode characters 27-31 (hex 1B to hex 1F), and \c?
- becomes either 255 (hex FF) or 95 (hex 5F).
-
- Thus, apart from \c?, these escapes generate the same character code
- values as they do in an ASCII environment, though the meanings of the
- values mostly differ. For example, \cG always generates code value 7,
+ ument. The only characters that are allowed after \c are A-Z, a-z, or
+ one of @, [, \, ], ^, _, or ?. Any other character provokes a compile-
+ time error. The sequence \c@ encodes character code 0; after \c the
+ letters (in either case) encode characters 1-26 (hex 01 to hex 1A); [,
+ \, ], ^, and _ encode characters 27-31 (hex 1B to hex 1F), and \c? be-
+ comes either 255 (hex FF) or 95 (hex 5F).
+
+ Thus, apart from \c?, these escapes generate the same character code
+ values as they do in an ASCII environment, though the meanings of the
+ values mostly differ. For example, \cG always generates code value 7,
which is BEL in ASCII but DEL in EBCDIC.
- The sequence \c? generates DEL (127, hex 7F) in an ASCII environment,
- but because 127 is not a control character in EBCDIC, Perl makes it
- generate the APC character. Unfortunately, there are several variants
- of EBCDIC. In most of them the APC character has the value 255 (hex
- FF), but in the one Perl calls POSIX-BC its value is 95 (hex 5F). If
+ The sequence \c? generates DEL (127, hex 7F) in an ASCII environment,
+ but because 127 is not a control character in EBCDIC, Perl makes it
+ generate the APC character. Unfortunately, there are several variants
+ of EBCDIC. In most of them the APC character has the value 255 (hex
+ FF), but in the one Perl calls POSIX-BC its value is 95 (hex 5F). If
certain other characters have POSIX-BC values, PCRE2 makes \c? generate
95; otherwise it generates 255.
- After \0 up to two further octal digits are read. If there are fewer
- than two digits, just those that are present are used. Thus the
- sequence \0\x\015 specifies two binary zeros followed by a CR character
+ After \0 up to two further octal digits are read. If there are fewer
+ than two digits, just those that are present are used. Thus the se-
+ quence \0\x\015 specifies two binary zeros followed by a CR character
(code value 13). Make sure you supply two digits after the initial zero
if the pattern character that follows is itself an octal digit.
- The escape \o must be followed by a sequence of octal digits, enclosed
- in braces. An error occurs if this is not the case. This escape is a
- recent addition to Perl; it provides way of specifying character code
- points as octal numbers greater than 0777, and it also allows octal
+ The escape \o must be followed by a sequence of octal digits, enclosed
+ in braces. An error occurs if this is not the case. This escape is a
+ recent addition to Perl; it provides way of specifying character code
+ points as octal numbers greater than 0777, and it also allows octal
numbers and backreferences to be unambiguously specified.
For greater clarity and unambiguity, it is best to avoid following \ by
@@ -6262,21 +6459,21 @@ BACKSLASH
Outside a character class, PCRE2 reads the digit and any following dig-
its as a decimal number. If the number is less than 10, begins with the
- digit 8 or 9, or if there are at least that many previous capturing
- left parentheses in the expression, the entire sequence is taken as a
- backreference. A description of how this works is given later, follow-
- ing the discussion of parenthesized subpatterns. Otherwise, up to
- three octal digits are read to form a character code.
-
- Inside a character class, PCRE2 handles \8 and \9 as the literal char-
- acters "8" and "9", and otherwise reads up to three octal digits fol-
+ digit 8 or 9, or if there are at least that many previous capture
+ groups in the expression, the entire sequence is taken as a backrefer-
+ ence. A description of how this works is given later, following the
+ discussion of parenthesized groups. Otherwise, up to three octal dig-
+ its are read to form a character code.
+
+ Inside a character class, PCRE2 handles \8 and \9 as the literal char-
+ acters "8" and "9", and otherwise reads up to three octal digits fol-
lowing the backslash, using them to generate a data character. Any sub-
- sequent digits stand for themselves. For example, outside a character
+ sequent digits stand for themselves. For example, outside a character
class:
\040 is another way of writing an ASCII space
\40 is the same, provided there are fewer than 40
- previous capturing subpatterns
+ previous capture groups
\7 is always a backreference
\11 might be a backreference, or another way of
writing a tab
@@ -6288,31 +6485,13 @@ BACKSLASH
the value 255 (decimal)
\81 is always a backreference
- Note that octal values of 100 or greater that are specified using this
- syntax must not be introduced by a leading zero, because no more than
+ Note that octal values of 100 or greater that are specified using this
+ syntax must not be introduced by a leading zero, because no more than
three octal digits are ever read.
- By default, after \x that is not followed by {, from zero to two hexa-
- decimal digits are read (letters can be in upper or lower case). Any
- number of hexadecimal digits may appear between \x{ and }. If a charac-
- ter other than a hexadecimal digit appears between \x{ and }, or if
- there is no terminating }, an error occurs.
-
- If the PCRE2_ALT_BSUX option is set, the interpretation of \x is as
- just described only when it is followed by two hexadecimal digits. Oth-
- erwise, it matches a literal "x" character. In this mode, support for
- code points greater than 256 is provided by \u, which must be followed
- by four hexadecimal digits; otherwise it matches a literal "u" charac-
- ter.
-
- Characters whose value is less than 256 can be defined by either of the
- two syntaxes for \x (or by \u in PCRE2_ALT_BSUX mode). There is no dif-
- ference in the way they are handled. For example, \xdc is exactly the
- same as \x{dc} (or \u00dc in PCRE2_ALT_BSUX mode).
-
Constraints on character values
- Characters that are specified using octal or hexadecimal numbers are
+ Characters that are specified using octal or hexadecimal numbers are
limited to certain values, as follows:
8-bit non-UTF mode no greater than 0xff
@@ -6321,43 +6500,44 @@ BACKSLASH
All UTF modes no greater than 0x10ffff and a valid code point
Invalid Unicode code points are all those in the range 0xd800 to 0xdfff
- (the so-called "surrogate" code points). The check for these can be
- disabled by the caller of pcre2_compile() by setting the option
- PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES. However, this is possible only in
- UTF-8 and UTF-32 modes, because these values are not representable in
+ (the so-called "surrogate" code points). The check for these can be
+ disabled by the caller of pcre2_compile() by setting the option
+ PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES. However, this is possible only in
+ UTF-8 and UTF-32 modes, because these values are not representable in
UTF-16.
Escape sequences in character classes
All the sequences that define a single character value can be used both
- inside and outside character classes. In addition, inside a character
+ inside and outside character classes. In addition, inside a character
class, \b is interpreted as the backspace character (hex 08).
When not followed by an opening brace, \N is not allowed in a character
- class. \B, \R, and \X are not special inside a character class. Like
- other unrecognized alphabetic escape sequences, they cause an error.
+ class. \B, \R, and \X are not special inside a character class. Like
+ other unrecognized alphabetic escape sequences, they cause an error.
Outside a character class, these sequences have different meanings.
Unsupported escape sequences
- In Perl, the sequences \F, \l, \L, \u, and \U are recognized by its
- string handler and used to modify the case of following characters. By
- default, PCRE2 does not support these escape sequences. However, if the
- PCRE2_ALT_BSUX option is set, \U matches a "U" character, and \u can be
- used to define a character by code point, as described above.
+ In Perl, the sequences \F, \l, \L, \u, and \U are recognized by its
+ string handler and used to modify the case of following characters. By
+ default, PCRE2 does not support these escape sequences in patterns.
+ However, if either of the PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX op-
+ tions is set, \U matches a "U" character, and \u can be used to define
+ a character by code point, as described above.
Absolute and relative backreferences
- The sequence \g followed by a signed or unsigned number, optionally
- enclosed in braces, is an absolute or relative backreference. A named
+ The sequence \g followed by a signed or unsigned number, optionally en-
+ closed in braces, is an absolute or relative backreference. A named
backreference can be coded as \g{name}. Backreferences are discussed
- later, following the discussion of parenthesized subpatterns.
+ later, following the discussion of parenthesized groups.
Absolute and relative subroutine calls
For compatibility with Oniguruma, the non-Perl syntax \g followed by a
name or a number enclosed either in angle brackets or single quotes, is
- an alternative syntax for referencing a subpattern as a "subroutine".
+ an alternative syntax for referencing a capture group as a subroutine.
Details are discussed later. Note that \g{...} (Perl syntax) and
\g<...> (Oniguruma syntax) are not synonymous. The former is a backref-
erence; the latter is a subroutine call.
@@ -6394,8 +6574,8 @@ BACKSLASH
match.
The default \s characters are HT (9), LF (10), VT (11), FF (12), CR
- (13), and space (32), which are defined as white space in the "C"
- locale. This list may vary if locale-specific matching is taking place.
+ (13), and space (32), which are defined as white space in the "C" lo-
+ cale. This list may vary if locale-specific matching is taking place.
For example, in some locales the "non-breaking space" character (\xA0)
is recognized as white space, and in others the VT character is not.
@@ -6473,8 +6653,8 @@ BACKSLASH
(?>\r\n|\n|\x0b|\f|\r|\x85)
- This is an example of an "atomic group", details of which are given
- below. This particular group matches either the two-character sequence
+ This is an example of an "atomic group", details of which are given be-
+ low. This particular group matches either the two-character sequence
CR followed by LF, or one of the single characters LF (linefeed,
U+000A), VT (vertical tab, U+000B), FF (form feed, U+000C), CR (car-
riage return, U+000D), or NEL (next line, U+0085). Because this is an
@@ -6501,36 +6681,38 @@ BACKSLASH
tion. Note that these special settings, which are not Perl-compatible,
are recognized only at the very start of a pattern, and that they must
be in upper case. If more than one of them is present, the last one is
- used. They can be combined with a change of newline convention; for
- example, a pattern can start with:
+ used. They can be combined with a change of newline convention; for ex-
+ ample, a pattern can start with:
(*ANY)(*BSR_ANYCRLF)
They can also be combined with the (*UTF) or (*UCP) special sequences.
- Inside a character class, \R is treated as an unrecognized escape
- sequence, and causes an error.
+ Inside a character class, \R is treated as an unrecognized escape se-
+ quence, and causes an error.
Unicode character properties
When PCRE2 is built with Unicode support (the default), three addi-
tional escape sequences that match characters with specific properties
- are available. In 8-bit non-UTF-8 mode, these sequences are of course
- limited to testing characters whose code points are less than 256, but
- they do work in this mode. In 32-bit non-UTF mode, code points greater
- than 0x10ffff (the Unicode limit) may be encountered. These are all
- treated as being in the Common script and with an unassigned type. The
- extra escape sequences are:
+ are available. They can be used in any mode, though in 8-bit and 16-bit
+ non-UTF modes these sequences are of course limited to testing charac-
+ ters whose code points are less than U+0100 and U+10000, respectively.
+ In 32-bit non-UTF mode, code points greater than 0x10ffff (the Unicode
+ limit) may be encountered. These are all treated as being in the Un-
+ known script and with an unassigned type. The extra escape sequences
+ are:
\p{xx} a character with the xx property
\P{xx} a character without the xx property
\X a Unicode extended grapheme cluster
- The property names represented by xx above are limited to the Unicode
- script names, the general category properties, "Any", which matches any
- character (including newline), and some special PCRE2 properties
- (described in the next section). Other Perl properties such as "InMu-
- sicalSymbols" are not supported by PCRE2. Note that \P{Any} does not
- match any characters, so always causes a match failure.
+ The property names represented by xx above are case-sensitive. There is
+ support for Unicode script names, Unicode general category properties,
+ "Any", which matches any character (including newline), and some spe-
+ cial PCRE2 properties (described in the next section). Other Perl
+ properties such as "InMusicalSymbols" are not supported by PCRE2. Note
+ that \P{Any} does not match any characters, so always causes a match
+ failure.
Sets of Unicode characters are defined as belonging to certain scripts.
A character from one of these sets can be matched using a script name.
@@ -6539,42 +6721,45 @@ BACKSLASH
\p{Greek}
\P{Han}
- Those that are not part of an identified script are lumped together as
- "Common". The current list of scripts is:
+ Unassigned characters (and in non-UTF 32-bit mode, characters with code
+ points greater than 0x10FFFF) are assigned the "Unknown" script. Others
+ that are not part of an identified script are lumped together as "Com-
+ mon". The current list of scripts is:
Adlam, Ahom, Anatolian_Hieroglyphs, Arabic, Armenian, Avestan, Bali-
nese, Bamum, Bassa_Vah, Batak, Bengali, Bhaiksuki, Bopomofo, Brahmi,
Braille, Buginese, Buhid, Canadian_Aboriginal, Carian, Caucasian_Alba-
nian, Chakma, Cham, Cherokee, Common, Coptic, Cuneiform, Cypriot,
Cyrillic, Deseret, Devanagari, Dogra, Duployan, Egyptian_Hieroglyphs,
- Elbasan, Ethiopic, Georgian, Glagolitic, Gothic, Grantha, Greek,
- Gujarati, Gunjala_Gondi, Gurmukhi, Han, Hangul, Hanifi_Rohingya,
- Hanunoo, Hatran, Hebrew, Hiragana, Imperial_Aramaic, Inherited,
- Inscriptional_Pahlavi, Inscriptional_Parthian, Javanese, Kaithi, Kan-
- nada, Katakana, Kayah_Li, Kharoshthi, Khmer, Khojki, Khudawadi, Lao,
- Latin, Lepcha, Limbu, Linear_A, Linear_B, Lisu, Lycian, Lydian, Maha-
- jani, Makasar, Malayalam, Mandaic, Manichaean, Marchen, Masaram_Gondi,
- Medefaidrin, Meetei_Mayek, Mende_Kikakui, Meroitic_Cursive,
- Meroitic_Hieroglyphs, Miao, Modi, Mongolian, Mro, Multani, Myanmar,
- Nabataean, New_Tai_Lue, Newa, Nko, Nushu, Ogham, Ol_Chiki, Old_Hungar-
- ian, Old_Italic, Old_North_Arabian, Old_Permic, Old_Persian, Old_Sog-
- dian, Old_South_Arabian, Old_Turkic, Oriya, Osage, Osmanya,
- Pahawh_Hmong, Palmyrene, Pau_Cin_Hau, Phags_Pa, Phoenician,
+ Elbasan, Elymaic, Ethiopic, Georgian, Glagolitic, Gothic, Grantha,
+ Greek, Gujarati, Gunjala_Gondi, Gurmukhi, Han, Hangul, Hanifi_Rohingya,
+ Hanunoo, Hatran, Hebrew, Hiragana, Imperial_Aramaic, Inherited, In-
+ scriptional_Pahlavi, Inscriptional_Parthian, Javanese, Kaithi, Kannada,
+ Katakana, Kayah_Li, Kharoshthi, Khmer, Khojki, Khudawadi, Lao, Latin,
+ Lepcha, Limbu, Linear_A, Linear_B, Lisu, Lycian, Lydian, Mahajani,
+ Makasar, Malayalam, Mandaic, Manichaean, Marchen, Masaram_Gondi, Mede-
+ faidrin, Meetei_Mayek, Mende_Kikakui, Meroitic_Cursive, Meroitic_Hiero-
+ glyphs, Miao, Modi, Mongolian, Mro, Multani, Myanmar, Nabataean, Nandi-
+ nagari, New_Tai_Lue, Newa, Nko, Nushu, Nyakeng_Puachue_Hmong, Ogham,
+ Ol_Chiki, Old_Hungarian, Old_Italic, Old_North_Arabian, Old_Permic,
+ Old_Persian, Old_Sogdian, Old_South_Arabian, Old_Turkic, Oriya, Osage,
+ Osmanya, Pahawh_Hmong, Palmyrene, Pau_Cin_Hau, Phags_Pa, Phoenician,
Psalter_Pahlavi, Rejang, Runic, Samaritan, Saurashtra, Sharada, Sha-
vian, Siddham, SignWriting, Sinhala, Sogdian, Sora_Sompeng, Soyombo,
Sundanese, Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tai_Tham,
Tai_Viet, Takri, Tamil, Tangut, Telugu, Thaana, Thai, Tibetan, Tifi-
- nagh, Tirhuta, Ugaritic, Vai, Warang_Citi, Yi, Zanabazar_Square.
+ nagh, Tirhuta, Ugaritic, Unknown, Vai, Wancho, Warang_Citi, Yi, Zan-
+ abazar_Square.
Each character has exactly one Unicode general category property, spec-
- ified by a two-letter abbreviation. For compatibility with Perl, nega-
- tion can be specified by including a circumflex between the opening
- brace and the property name. For example, \p{^Lu} is the same as
+ ified by a two-letter abbreviation. For compatibility with Perl, nega-
+ tion can be specified by including a circumflex between the opening
+ brace and the property name. For example, \p{^Lu} is the same as
\P{Lu}.
If only one letter is specified with \p or \P, it includes all the gen-
- eral category properties that start with that letter. In this case, in
- the absence of negation, the curly brackets in the escape sequence are
+ eral category properties that start with that letter. In this case, in
+ the absence of negation, the curly brackets in the escape sequence are
optional; these two examples have the same effect:
\p{L}
@@ -6626,86 +6811,88 @@ BACKSLASH
Zp Paragraph separator
Zs Space separator
- The special property L& is also supported: it matches a character that
- has the Lu, Ll, or Lt property, in other words, a letter that is not
+ The special property L& is also supported: it matches a character that
+ has the Lu, Ll, or Lt property, in other words, a letter that is not
classified as a modifier or "other".
- The Cs (Surrogate) property applies only to characters in the range
- U+D800 to U+DFFF. Such characters are not valid in Unicode strings and
- so cannot be tested by PCRE2, unless UTF validity checking has been
- turned off (see the discussion of PCRE2_NO_UTF_CHECK in the pcre2api
- page). Perl does not support the Cs property.
+ The Cs (Surrogate) property applies only to characters whose code
+ points are in the range U+D800 to U+DFFF. These characters are no dif-
+ ferent to any other character when PCRE2 is not in UTF mode (using the
+ 16-bit or 32-bit library). However, they are not valid in Unicode
+ strings and so cannot be tested by PCRE2 in UTF mode, unless UTF valid-
+ ity checking has been turned off (see the discussion of
+ PCRE2_NO_UTF_CHECK in the pcre2api page).
- The long synonyms for property names that Perl supports (such as
- \p{Letter}) are not supported by PCRE2, nor is it permitted to prefix
+ The long synonyms for property names that Perl supports (such as
+ \p{Letter}) are not supported by PCRE2, nor is it permitted to prefix
any of these properties with "Is".
No character that is in the Unicode table has the Cn (unassigned) prop-
erty. Instead, this property is assumed for any code point that is not
in the Unicode table.
- Specifying caseless matching does not affect these escape sequences.
- For example, \p{Lu} always matches only upper case letters. This is
+ Specifying caseless matching does not affect these escape sequences.
+ For example, \p{Lu} always matches only upper case letters. This is
different from the behaviour of current versions of Perl.
- Matching characters by Unicode property is not fast, because PCRE2 has
- to do a multistage table lookup in order to find a character's prop-
+ Matching characters by Unicode property is not fast, because PCRE2 has
+ to do a multistage table lookup in order to find a character's prop-
erty. That is why the traditional escape sequences such as \d and \w do
- not use Unicode properties in PCRE2 by default, though you can make
- them do so by setting the PCRE2_UCP option or by starting the pattern
+ not use Unicode properties in PCRE2 by default, though you can make
+ them do so by setting the PCRE2_UCP option or by starting the pattern
with (*UCP).
Extended grapheme clusters
- The \X escape matches any number of Unicode characters that form an
+ The \X escape matches any number of Unicode characters that form an
"extended grapheme cluster", and treats the sequence as an atomic group
- (see below). Unicode supports various kinds of composite character by
- giving each character a grapheme breaking property, and having rules
+ (see below). Unicode supports various kinds of composite character by
+ giving each character a grapheme breaking property, and having rules
that use these properties to define the boundaries of extended grapheme
- clusters. The rules are defined in Unicode Standard Annex 29, "Unicode
- Text Segmentation". Unicode 11.0.0 abandoned the use of some previous
- properties that had been used for emojis. Instead it introduced vari-
- ous emoji-specific properties. PCRE2 uses only the Extended Picto-
+ clusters. The rules are defined in Unicode Standard Annex 29, "Unicode
+ Text Segmentation". Unicode 11.0.0 abandoned the use of some previous
+ properties that had been used for emojis. Instead it introduced vari-
+ ous emoji-specific properties. PCRE2 uses only the Extended Picto-
graphic property.
- \X always matches at least one character. Then it decides whether to
+ \X always matches at least one character. Then it decides whether to
add additional characters according to the following rules for ending a
cluster:
1. End at the end of the subject string.
- 2. Do not end between CR and LF; otherwise end after any control char-
+ 2. Do not end between CR and LF; otherwise end after any control char-
acter.
- 3. Do not break Hangul (a Korean script) syllable sequences. Hangul
- characters are of five types: L, V, T, LV, and LVT. An L character may
- be followed by an L, V, LV, or LVT character; an LV or V character may
+ 3. Do not break Hangul (a Korean script) syllable sequences. Hangul
+ characters are of five types: L, V, T, LV, and LVT. An L character may
+ be followed by an L, V, LV, or LVT character; an LV or V character may
be followed by a V or T character; an LVT or T character may be follwed
only by a T character.
- 4. Do not end before extending characters or spacing marks or the
- "zero-width joiner" character. Characters with the "mark" property
- always have the "extend" grapheme breaking property.
+ 4. Do not end before extending characters or spacing marks or the
+ "zero-width joiner" character. Characters with the "mark" property al-
+ ways have the "extend" grapheme breaking property.
5. Do not end after prepend characters.
6. Do not break within emoji modifier sequences or emoji zwj sequences.
That is, do not break between characters with the Extended_Pictographic
- property. Extend and ZWJ characters are allowed between the charac-
+ property. Extend and ZWJ characters are allowed between the charac-
ters.
- 7. Do not break within emoji flag sequences. That is, do not break
- between regional indicator (RI) characters if there are an odd number
- of RI characters before the break point.
+ 7. Do not break within emoji flag sequences. That is, do not break be-
+ tween regional indicator (RI) characters if there are an odd number of
+ RI characters before the break point.
8. Otherwise, end the cluster.
PCRE2's additional properties
- As well as the standard Unicode properties described above, PCRE2 sup-
- ports four more that make it possible to convert traditional escape
- sequences such as \w and \s to use Unicode properties. PCRE2 uses these
- non-standard, non-Perl properties internally when PCRE2_UCP is set.
+ As well as the standard Unicode properties described above, PCRE2 sup-
+ ports four more that make it possible to convert traditional escape se-
+ quences such as \w and \s to use Unicode properties. PCRE2 uses these
+ non-standard, non-Perl properties internally when PCRE2_UCP is set.
However, they may also be used explicitly. These properties are:
Xan Any alphanumeric character
@@ -6713,70 +6900,70 @@ BACKSLASH
Xsp Any Perl space character
Xwd Any Perl "word" character
- Xan matches characters that have either the L (letter) or the N (num-
- ber) property. Xps matches the characters tab, linefeed, vertical tab,
- form feed, or carriage return, and any other character that has the Z
- (separator) property. Xsp is the same as Xps; in PCRE1 it used to
- exclude vertical tab, for Perl compatibility, but Perl changed. Xwd
+ Xan matches characters that have either the L (letter) or the N (num-
+ ber) property. Xps matches the characters tab, linefeed, vertical tab,
+ form feed, or carriage return, and any other character that has the Z
+ (separator) property. Xsp is the same as Xps; in PCRE1 it used to ex-
+ clude vertical tab, for Perl compatibility, but Perl changed. Xwd
matches the same characters as Xan, plus underscore.
- There is another non-standard property, Xuc, which matches any charac-
- ter that can be represented by a Universal Character Name in C++ and
- other programming languages. These are the characters $, @, ` (grave
- accent), and all characters with Unicode code points greater than or
- equal to U+00A0, except for the surrogates U+D800 to U+DFFF. Note that
- most base (ASCII) characters are excluded. (Universal Character Names
- are of the form \uHHHH or \UHHHHHHHH where H is a hexadecimal digit.
+ There is another non-standard property, Xuc, which matches any charac-
+ ter that can be represented by a Universal Character Name in C++ and
+ other programming languages. These are the characters $, @, ` (grave
+ accent), and all characters with Unicode code points greater than or
+ equal to U+00A0, except for the surrogates U+D800 to U+DFFF. Note that
+ most base (ASCII) characters are excluded. (Universal Character Names
+ are of the form \uHHHH or \UHHHHHHHH where H is a hexadecimal digit.
Note that the Xuc property does not match these sequences but the char-
acters that they represent.)
Resetting the match start
- In normal use, the escape sequence \K causes any previously matched
- characters not to be included in the final matched sequence that is
- returned. For example, the pattern:
+ In normal use, the escape sequence \K causes any previously matched
+ characters not to be included in the final matched sequence that is re-
+ turned. For example, the pattern:
foo\Kbar
- matches "foobar", but reports that it has matched "bar". \K does not
+ matches "foobar", but reports that it has matched "bar". \K does not
interact with anchoring in any way. The pattern:
^foo\Kbar
- matches only when the subject begins with "foobar" (in single line
- mode), though it again reports the matched string as "bar". This fea-
- ture is similar to a lookbehind assertion (described below). However,
- in this case, the part of the subject before the real match does not
- have to be of fixed length, as lookbehind assertions do. The use of \K
- does not interfere with the setting of captured substrings. For exam-
+ matches only when the subject begins with "foobar" (in single line
+ mode), though it again reports the matched string as "bar". This fea-
+ ture is similar to a lookbehind assertion (described below). However,
+ in this case, the part of the subject before the real match does not
+ have to be of fixed length, as lookbehind assertions do. The use of \K
+ does not interfere with the setting of captured substrings. For exam-
ple, when the pattern
(foo)\Kbar
matches "foobar", the first substring is still set to "foo".
- Perl documents that the use of \K within assertions is "not well
- defined". In PCRE2, \K is acted upon when it occurs inside positive
- assertions, but is ignored in negative assertions. Note that when a
- pattern such as (?=ab\K) matches, the reported start of the match can
- be greater than the end of the match. Using \K in a lookbehind asser-
- tion at the start of a pattern can also lead to odd effects. For exam-
- ple, consider this pattern:
+ Perl documents that the use of \K within assertions is "not well de-
+ fined". In PCRE2, \K is acted upon when it occurs inside positive as-
+ sertions, but is ignored in negative assertions. Note that when a pat-
+ tern such as (?=ab\K) matches, the reported start of the match can be
+ greater than the end of the match. Using \K in a lookbehind assertion
+ at the start of a pattern can also lead to odd effects. For example,
+ consider this pattern:
(?<=\Kfoo)bar
- If the subject is "foobar", a call to pcre2_match() with a starting
- offset of 3 succeeds and reports the matching string as "foobar", that
- is, the start of the reported match is earlier than where the match
+ If the subject is "foobar", a call to pcre2_match() with a starting
+ offset of 3 succeeds and reports the matching string as "foobar", that
+ is, the start of the reported match is earlier than where the match
started.
Simple assertions
- The final use of backslash is for certain simple assertions. An asser-
- tion specifies a condition that has to be met at a particular point in
- a match, without consuming any characters from the subject string. The
- use of subpatterns for more complicated assertions is described below.
- The backslashed assertions are:
+ The final use of backslash is for certain simple assertions. An asser-
+ tion specifies a condition that has to be met at a particular point in
+ a match, without consuming any characters from the subject string. The
+ use of groups for more complicated assertions is described below. The
+ backslashed assertions are:
\b matches at a word boundary
\B matches when not at a word boundary
@@ -6786,19 +6973,20 @@ BACKSLASH
\z matches only at the end of the subject
\G matches at the first matching position in the subject
- Inside a character class, \b has a different meaning; it matches the
- backspace character. If any other of these assertions appears in a
+ Inside a character class, \b has a different meaning; it matches the
+ backspace character. If any other of these assertions appears in a
character class, an "invalid escape sequence" error is generated.
- A word boundary is a position in the subject string where the current
- character and the previous character do not both match \w or \W (i.e.
- one matches \w and the other matches \W), or the start or end of the
- string if the first or last character matches \w, respectively. In a
- UTF mode, the meanings of \w and \W can be changed by setting the
- PCRE2_UCP option. When this is done, it also affects \b and \B. Neither
- PCRE2 nor Perl has a separate "start of word" or "end of word" metase-
- quence. However, whatever follows \b normally determines which it is.
- For example, the fragment \ba matches "a" at the start of a word.
+ A word boundary is a position in the subject string where the current
+ character and the previous character do not both match \w or \W (i.e.
+ one matches \w and the other matches \W), or the start or end of the
+ string if the first or last character matches \w, respectively. When
+ PCRE2 is built with Unicode support, the meanings of \w and \W can be
+ changed by setting the PCRE2_UCP option. When this is done, it also af-
+ fects \b and \B. Neither PCRE2 nor Perl has a separate "start of word"
+ or "end of word" metasequence. However, whatever follows \b normally
+ determines which it is. For example, the fragment \ba matches "a" at
+ the start of a word.
The \A, \Z, and \z assertions differ from the traditional circumflex
and dollar (described in the next section) in that they only ever match
@@ -6846,8 +7034,8 @@ CIRCUMFLEX AND DOLLAR
point is at the start of the subject string. If the startoffset argu-
ment of pcre2_match() is non-zero, or if PCRE2_NOTBOL is set, circum-
flex can never match if the PCRE2_MULTILINE option is unset. Inside a
- character class, circumflex has an entirely different meaning (see
- below).
+ character class, circumflex has an entirely different meaning (see be-
+ low).
Circumflex need not be the first character of the pattern if a number
of alternatives are involved, but it should be the first thing in each
@@ -6858,11 +7046,11 @@ CIRCUMFLEX AND DOLLAR
constructs that can cause a pattern to be anchored.)
The dollar character is an assertion that is true only if the current
- matching point is at the end of the subject string, or immediately
- before a newline at the end of the string (by default), unless
- PCRE2_NOTEOL is set. Note, however, that it does not actually match the
- newline. Dollar need not be the last character of the pattern if a num-
- ber of alternatives are involved, but it should be the last item in any
+ matching point is at the end of the subject string, or immediately be-
+ fore a newline at the end of the string (by default), unless PCRE2_NO-
+ TEOL is set. Note, however, that it does not actually match the new-
+ line. Dollar need not be the last character of the pattern if a number
+ of alternatives are involved, but it should be the last item in any
branch in which it appears. Dollar has no special meaning in a charac-
ter class.
@@ -6945,11 +7133,11 @@ MATCHING A SINGLE CODE UNIT
Because \C breaks up characters into individual code units, matching
one unit with \C in UTF-8 or UTF-16 mode means that the rest of the
- string may start with a malformed UTF character. This has undefined
- results, because PCRE2 assumes that it is matching character by charac-
- ter in a valid UTF string (by default it checks the subject string's
- validity at the start of processing unless the PCRE2_NO_UTF_CHECK
- option is used).
+ string may start with a malformed UTF character. This has undefined re-
+ sults, because PCRE2 assumes that it is matching character by character
+ in a valid UTF string (by default it checks the subject string's valid-
+ ity at the start of processing unless the PCRE2_NO_UTF_CHECK or
+ PCRE2_MATCH_INVALID_UTF option is used).
An application can lock out the use of \C by setting the
PCRE2_NEVER_BACKSLASH_C option when compiling a pattern. It is also
@@ -6962,8 +7150,8 @@ MATCHING A SINGLE CODE UNIT
these UTF modes. The former gives a match-time error; the latter fails
to optimize and so the match is always run using the interpreter.
- In the 32-bit library, however, \C is always supported (when not
- explicitly locked out) because it always matches a single code unit,
+ In the 32-bit library, however, \C is always supported (when not ex-
+ plicitly locked out) because it always matches a single code unit,
whether or not UTF-32 is specified.
In general, the \C escape sequence is best avoided. However, one way of
@@ -6978,11 +7166,11 @@ MATCHING A SINGLE CODE UNIT
(?=[\x{10000}-\x{1fffff}])(\C)(\C)(\C)(\C))
In this example, a group that starts with (?| resets the capturing
- parentheses numbers in each alternative (see "Duplicate Subpattern Num-
- bers" below). The assertions at the start of each branch check the next
- UTF-8 character for values whose encoding uses 1, 2, 3, or 4 bytes,
- respectively. The character's individual bytes are then captured by the
- appropriate number of \C groups.
+ parentheses numbers in each alternative (see "Duplicate Group Numbers"
+ below). The assertions at the start of each branch check the next UTF-8
+ character for values whose encoding uses 1, 2, 3, or 4 bytes, respec-
+ tively. The character's individual bytes are then captured by the ap-
+ propriate number of \C groups.
SQUARE BRACKETS AND CHARACTER CLASSES
@@ -7019,93 +7207,92 @@ SQUARE BRACKETS AND CHARACTER CLASSES
would.
Characters that might indicate line breaks are never treated in any
- special way when matching character classes, whatever line-ending
- sequence is in use, and whatever setting of the PCRE2_DOTALL and
+ special way when matching character classes, whatever line-ending se-
+ quence is in use, and whatever setting of the PCRE2_DOTALL and
PCRE2_MULTILINE options is used. A class such as [^a] always matches
one of these characters.
The generic character type escape sequences \d, \D, \h, \H, \p, \P, \s,
\S, \v, \V, \w, and \W may appear in a character class, and add the
characters that they match to the class. For example, [\dABCDEF]
- matches any hexadecimal digit. In UTF modes, the PCRE2_UCP option
- affects the meanings of \d, \s, \w and their upper case partners, just
- as it does when they appear outside a character class, as described in
- the section entitled "Generic character types" above. The escape
- sequence \b has a different meaning inside a character class; it
- matches the backspace character. The sequences \B, \R, and \X are not
- special inside a character class. Like any other unrecognized escape
- sequences, they cause an error. The same is true for \N when not fol-
- lowed by an opening brace.
+ matches any hexadecimal digit. In UTF modes, the PCRE2_UCP option af-
+ fects the meanings of \d, \s, \w and their upper case partners, just as
+ it does when they appear outside a character class, as described in the
+ section entitled "Generic character types" above. The escape sequence
+ \b has a different meaning inside a character class; it matches the
+ backspace character. The sequences \B, \R, and \X are not special in-
+ side a character class. Like any other unrecognized escape sequences,
+ they cause an error. The same is true for \N when not followed by an
+ opening brace.
The minus (hyphen) character can be used to specify a range of charac-
- ters in a character class. For example, [d-m] matches any letter
- between d and m, inclusive. If a minus character is required in a
- class, it must be escaped with a backslash or appear in a position
- where it cannot be interpreted as indicating a range, typically as the
- first or last character in the class, or immediately after a range. For
- example, [b-d-z] matches letters in the range b to d, a hyphen charac-
- ter, or z.
+ ters in a character class. For example, [d-m] matches any letter be-
+ tween d and m, inclusive. If a minus character is required in a class,
+ it must be escaped with a backslash or appear in a position where it
+ cannot be interpreted as indicating a range, typically as the first or
+ last character in the class, or immediately after a range. For example,
+ [b-d-z] matches letters in the range b to d, a hyphen character, or z.
Perl treats a hyphen as a literal if it appears before or after a POSIX
class (see below) or before or after a character type escape such as as
- \d or \H. However, unless the hyphen is the last character in the
- class, Perl outputs a warning in its warning mode, as this is most
- likely a user error. As PCRE2 has no facility for warning, an error is
+ \d or \H. However, unless the hyphen is the last character in the
+ class, Perl outputs a warning in its warning mode, as this is most
+ likely a user error. As PCRE2 has no facility for warning, an error is
given in these cases.
It is not possible to have the literal character "]" as the end charac-
- ter of a range. A pattern such as [W-]46] is interpreted as a class of
- two characters ("W" and "-") followed by a literal string "46]", so it
- would match "W46]" or "-46]". However, if the "]" is escaped with a
- backslash it is interpreted as the end of range, so [W-\]46] is inter-
- preted as a class containing a range followed by two other characters.
- The octal or hexadecimal representation of "]" can also be used to end
+ ter of a range. A pattern such as [W-]46] is interpreted as a class of
+ two characters ("W" and "-") followed by a literal string "46]", so it
+ would match "W46]" or "-46]". However, if the "]" is escaped with a
+ backslash it is interpreted as the end of range, so [W-\]46] is inter-
+ preted as a class containing a range followed by two other characters.
+ The octal or hexadecimal representation of "]" can also be used to end
a range.
Ranges normally include all code points between the start and end char-
- acters, inclusive. They can also be used for code points specified
- numerically, for example [\000-\037]. Ranges can include any characters
- that are valid for the current mode. In any UTF mode, the so-called
- "surrogate" characters (those whose code points lie between 0xd800 and
- 0xdfff inclusive) may not be specified explicitly by default (the
- PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES option disables this check). How-
+ acters, inclusive. They can also be used for code points specified nu-
+ merically, for example [\000-\037]. Ranges can include any characters
+ that are valid for the current mode. In any UTF mode, the so-called
+ "surrogate" characters (those whose code points lie between 0xd800 and
+ 0xdfff inclusive) may not be specified explicitly by default (the
+ PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES option disables this check). How-
ever, ranges such as [\x{d7ff}-\x{e000}], which include the surrogates,
are always permitted.
- There is a special case in EBCDIC environments for ranges whose end
+ There is a special case in EBCDIC environments for ranges whose end
points are both specified as literal letters in the same case. For com-
- patibility with Perl, EBCDIC code points within the range that are not
- letters are omitted. For example, [h-k] matches only four characters,
+ patibility with Perl, EBCDIC code points within the range that are not
+ letters are omitted. For example, [h-k] matches only four characters,
even though the codes for h and k are 0x88 and 0x92, a range of 11 code
- points. However, if the range is specified numerically, for example,
+ points. However, if the range is specified numerically, for example,
[\x88-\x92] or [h-\x92], all code points are included.
If a range that includes letters is used when caseless matching is set,
it matches the letters in either case. For example, [W-c] is equivalent
- to [][\\^_`wxyzabc], matched caselessly, and in a non-UTF mode, if
- character tables for a French locale are in use, [\xc8-\xcb] matches
+ to [][\\^_`wxyzabc], matched caselessly, and in a non-UTF mode, if
+ character tables for a French locale are in use, [\xc8-\xcb] matches
accented E characters in both cases.
- A circumflex can conveniently be used with the upper case character
- types to specify a more restricted set of characters than the matching
- lower case type. For example, the class [^\W_] matches any letter or
+ A circumflex can conveniently be used with the upper case character
+ types to specify a more restricted set of characters than the matching
+ lower case type. For example, the class [^\W_] matches any letter or
digit, but not underscore, whereas [\w] includes underscore. A positive
character class should be read as "something OR something OR ..." and a
negative class as "NOT something AND NOT something AND NOT ...".
- The only metacharacters that are recognized in character classes are
- backslash, hyphen (only where it can be interpreted as specifying a
- range), circumflex (only at the start), opening square bracket (only
- when it can be interpreted as introducing a POSIX class name, or for a
- special compatibility feature - see the next two sections), and the
- terminating closing square bracket. However, escaping other non-
- alphanumeric characters does no harm.
+ The only metacharacters that are recognized in character classes are
+ backslash, hyphen (only where it can be interpreted as specifying a
+ range), circumflex (only at the start), opening square bracket (only
+ when it can be interpreted as introducing a POSIX class name, or for a
+ special compatibility feature - see the next two sections), and the
+ terminating closing square bracket. However, escaping other non-al-
+ phanumeric characters does no harm.
POSIX CHARACTER CLASSES
Perl supports the POSIX notation for character classes. This uses names
- enclosed by [: and :] within the enclosing square brackets. PCRE2 also
+ enclosed by [: and :] within the enclosing square brackets. PCRE2 also
supports this notation. For example,
[01[:alpha:]%]
@@ -7128,13 +7315,13 @@ POSIX CHARACTER CLASSES
word "word" characters (same as \w)
xdigit hexadecimal digits
- The default "space" characters are HT (9), LF (10), VT (11), FF (12),
- CR (13), and space (32). If locale-specific matching is taking place,
- the list of space characters may be different; there may be fewer or
+ The default "space" characters are HT (9), LF (10), VT (11), FF (12),
+ CR (13), and space (32). If locale-specific matching is taking place,
+ the list of space characters may be different; there may be fewer or
more of them. "Space" and \s match the same set of characters.
- The name "word" is a Perl extension, and "blank" is a GNU extension
- from Perl 5.8. Another Perl extension is negation, which is indicated
+ The name "word" is a Perl extension, and "blank" is a GNU extension
+ from Perl 5.8. Another Perl extension is negation, which is indicated
by a ^ character after the colon. For example,
[12[:^digit:]]
@@ -7145,11 +7332,11 @@ POSIX CHARACTER CLASSES
By default, characters with values greater than 127 do not match any of
the POSIX character classes, although this may be different for charac-
- ters in the range 128-255 when locale-specific matching is happening.
- However, if the PCRE2_UCP option is passed to pcre2_compile(), some of
- the classes are changed so that Unicode character properties are used.
- This is achieved by replacing certain POSIX classes with other
- sequences, as follows:
+ ters in the range 128-255 when locale-specific matching is happening.
+ However, if the PCRE2_UCP option is passed to pcre2_compile(), some of
+ the classes are changed so that Unicode character properties are used.
+ This is achieved by replacing certain POSIX classes with other se-
+ quences, as follows:
[:alnum:] becomes \p{Xan}
[:alpha:] becomes \p{L}
@@ -7161,10 +7348,10 @@ POSIX CHARACTER CLASSES
[:upper:] becomes \p{Lu}
[:word:] becomes \p{Xwd}
- Negated versions, such as [:^alpha:] use \P instead of \p. Three other
+ Negated versions, such as [:^alpha:] use \P instead of \p. Three other
POSIX classes are handled specially in UCP mode:
- [:graph:] This matches characters that have glyphs that mark the page
+ [:graph:] This matches characters that have glyphs that mark the page
when printed. In Unicode property terms, it matches all char-
acters with the L, M, N, P, S, or Cf properties, except for:
@@ -7173,60 +7360,60 @@ POSIX CHARACTER CLASSES
U+2066 - U+2069 Various "isolate"s
- [:print:] This matches the same characters as [:graph:] plus space
- characters that are not controls, that is, characters with
+ [:print:] This matches the same characters as [:graph:] plus space
+ characters that are not controls, that is, characters with
the Zs property.
[:punct:] This matches all characters that have the Unicode P (punctua-
- tion) property, plus those characters with code points less
+ tion) property, plus those characters with code points less
than 256 that have the S (Symbol) property.
- The other POSIX classes are unchanged, and match only characters with
+ The other POSIX classes are unchanged, and match only characters with
code points less than 256.
COMPATIBILITY FEATURE FOR WORD BOUNDARIES
- In the POSIX.2 compliant library that was included in 4.4BSD Unix, the
- ugly syntax [[:<:]] and [[:>:]] is used for matching "start of word"
+ In the POSIX.2 compliant library that was included in 4.4BSD Unix, the
+ ugly syntax [[:<:]] and [[:>:]] is used for matching "start of word"
and "end of word". PCRE2 treats these items as follows:
[[:<:]] is converted to \b(?=\w)
[[:>:]] is converted to \b(?<=\w)
Only these exact character sequences are recognized. A sequence such as
- [a[:<:]b] provokes error for an unrecognized POSIX class name. This
- support is not compatible with Perl. It is provided to help migrations
+ [a[:<:]b] provokes error for an unrecognized POSIX class name. This
+ support is not compatible with Perl. It is provided to help migrations
from other environments, and is best not used in any new patterns. Note
- that \b matches at the start and the end of a word (see "Simple asser-
- tions" above), and in a Perl-style pattern the preceding or following
- character normally shows which is wanted, without the need for the
- assertions that are used above in order to give exactly the POSIX be-
- haviour.
+ that \b matches at the start and the end of a word (see "Simple asser-
+ tions" above), and in a Perl-style pattern the preceding or following
+ character normally shows which is wanted, without the need for the as-
+ sertions that are used above in order to give exactly the POSIX behav-
+ iour.
VERTICAL BAR
- Vertical bar characters are used to separate alternative patterns. For
+ Vertical bar characters are used to separate alternative patterns. For
example, the pattern
gilbert|sullivan
- matches either "gilbert" or "sullivan". Any number of alternatives may
- appear, and an empty alternative is permitted (matching the empty
+ matches either "gilbert" or "sullivan". Any number of alternatives may
+ appear, and an empty alternative is permitted (matching the empty
string). The matching process tries each alternative in turn, from left
- to right, and the first one that succeeds is used. If the alternatives
- are within a subpattern (defined below), "succeeds" means matching the
- rest of the main pattern as well as the alternative in the subpattern.
+ to right, and the first one that succeeds is used. If the alternatives
+ are within a group (defined below), "succeeds" means matching the rest
+ of the main pattern as well as the alternative in the group.
INTERNAL OPTION SETTING
- The settings of the PCRE2_CASELESS, PCRE2_MULTILINE, PCRE2_DOTALL,
- PCRE2_EXTENDED, PCRE2_EXTENDED_MORE, and PCRE2_NO_AUTO_CAPTURE options
- can be changed from within the pattern by a sequence of letters
- enclosed between "(?" and ")". These options are Perl-compatible, and
- are described in detail in the pcre2api documentation. The option let-
+ The settings of the PCRE2_CASELESS, PCRE2_MULTILINE, PCRE2_DOTALL,
+ PCRE2_EXTENDED, PCRE2_EXTENDED_MORE, and PCRE2_NO_AUTO_CAPTURE options
+ can be changed from within the pattern by a sequence of letters en-
+ closed between "(?" and ")". These options are Perl-compatible, and
+ are described in detail in the pcre2api documentation. The option let-
ters are:
i for PCRE2_CASELESS
@@ -7237,72 +7424,73 @@ INTERNAL OPTION SETTING
xx for PCRE2_EXTENDED_MORE
For example, (?im) sets caseless, multiline matching. It is also possi-
- ble to unset these options by preceding the relevant letters with a
- hyphen, for example (?-im). The two "extended" options are not indepen-
+ ble to unset these options by preceding the relevant letters with a hy-
+ phen, for example (?-im). The two "extended" options are not indepen-
dent; unsetting either one cancels the effects of both of them.
- A combined setting and unsetting such as (?im-sx), which sets
- PCRE2_CASELESS and PCRE2_MULTILINE while unsetting PCRE2_DOTALL and
- PCRE2_EXTENDED, is also permitted. Only one hyphen may appear in the
- options string. If a letter appears both before and after the hyphen,
- the option is unset. An empty options setting "(?)" is allowed. Need-
+ A combined setting and unsetting such as (?im-sx), which sets
+ PCRE2_CASELESS and PCRE2_MULTILINE while unsetting PCRE2_DOTALL and
+ PCRE2_EXTENDED, is also permitted. Only one hyphen may appear in the
+ options string. If a letter appears both before and after the hyphen,
+ the option is unset. An empty options setting "(?)" is allowed. Need-
less to say, it has no effect.
- If the first character following (? is a circumflex, it causes all of
- the above options to be unset. Thus, (?^) is equivalent to (?-imnsx).
- Letters may follow the circumflex to cause some options to be re-
- instated, but a hyphen may not appear.
+ If the first character following (? is a circumflex, it causes all of
+ the above options to be unset. Thus, (?^) is equivalent to (?-imnsx).
+ Letters may follow the circumflex to cause some options to be re-in-
+ stated, but a hyphen may not appear.
- The PCRE2-specific options PCRE2_DUPNAMES and PCRE2_UNGREEDY can be
- changed in the same way as the Perl-compatible options by using the
+ The PCRE2-specific options PCRE2_DUPNAMES and PCRE2_UNGREEDY can be
+ changed in the same way as the Perl-compatible options by using the
characters J and U respectively. However, these are not unset by (?^).
- When one of these option changes occurs at top level (that is, not
- inside subpattern parentheses), the change applies to the remainder of
- the pattern that follows. An option change within a subpattern (see
- below for a description of subpatterns) affects only that part of the
- subpattern that follows it, so
+ When one of these option changes occurs at top level (that is, not in-
+ side group parentheses), the change applies to the remainder of the
+ pattern that follows. An option change within a group (see below for a
+ description of groups) affects only that part of the group that follows
+ it, so
(a(?i)b)c
- matches abc and aBc and no other strings (assuming PCRE2_CASELESS is
- not used). By this means, options can be made to have different set-
+ matches abc and aBc and no other strings (assuming PCRE2_CASELESS is
+ not used). By this means, options can be made to have different set-
tings in different parts of the pattern. Any changes made in one alter-
- native do carry on into subsequent branches within the same subpattern.
- For example,
+ native do carry on into subsequent branches within the same group. For
+ example,
(a(?i)b|c)
- matches "ab", "aB", "c", and "C", even though when matching "C" the
- first branch is abandoned before the option setting. This is because
- the effects of option settings happen at compile time. There would be
+ matches "ab", "aB", "c", and "C", even though when matching "C" the
+ first branch is abandoned before the option setting. This is because
+ the effects of option settings happen at compile time. There would be
some very weird behaviour otherwise.
- As a convenient shorthand, if any option settings are required at the
- start of a non-capturing subpattern (see the next section), the option
- letters may appear between the "?" and the ":". Thus the two patterns
+ As a convenient shorthand, if any option settings are required at the
+ start of a non-capturing group (see the next section), the option let-
+ ters may appear between the "?" and the ":". Thus the two patterns
(?i:saturday|sunday)
(?:(?i)saturday|sunday)
match exactly the same set of strings.
- Note: There are other PCRE2-specific options that can be set by the
- application when the compiling function is called. The pattern can con-
- tain special leading sequences such as (*CRLF) to override what the
- application has set or what has been defaulted. Details are given in
- the section entitled "Newline sequences" above. There are also the
- (*UTF) and (*UCP) leading sequences that can be used to set UTF and
- Unicode property modes; they are equivalent to setting the PCRE2_UTF
- and PCRE2_UCP options, respectively. However, the application can set
- the PCRE2_NEVER_UTF and PCRE2_NEVER_UCP options, which lock out the use
- of the (*UTF) and (*UCP) sequences.
+ Note: There are other PCRE2-specific options, applying to the whole
+ pattern, which can be set by the application when the compiling func-
+ tion is called. In addition, the pattern can contain special leading
+ sequences such as (*CRLF) to override what the application has set or
+ what has been defaulted. Details are given in the section entitled
+ "Newline sequences" above. There are also the (*UTF) and (*UCP) leading
+ sequences that can be used to set UTF and Unicode property modes; they
+ are equivalent to setting the PCRE2_UTF and PCRE2_UCP options, respec-
+ tively. However, the application can set the PCRE2_NEVER_UTF and
+ PCRE2_NEVER_UCP options, which lock out the use of the (*UTF) and
+ (*UCP) sequences.
-SUBPATTERNS
+GROUPS
- Subpatterns are delimited by parentheses (round brackets), which can be
- nested. Turning part of a pattern into a subpattern does two things:
+ Groups are delimited by parentheses (round brackets), which can be
+ nested. Turning part of a pattern into a group does two things:
1. It localizes a set of alternatives. For example, the pattern
@@ -7311,55 +7499,53 @@ SUBPATTERNS
matches "cataract", "caterpillar", or "cat". Without the parentheses,
it would match "cataract", "erpillar" or an empty string.
- 2. It sets up the subpattern as a capturing subpattern. This means
- that, when the whole pattern matches, the portion of the subject string
- that matched the subpattern is passed back to the caller, separately
- from the portion that matched the whole pattern. (This applies only to
- the traditional matching function; the DFA matching function does not
- support capturing.)
+ 2. It creates a "capture group". This means that, when the whole pat-
+ tern matches, the portion of the subject string that matched the group
+ is passed back to the caller, separately from the portion that matched
+ the whole pattern. (This applies only to the traditional matching
+ function; the DFA matching function does not support capturing.)
Opening parentheses are counted from left to right (starting from 1) to
- obtain numbers for the capturing subpatterns. For example, if the
- string "the red king" is matched against the pattern
+ obtain numbers for capture groups. For example, if the string "the red
+ king" is matched against the pattern
the ((red|white) (king|queen))
the captured substrings are "red king", "red", and "king", and are num-
bered 1, 2, and 3, respectively.
- The fact that plain parentheses fulfil two functions is not always
- helpful. There are often times when a grouping subpattern is required
- without a capturing requirement. If an opening parenthesis is followed
- by a question mark and a colon, the subpattern does not do any captur-
- ing, and is not counted when computing the number of any subsequent
- capturing subpatterns. For example, if the string "the white queen" is
- matched against the pattern
+ The fact that plain parentheses fulfil two functions is not always
+ helpful. There are often times when grouping is required without cap-
+ turing. If an opening parenthesis is followed by a question mark and a
+ colon, the group does not do any capturing, and is not counted when
+ computing the number of any subsequent capture groups. For example, if
+ the string "the white queen" is matched against the pattern
the ((?:red|white) (king|queen))
the captured substrings are "white queen" and "queen", and are numbered
- 1 and 2. The maximum number of capturing subpatterns is 65535.
+ 1 and 2. The maximum number of capture groups is 65535.
As a convenient shorthand, if any option settings are required at the
- start of a non-capturing subpattern, the option letters may appear
- between the "?" and the ":". Thus the two patterns
+ start of a non-capturing group, the option letters may appear between
+ the "?" and the ":". Thus the two patterns
(?i:saturday|sunday)
(?:(?i)saturday|sunday)
match exactly the same set of strings. Because alternative branches are
tried from left to right, and options are not reset until the end of
- the subpattern is reached, an option setting in one branch does affect
- subsequent branches, so the above patterns match "SUNDAY" as well as
- "Saturday".
+ the group is reached, an option setting in one branch does affect sub-
+ sequent branches, so the above patterns match "SUNDAY" as well as "Sat-
+ urday".
-DUPLICATE SUBPATTERN NUMBERS
+DUPLICATE GROUP NUMBERS
- Perl 5.10 introduced a feature whereby each alternative in a subpattern
- uses the same numbers for its capturing parentheses. Such a subpattern
- starts with (?| and is itself a non-capturing subpattern. For example,
- consider this pattern:
+ Perl 5.10 introduced a feature whereby each alternative in a group uses
+ the same numbers for its capturing parentheses. Such a group starts
+ with (?| and is itself a non-capturing group. For example, consider
+ this pattern:
(?|(Sat)ur|(Sun))day
@@ -7370,7 +7556,7 @@ DUPLICATE SUBPATTERN NUMBERS
not all, of one of a number of alternatives. Inside a (?| group, paren-
theses are numbered as usual, but the number is reset at the start of
each branch. The numbers of any capturing parentheses that follow the
- subpattern start after the highest number used in any branch. The fol-
+ whole group start after the highest number used in any branch. The fol-
lowing example is taken from the Perl documentation. The numbers under-
neath show in which buffer the captured content will be stored.
@@ -7378,90 +7564,94 @@ DUPLICATE SUBPATTERN NUMBERS
/ ( a ) (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x
# 1 2 2 3 2 3 4
- A backreference to a numbered subpattern uses the most recent value
- that is set for that number by any subpattern. The following pattern
- matches "abcabc" or "defdef":
+ A backreference to a capture group uses the most recent value that is
+ set for the group. The following pattern matches "abcabc" or "defdef":
/(?|(abc)|(def))\1/
- In contrast, a subroutine call to a numbered subpattern always refers
- to the first one in the pattern with the given number. The following
- pattern matches "abcabc" or "defabc":
+ In contrast, a subroutine call to a capture group always refers to the
+ first one in the pattern with the given number. The following pattern
+ matches "abcabc" or "defabc":
/(?|(abc)|(def))(?1)/
A relative reference such as (?-1) is no different: it is just a conve-
nient way of computing an absolute group number.
- If a condition test for a subpattern's having matched refers to a non-
- unique number, the test is true if any of the subpatterns of that num-
- ber have matched.
+ If a condition test for a group's having matched refers to a non-unique
+ number, the test is true if any group with that number has matched.
An alternative approach to using this "branch reset" feature is to use
- duplicate named subpatterns, as described in the next section.
+ duplicate named groups, as described in the next section.
-NAMED SUBPATTERNS
+NAMED CAPTURE GROUPS
- Identifying capturing parentheses by number is simple, but it can be
- very hard to keep track of the numbers in complicated patterns. Fur-
- thermore, if an expression is modified, the numbers may change. To help
- with this difficulty, PCRE2 supports the naming of capturing subpat-
- terns. This feature was not added to Perl until release 5.10. Python
- had the feature earlier, and PCRE1 introduced it at release 4.0, using
- the Python syntax. PCRE2 supports both the Perl and the Python syntax.
+ Identifying capture groups by number is simple, but it can be very hard
+ to keep track of the numbers in complicated patterns. Furthermore, if
+ an expression is modified, the numbers may change. To help with this
+ difficulty, PCRE2 supports the naming of capture groups. This feature
+ was not added to Perl until release 5.10. Python had the feature ear-
+ lier, and PCRE1 introduced it at release 4.0, using the Python syntax.
+ PCRE2 supports both the Perl and the Python syntax.
- In PCRE2, a capturing subpattern can be named in one of three ways:
+ In PCRE2, a capture group can be named in one of three ways:
(?...) or (?'name'...) as in Perl, or (?P...) as in Python.
- Names consist of up to 32 alphanumeric characters and underscores, but
- must start with a non-digit. References to capturing parentheses from
- other parts of the pattern, such as backreferences, recursion, and con-
- ditions, can all be made by name as well as by number.
-
- Named capturing parentheses are allocated numbers as well as names,
- exactly as if the names were not present. In both PCRE2 and Perl, cap-
- turing subpatterns are primarily identified by numbers; any names are
- just aliases for these numbers. The PCRE2 API provides function calls
- for extracting the complete name-to-number translation table from a
- compiled pattern, as well as convenience functions for extracting cap-
- tured substrings by name.
-
- Warning: When more than one subpattern has the same number, as
- described in the previous section, a name given to one of them applies
- to all of them. Perl allows identically numbered subpatterns to have
- different names. Consider this pattern, where there are two capturing
- subpatterns, both numbered 1:
+ Names may be up to 32 code units long. When PCRE2_UTF is not set, they
+ may contain only ASCII alphanumeric characters and underscores, but
+ must start with a non-digit. When PCRE2_UTF is set, the syntax of group
+ names is extended to allow any Unicode letter or Unicode decimal digit.
+ In other words, group names must match one of these patterns:
+
+ ^[_A-Za-z][_A-Za-z0-9]*\z when PCRE2_UTF is not set
+ ^[_\p{L}][_\p{L}\p{Nd}]*\z when PCRE2_UTF is set
+
+ References to capture groups from other parts of the pattern, such as
+ backreferences, recursion, and conditions, can all be made by name as
+ well as by number.
+
+ Named capture groups are allocated numbers as well as names, exactly as
+ if the names were not present. In both PCRE2 and Perl, capture groups
+ are primarily identified by numbers; any names are just aliases for
+ these numbers. The PCRE2 API provides function calls for extracting the
+ complete name-to-number translation table from a compiled pattern, as
+ well as convenience functions for extracting captured substrings by
+ name.
+
+ Warning: When more than one capture group has the same number, as de-
+ scribed in the previous section, a name given to one of them applies to
+ all of them. Perl allows identically numbered groups to have different
+ names. Consider this pattern, where there are two capture groups, both
+ numbered 1:
(?|(?aa)|(?bb))
- Perl allows this, with both names AA and BB as aliases of group 1.
+ Perl allows this, with both names AA and BB as aliases of group 1.
Thus, after a successful match, both names yield the same value (either
"aa" or "bb").
- In an attempt to reduce confusion, PCRE2 does not allow the same group
+ In an attempt to reduce confusion, PCRE2 does not allow the same group
number to be associated with more than one name. The example above pro-
- vokes a compile-time error. However, there is still scope for confu-
+ vokes a compile-time error. However, there is still scope for confu-
sion. Consider this pattern:
(?|(?aa)|(bb))
- Although the second subpattern number 1 is not explicitly named, the
- name AA is still an alias for subpattern 1. Whether the pattern matches
- "aa" or "bb", a reference by name to group AA yields the matched
- string.
+ Although the second group number 1 is not explicitly named, the name AA
+ is still an alias for any group 1. Whether the pattern matches "aa" or
+ "bb", a reference by name to group AA yields the matched string.
By default, a name must be unique within a pattern, except that dupli-
- cate names are permitted for subpatterns with the same number, for
- example:
+ cate names are permitted for groups with the same number, for example:
(?|(?aa)|(?bb))
The duplicate name constraint can be disabled by setting the PCRE2_DUP-
NAMES option at compile time, or by the use of (?J) within the pattern.
- Duplicate names can be useful for patterns where only one instance of
- the named parentheses can match. Suppose you want to match the name of
- a weekday, either as a 3-letter abbreviation or as the full name, and
- in both cases you want to extract the abbreviation. This pattern
+ Duplicate names can be useful for patterns where only one instance of
+ the named capture group can match. Suppose you want to match the name
+ of a weekday, either as a 3-letter abbreviation or as the full name,
+ and in both cases you want to extract the abbreviation. This pattern
(ignoring the line breaks) does the job:
(?Mon|Fri|Sun)(?:day)?|
@@ -7470,33 +7660,32 @@ NAMED SUBPATTERNS
(?Thu)(?:rsday)?|
(?Sat)(?:urday)?
- There are five capturing substrings, but only one is ever set after a
- match. The convenience functions for extracting the data by name
- returns the substring for the first (and in this example, the only)
- subpattern of that name that matched. This saves searching to find
- which numbered subpattern it was. (An alternative way of solving this
- problem is to use a "branch reset" subpattern, as described in the pre-
- vious section.)
+ There are five capture groups, but only one is ever set after a match.
+ The convenience functions for extracting the data by name returns the
+ substring for the first (and in this example, the only) group of that
+ name that matched. This saves searching to find which numbered group it
+ was. (An alternative way of solving this problem is to use a "branch
+ reset" group, as described in the previous section.)
- If you make a backreference to a non-unique named subpattern from else-
- where in the pattern, the subpatterns to which the name refers are
- checked in the order in which they appear in the overall pattern. The
- first one that is set is used for the reference. For example, this pat-
- tern matches both "foofoo" and "barbar" but not "foobar" or "barfoo":
+ If you make a backreference to a non-unique named group from elsewhere
+ in the pattern, the groups to which the name refers are checked in the
+ order in which they appear in the overall pattern. The first one that
+ is set is used for the reference. For example, this pattern matches
+ both "foofoo" and "barbar" but not "foobar" or "barfoo":
(?:(?foo)|(?bar))\k
- If you make a subroutine call to a non-unique named subpattern, the one
- that corresponds to the first occurrence of the name is used. In the
- absence of duplicate numbers this is the one with the lowest number.
+ If you make a subroutine call to a non-unique named group, the one that
+ corresponds to the first occurrence of the name is used. In the absence
+ of duplicate numbers this is the one with the lowest number.
If you use a named reference in a condition test (see the section about
- conditions below), either to check whether a subpattern has matched, or
- to check for recursion, all subpatterns with the same name are tested.
- If the condition is true for any one of them, the overall condition is
- true. This is the same behaviour as testing by number. For further
- details of the interfaces for handling named subpatterns, see the
+ conditions below), either to check whether a capture group has matched,
+ or to check for recursion, all groups with the same name are tested. If
+ the condition is true for any one of them, the overall condition is
+ true. This is the same behaviour as testing by number. For further de-
+ tails of the interfaces for handling named capture groups, see the
pcre2api documentation.
@@ -7508,18 +7697,18 @@ REPETITION
a literal data character
the dot metacharacter
the \C escape sequence
- the \X escape sequence
the \R escape sequence
+ the \X escape sequence
an escape such as \d or \pL that matches a single character
a character class
a backreference
- a parenthesized subpattern (including most assertions)
- a subroutine call to a subpattern (recursive or otherwise)
+ a parenthesized group (including most assertions)
+ a subroutine call (recursive or otherwise)
The general repetition quantifier specifies a minimum and maximum num-
ber of permitted matches, by giving the two numbers in curly brackets
(braces), separated by a comma. The numbers must be less than 65536,
- and the first must be less than or equal to the second. For example:
+ and the first must be less than or equal to the second. For example,
z{2,4}
@@ -7549,37 +7738,40 @@ REPETITION
The quantifier {0} is permitted, causing the expression to behave as if
the previous item and the quantifier were not present. This may be use-
- ful for subpatterns that are referenced as subroutines from elsewhere
- in the pattern (but see also the section entitled "Defining subpatterns
- for use by reference only" below). Items other than subpatterns that
- have a {0} quantifier are omitted from the compiled pattern.
+ ful for capture groups that are referenced as subroutines from else-
+ where in the pattern (but see also the section entitled "Defining cap-
+ ture groups for use by reference only" below). Except for parenthesized
+ groups, items that have a {0} quantifier are omitted from the compiled
+ pattern.
- For convenience, the three most common quantifiers have single-charac-
+ For convenience, the three most common quantifiers have single-charac-
ter abbreviations:
* is equivalent to {0,}
+ is equivalent to {1,}
? is equivalent to {0,1}
- It is possible to construct infinite loops by following a subpattern
- that can match no characters with a quantifier that has no upper limit,
- for example:
+ It is possible to construct infinite loops by following a group that
+ can match no characters with a quantifier that has no upper limit, for
+ example:
(a?)*
- Earlier versions of Perl and PCRE1 used to give an error at compile
+ Earlier versions of Perl and PCRE1 used to give an error at compile
time for such patterns. However, because there are cases where this can
- be useful, such patterns are now accepted, but if any repetition of the
- subpattern does in fact match no characters, the loop is forcibly bro-
- ken.
-
- By default, the quantifiers are "greedy", that is, they match as much
- as possible (up to the maximum number of permitted times), without
- causing the rest of the pattern to fail. The classic example of where
- this gives problems is in trying to match comments in C programs. These
- appear between /* and */ and within the comment, individual * and /
- characters may appear. An attempt to match C comments by applying the
- pattern
+ be useful, such patterns are now accepted, but whenever an iteration of
+ such a group matches no characters, matching moves on to the next item
+ in the pattern instead of repeatedly matching an empty string. This
+ does not prevent backtracking into any of the iterations if a subse-
+ quent item fails to match.
+
+ By default, quantifiers are "greedy", that is, they match as much as
+ possible (up to the maximum number of permitted times), without causing
+ the rest of the pattern to fail. The classic example of where this
+ gives problems is in trying to match comments in C programs. These ap-
+ pear between /* and */ and within the comment, individual * and / char-
+ acters may appear. An attempt to match C comments by applying the pat-
+ tern
/\*.*\*/
@@ -7587,19 +7779,17 @@ REPETITION
/* first comment */ not comment /* second comment */
- fails, because it matches the entire string owing to the greediness of
- the .* item.
-
- If a quantifier is followed by a question mark, it ceases to be greedy,
- and instead matches the minimum number of times possible, so the pat-
- tern
+ fails, because it matches the entire string owing to the greediness of
+ the .* item. However, if a quantifier is followed by a question mark,
+ it ceases to be greedy, and instead matches the minimum number of times
+ possible, so the pattern
/\*.*?\*/
- does the right thing with the C comments. The meaning of the various
- quantifiers is not otherwise changed, just the preferred number of
- matches. Do not confuse this use of question mark with its use as a
- quantifier in its own right. Because it has two uses, it can sometimes
+ does the right thing with the C comments. The meaning of the various
+ quantifiers is not otherwise changed, just the preferred number of
+ matches. Do not confuse this use of question mark with its use as a
+ quantifier in its own right. Because it has two uses, it can sometimes
appear doubled, as in
\d??\d
@@ -7608,56 +7798,56 @@ REPETITION
only way the rest of the pattern matches.
If the PCRE2_UNGREEDY option is set (an option that is not available in
- Perl), the quantifiers are not greedy by default, but individual ones
- can be made greedy by following them with a question mark. In other
+ Perl), the quantifiers are not greedy by default, but individual ones
+ can be made greedy by following them with a question mark. In other
words, it inverts the default behaviour.
- When a parenthesized subpattern is quantified with a minimum repeat
- count that is greater than 1 or with a limited maximum, more memory is
- required for the compiled pattern, in proportion to the size of the
- minimum or maximum.
-
- If a pattern starts with .* or .{0,} and the PCRE2_DOTALL option
- (equivalent to Perl's /s) is set, thus allowing the dot to match new-
- lines, the pattern is implicitly anchored, because whatever follows
- will be tried against every character position in the subject string,
- so there is no point in retrying the overall match at any position
- after the first. PCRE2 normally treats such a pattern as though it were
+ When a parenthesized group is quantified with a minimum repeat count
+ that is greater than 1 or with a limited maximum, more memory is re-
+ quired for the compiled pattern, in proportion to the size of the mini-
+ mum or maximum.
+
+ If a pattern starts with .* or .{0,} and the PCRE2_DOTALL option
+ (equivalent to Perl's /s) is set, thus allowing the dot to match new-
+ lines, the pattern is implicitly anchored, because whatever follows
+ will be tried against every character position in the subject string,
+ so there is no point in retrying the overall match at any position af-
+ ter the first. PCRE2 normally treats such a pattern as though it were
preceded by \A.
- In cases where it is known that the subject string contains no new-
- lines, it is worth setting PCRE2_DOTALL in order to obtain this opti-
+ In cases where it is known that the subject string contains no new-
+ lines, it is worth setting PCRE2_DOTALL in order to obtain this opti-
mization, or alternatively, using ^ to indicate anchoring explicitly.
- However, there are some cases where the optimization cannot be used.
- When .* is inside capturing parentheses that are the subject of a
- backreference elsewhere in the pattern, a match at the start may fail
+ However, there are some cases where the optimization cannot be used.
+ When .* is inside capturing parentheses that are the subject of a
+ backreference elsewhere in the pattern, a match at the start may fail
where a later one succeeds. Consider, for example:
(.*)abc\1
- If the subject is "xyz123abc123" the match point is the fourth charac-
+ If the subject is "xyz123abc123" the match point is the fourth charac-
ter. For this reason, such a pattern is not implicitly anchored.
- Another case where implicit anchoring is not applied is when the lead-
- ing .* is inside an atomic group. Once again, a match at the start may
+ Another case where implicit anchoring is not applied is when the lead-
+ ing .* is inside an atomic group. Once again, a match at the start may
fail where a later one succeeds. Consider this pattern:
(?>.*?a)b
- It matches "ab" in the subject "aab". The use of the backtracking con-
- trol verbs (*PRUNE) and (*SKIP) also disable this optimization, and
+ It matches "ab" in the subject "aab". The use of the backtracking con-
+ trol verbs (*PRUNE) and (*SKIP) also disable this optimization, and
there is an option, PCRE2_NO_DOTSTAR_ANCHOR, to do so explicitly.
- When a capturing subpattern is repeated, the value captured is the sub-
- string that matched the final iteration. For example, after
+ When a capture group is repeated, the value captured is the substring
+ that matched the final iteration. For example, after
(tweedle[dume]{3}\s*)+
has matched "tweedledum tweedledee" the value of the captured substring
- is "tweedledee". However, if there are nested capturing subpatterns,
- the corresponding captured values may have been set in previous itera-
- tions. For example, after
+ is "tweedledee". However, if there are nested capture groups, the cor-
+ responding captured values may have been set in previous iterations.
+ For example, after
(a|(b))+
@@ -7666,54 +7856,58 @@ REPETITION
ATOMIC GROUPING AND POSSESSIVE QUANTIFIERS
- With both maximizing ("greedy") and minimizing ("ungreedy" or "lazy")
- repetition, failure of what follows normally causes the repeated item
- to be re-evaluated to see if a different number of repeats allows the
- rest of the pattern to match. Sometimes it is useful to prevent this,
- either to change the nature of the match, or to cause it fail earlier
- than it otherwise might, when the author of the pattern knows there is
+ With both maximizing ("greedy") and minimizing ("ungreedy" or "lazy")
+ repetition, failure of what follows normally causes the repeated item
+ to be re-evaluated to see if a different number of repeats allows the
+ rest of the pattern to match. Sometimes it is useful to prevent this,
+ either to change the nature of the match, or to cause it fail earlier
+ than it otherwise might, when the author of the pattern knows there is
no point in carrying on.
- Consider, for example, the pattern \d+foo when applied to the subject
+ Consider, for example, the pattern \d+foo when applied to the subject
line
123456bar
After matching all 6 digits and then failing to match "foo", the normal
- action of the matcher is to try again with only 5 digits matching the
- \d+ item, and then with 4, and so on, before ultimately failing.
- "Atomic grouping" (a term taken from Jeffrey Friedl's book) provides
- the means for specifying that once a subpattern has matched, it is not
- to be re-evaluated in this way.
-
- If we use atomic grouping for the previous example, the matcher gives
- up immediately on failing to match "foo" the first time. The notation
+ action of the matcher is to try again with only 5 digits matching the
+ \d+ item, and then with 4, and so on, before ultimately failing.
+ "Atomic grouping" (a term taken from Jeffrey Friedl's book) provides
+ the means for specifying that once a group has matched, it is not to be
+ re-evaluated in this way.
+
+ If we use atomic grouping for the previous example, the matcher gives
+ up immediately on failing to match "foo" the first time. The notation
is a kind of special parenthesis, starting with (?> as in this example:
(?>\d+)foo
- This kind of parenthesis "locks up" the part of the pattern it con-
- tains once it has matched, and a failure further into the pattern is
+ Perl 5.28 introduced an experimental alphabetic form starting with (*
+ which may be easier to remember:
+
+ (*atomic:\d+)foo
+
+ This kind of parenthesized group "locks up" the part of the pattern it
+ contains once it has matched, and a failure further into the pattern is
prevented from backtracking into it. Backtracking past it to previous
items, however, works as normal.
- An alternative description is that a subpattern of this type matches
- exactly the string of characters that an identical standalone pattern
- would match, if anchored at the current point in the subject string.
+ An alternative description is that a group of this type matches exactly
+ the string of characters that an identical standalone pattern would
+ match, if anchored at the current point in the subject string.
- Atomic grouping subpatterns are not capturing subpatterns. Simple cases
- such as the above example can be thought of as a maximizing repeat that
- must swallow everything it can. So, while both \d+ and \d+? are pre-
- pared to adjust the number of digits they match in order to make the
- rest of the pattern match, (?>\d+) can only match an entire sequence of
- digits.
+ Atomic groups are not capture groups. Simple cases such as the above
+ example can be thought of as a maximizing repeat that must swallow ev-
+ erything it can. So, while both \d+ and \d+? are prepared to adjust
+ the number of digits they match in order to make the rest of the pat-
+ tern match, (?>\d+) can only match an entire sequence of digits.
- Atomic groups in general can of course contain arbitrarily complicated
- subpatterns, and can be nested. However, when the subpattern for an
- atomic group is just a single repeated item, as in the example above, a
- simpler notation, called a "possessive quantifier" can be used. This
- consists of an additional + character following a quantifier. Using
- this notation, the previous example can be rewritten as
+ Atomic groups in general can of course contain arbitrarily complicated
+ expressions, and can be nested. However, when the contents of an atomic
+ group is just a single repeated item, as in the example above, a sim-
+ pler notation, called a "possessive quantifier" can be used. This con-
+ sists of an additional + character following a quantifier. Using this
+ notation, the previous example can be rewritten as
\d++foo
@@ -7722,47 +7916,47 @@ ATOMIC GROUPING AND POSSESSIVE QUANTIFIERS
(abc|xyz){2,3}+
- Possessive quantifiers are always greedy; the setting of the
- PCRE2_UNGREEDY option is ignored. They are a convenient notation for
- the simpler forms of atomic group. However, there is no difference in
- the meaning of a possessive quantifier and the equivalent atomic group,
- though there may be a performance difference; possessive quantifiers
+ Possessive quantifiers are always greedy; the setting of the PCRE2_UN-
+ GREEDY option is ignored. They are a convenient notation for the sim-
+ pler forms of atomic group. However, there is no difference in the
+ meaning of a possessive quantifier and the equivalent atomic group,
+ though there may be a performance difference; possessive quantifiers
should be slightly faster.
- The possessive quantifier syntax is an extension to the Perl 5.8 syn-
- tax. Jeffrey Friedl originated the idea (and the name) in the first
+ The possessive quantifier syntax is an extension to the Perl 5.8 syn-
+ tax. Jeffrey Friedl originated the idea (and the name) in the first
edition of his book. Mike McCloskey liked it, so implemented it when he
- built Sun's Java package, and PCRE1 copied it from there. It ultimately
- found its way into Perl at release 5.10.
+ built Sun's Java package, and PCRE1 copied it from there. It found its
+ way into Perl at release 5.10.
- PCRE2 has an optimization that automatically "possessifies" certain
- simple pattern constructs. For example, the sequence A+B is treated as
- A++B because there is no point in backtracking into a sequence of A's
+ PCRE2 has an optimization that automatically "possessifies" certain
+ simple pattern constructs. For example, the sequence A+B is treated as
+ A++B because there is no point in backtracking into a sequence of A's
when B must follow. This feature can be disabled by the PCRE2_NO_AUTO-
POSSESS option, or starting the pattern with (*NO_AUTO_POSSESS).
- When a pattern contains an unlimited repeat inside a subpattern that
- can itself be repeated an unlimited number of times, the use of an
- atomic group is the only way to avoid some failing matches taking a
- very long time indeed. The pattern
+ When a pattern contains an unlimited repeat inside a group that can it-
+ self be repeated an unlimited number of times, the use of an atomic
+ group is the only way to avoid some failing matches taking a very long
+ time indeed. The pattern
(\D+|<\d+>)*[!?]
- matches an unlimited number of substrings that either consist of non-
- digits, or digits enclosed in <>, followed by either ! or ?. When it
+ matches an unlimited number of substrings that either consist of non-
+ digits, or digits enclosed in <>, followed by either ! or ?. When it
matches, it runs quickly. However, if it is applied to
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- it takes a long time before reporting failure. This is because the
- string can be divided between the internal \D+ repeat and the external
- * repeat in a large number of ways, and all have to be tried. (The
- example uses [!?] rather than a single character at the end, because
- both PCRE2 and Perl have an optimization that allows for fast failure
- when a single character is used. They remember the last single charac-
- ter that is required for a match, and fail early if it is not present
- in the string.) If the pattern is changed so that it uses an atomic
- group, like this:
+ it takes a long time before reporting failure. This is because the
+ string can be divided between the internal \D+ repeat and the external
+ * repeat in a large number of ways, and all have to be tried. (The ex-
+ ample uses [!?] rather than a single character at the end, because both
+ PCRE2 and Perl have an optimization that allows for fast failure when a
+ single character is used. They remember the last single character that
+ is required for a match, and fail early if it is not present in the
+ string.) If the pattern is changed so that it uses an atomic group,
+ like this:
((?>\D+)|<\d+>)*[!?]
@@ -7772,26 +7966,25 @@ ATOMIC GROUPING AND POSSESSIVE QUANTIFIERS
BACKREFERENCES
Outside a character class, a backslash followed by a digit greater than
- 0 (and possibly further digits) is a backreference to a capturing sub-
- pattern earlier (that is, to its left) in the pattern, provided there
- have been that many previous capturing left parentheses.
-
- However, if the decimal number following the backslash is less than 8,
- it is always taken as a backreference, and causes an error only if
- there are not that many capturing left parentheses in the entire pat-
- tern. In other words, the parentheses that are referenced need not be
- to the left of the reference for numbers less than 8. A "forward back-
- reference" of this type can make sense when a repetition is involved
- and the subpattern to the right has participated in an earlier itera-
- tion.
+ 0 (and possibly further digits) is a backreference to a capture group
+ earlier (that is, to its left) in the pattern, provided there have been
+ that many previous capture groups.
+
+ However, if the decimal number following the backslash is less than 8,
+ it is always taken as a backreference, and causes an error only if
+ there are not that many capture groups in the entire pattern. In other
+ words, the group that is referenced need not be to the left of the ref-
+ erence for numbers less than 8. A "forward backreference" of this type
+ can make sense when a repetition is involved and the group to the right
+ has participated in an earlier iteration.
It is not possible to have a numerical "forward backreference" to a
- subpattern whose number is 8 or more using this syntax because a
- sequence such as \50 is interpreted as a character defined in octal.
- See the subsection entitled "Non-printing characters" above for further
- details of the handling of digits following a backslash. There is no
- such problem when named parentheses are used. A backreference to any
- subpattern is possible using named parentheses (see below).
+ group whose number is 8 or more using this syntax because a sequence
+ such as \50 is interpreted as a character defined in octal. See the
+ subsection entitled "Non-printing characters" above for further details
+ of the handling of digits following a backslash. Other forms of back-
+ referencing do not suffer from this restriction. In particular, there
+ is no problem when named capture groups are used (see below).
Another way of avoiding the ambiguity inherent in the use of digits
following a backslash is to use the \g escape sequence. This escape
@@ -7809,21 +8002,21 @@ BACKREFERENCES
(abc(def)ghi)\g{-1}
- The sequence \g{-1} is a reference to the most recently started captur-
- ing subpattern before \g, that is, is it equivalent to \2 in this exam-
- ple. Similarly, \g{-2} would be equivalent to \1. The use of relative
- references can be helpful in long patterns, and also in patterns that
- are created by joining together fragments that contain references
- within themselves.
+ The sequence \g{-1} is a reference to the most recently started capture
+ group before \g, that is, is it equivalent to \2 in this example. Simi-
+ larly, \g{-2} would be equivalent to \1. The use of relative references
+ can be helpful in long patterns, and also in patterns that are created
+ by joining together fragments that contain references within them-
+ selves.
- The sequence \g{+1} is a reference to the next capturing subpattern.
- This kind of forward reference can be useful it patterns that repeat.
- Perl does not support the use of + in this way.
+ The sequence \g{+1} is a reference to the next capture group. This kind
+ of forward reference can be useful in patterns that repeat. Perl does
+ not support the use of + in this way.
- A backreference matches whatever actually matched the capturing subpat-
- tern in the current subject string, rather than anything matching the
- subpattern itself (see "Subpatterns as subroutines" below for a way of
- doing that). So the pattern
+ A backreference matches whatever actually most recently matched the
+ capture group in the current subject string, rather than anything at
+ all that matches the group (see "Groups as subroutines" below for a way
+ of doing that). So the pattern
(sens|respons)e and \1ibility
@@ -7835,26 +8028,26 @@ BACKREFERENCES
((?i)rah)\s+\1
matches "rah rah" and "RAH RAH", but not "RAH rah", even though the
- original capturing subpattern is matched caselessly.
+ original capture group is matched caselessly.
There are several different ways of writing backreferences to named
- subpatterns. The .NET syntax \k{name} and the Perl syntax \k or
- \k'name' are supported, as is the Python syntax (?P=name). Perl 5.10's
- unified backreference syntax, in which \g can be used for both numeric
- and named references, is also supported. We could rewrite the above
- example in any of the following ways:
+ capture groups. The .NET syntax \k{name} and the Perl syntax \k
+ or \k'name' are supported, as is the Python syntax (?P=name). Perl
+ 5.10's unified backreference syntax, in which \g can be used for both
+ numeric and named references, is also supported. We could rewrite the
+ above example in any of the following ways:
(?(?i)rah)\s+\k
(?'p1'(?i)rah)\s+\k{p1}
(?P(?i)rah)\s+(?P=p1)
(?(?i)rah)\s+\g{p1}
- A subpattern that is referenced by name may appear in the pattern
+ A capture group that is referenced by name may appear in the pattern
before or after the reference.
- There may be more than one backreference to the same subpattern. If a
- subpattern has not actually been used in a particular match, any back-
- references to it always fail by default. For example, the pattern
+ There may be more than one backreference to the same group. If a group
+ has not actually been used in a particular match, backreferences to it
+ always fail by default. For example, the pattern
(a|(bc))\2
@@ -7862,62 +8055,72 @@ BACKREFERENCES
the PCRE2_MATCH_UNSET_BACKREF option is set at compile time, a backref-
erence to an unset value matches an empty string.
- Because there may be many capturing parentheses in a pattern, all dig-
- its following a backslash are taken as part of a potential backrefer-
- ence number. If the pattern continues with a digit character, some
- delimiter must be used to terminate the backreference. If the
- PCRE2_EXTENDED or PCRE2_EXTENDED_MORE option is set, this can be white
- space. Otherwise, the \g{ syntax or an empty comment (see "Comments"
- below) can be used.
+ Because there may be many capture groups in a pattern, all digits fol-
+ lowing a backslash are taken as part of a potential backreference num-
+ ber. If the pattern continues with a digit character, some delimiter
+ must be used to terminate the backreference. If the PCRE2_EXTENDED or
+ PCRE2_EXTENDED_MORE option is set, this can be white space. Otherwise,
+ the \g{} syntax or an empty comment (see "Comments" below) can be used.
Recursive backreferences
- A backreference that occurs inside the parentheses to which it refers
- fails when the subpattern is first used, so, for example, (a\1) never
- matches. However, such references can be useful inside repeated sub-
- patterns. For example, the pattern
+ A backreference that occurs inside the group to which it refers fails
+ when the group is first used, so, for example, (a\1) never matches.
+ However, such references can be useful inside repeated groups. For ex-
+ ample, the pattern
(a|b\1)+
matches any number of "a"s and also "aba", "ababbaa" etc. At each iter-
- ation of the subpattern, the backreference matches the character string
- corresponding to the previous iteration. In order for this to work, the
- pattern must be such that the first iteration does not need to match
- the backreference. This can be done using alternation, as in the exam-
+ ation of the group, the backreference matches the character string cor-
+ responding to the previous iteration. In order for this to work, the
+ pattern must be such that the first iteration does not need to match
+ the backreference. This can be done using alternation, as in the exam-
ple above, or by a quantifier with a minimum of zero.
- Backreferences of this type cause the group that they reference to be
- treated as an atomic group. Once the whole group has been matched, a
- subsequent matching failure cannot cause backtracking into the middle
+ Backreferences of this type cause the group that they reference to be
+ treated as an atomic group. Once the whole group has been matched, a
+ subsequent matching failure cannot cause backtracking into the middle
of the group.
ASSERTIONS
- An assertion is a test on the characters following or preceding the
+ An assertion is a test on the characters following or preceding the
current matching point that does not consume any characters. The simple
- assertions coded as \b, \B, \A, \G, \Z, \z, ^ and $ are described
+ assertions coded as \b, \B, \A, \G, \Z, \z, ^ and $ are described
above.
- More complicated assertions are coded as subpatterns. There are two
- kinds: those that look ahead of the current position in the subject
- string, and those that look behind it, and in each case an assertion
- may be positive (must succeed for matching to continue) or negative
- (must not succeed for matching to continue). An assertion subpattern is
- matched in the normal way, except that, when matching continues after a
- successful assertion, the matching position in the subject string is as
- it was before the assertion was processed.
-
- Assertion subpatterns are not capturing subpatterns. If an assertion
- contains capturing subpatterns within it, these are counted for the
- purposes of numbering the capturing subpatterns in the whole pattern.
- Within each branch of an assertion, locally captured substrings may be
- referenced in the usual way. For example, a sequence such as (.)\g{-1}
- can be used to check that two adjacent characters are the same.
+ More complicated assertions are coded as parenthesized groups. There
+ are two kinds: those that look ahead of the current position in the
+ subject string, and those that look behind it, and in each case an as-
+ sertion may be positive (must match for the assertion to be true) or
+ negative (must not match for the assertion to be true). An assertion
+ group is matched in the normal way, and if it is true, matching contin-
+ ues after it, but with the matching position in the subject string re-
+ set to what it was before the assertion was processed.
+
+ The Perl-compatible lookaround assertions are atomic. If an assertion
+ is true, but there is a subsequent matching failure, there is no back-
+ tracking into the assertion. However, there are some cases where non-
+ atomic assertions can be useful. PCRE2 has some support for these, de-
+ scribed in the section entitled "Non-atomic assertions" below, but they
+ are not Perl-compatible.
+
+ A lookaround assertion may appear as the condition in a conditional
+ group (see below). In this case, the result of matching the assertion
+ determines which branch of the condition is followed.
+
+ Assertion groups are not capture groups. If an assertion contains cap-
+ ture groups within it, these are counted for the purposes of numbering
+ the capture groups in the whole pattern. Within each branch of an as-
+ sertion, locally captured substrings may be referenced in the usual
+ way. For example, a sequence such as (.)\g{-1} can be used to check
+ that two adjacent characters are the same.
When a branch within an assertion fails to match, any substrings that
were captured are discarded (as happens with any pattern branch that
- fails to match). A negative assertion succeeds only when all its
+ fails to match). A negative assertion is true only when all its
branches fail to match; this means that no captured substrings are ever
retained after a successful negative assertion. When an assertion con-
tains a matching branch, what happens depends on the type of assertion.
@@ -7925,33 +8128,49 @@ ASSERTIONS
For a positive assertion, internally captured substrings in the suc-
cessful branch are retained, and matching continues with the next pat-
tern item after the assertion. For a negative assertion, a matching
- branch means that the assertion has failed. If the assertion is being
- used as a condition in a conditional subpattern (see below), captured
+ branch means that the assertion is not true. If such an assertion is
+ being used as a condition in a conditional group (see below), captured
substrings are retained, because matching continues with the "no"
branch of the condition. For other failing negative assertions, control
passes to the previous backtracking point, thus discarding any captured
strings within the assertion.
- For compatibility with Perl, most assertion subpatterns may be
- repeated; though it makes no sense to assert the same thing several
- times, the side effect of capturing parentheses may occasionally be
- useful. However, an assertion that forms the condition for a condi-
- tional subpattern may not be quantified. In practice, for other asser-
- tions, there only three cases:
+ For compatibility with Perl, most assertion groups may be repeated;
+ though it makes no sense to assert the same thing several times, the
+ side effect of capturing may occasionally be useful. However, an asser-
+ tion that forms the condition for a conditional group may not be quan-
+ tified. In practice, for other assertions, there only three cases:
- (1) If the quantifier is {0}, the assertion is never obeyed during
- matching. However, it may contain internal capturing parenthesized
- groups that are called from elsewhere via the subroutine mechanism.
+ (1) If the quantifier is {0}, the assertion is never obeyed during
+ matching. However, it may contain internal capture groups that are
+ called from elsewhere via the subroutine mechanism.
- (2) If quantifier is {0,n} where n is greater than zero, it is treated
- as if it were {0,1}. At run time, the rest of the pattern match is
+ (2) If quantifier is {0,n} where n is greater than zero, it is treated
+ as if it were {0,1}. At run time, the rest of the pattern match is
tried with and without the assertion, the order depending on the greed-
iness of the quantifier.
- (3) If the minimum repetition is greater than zero, the quantifier is
- ignored. The assertion is obeyed just once when encountered during
+ (3) If the minimum repetition is greater than zero, the quantifier is
+ ignored. The assertion is obeyed just once when encountered during
matching.
+ Alphabetic assertion names
+
+ Traditionally, symbolic sequences such as (?= and (?<= have been used
+ to specify lookaround assertions. Perl 5.28 introduced some experimen-
+ tal alphabetic alternatives which might be easier to remember. They all
+ start with (* instead of (? and must be written using lower case let-
+ ters. PCRE2 supports the following synonyms:
+
+ (*positive_lookahead: or (*pla: is the same as (?=
+ (*negative_lookahead: or (*nla: is the same as (?!
+ (*positive_lookbehind: or (*plb: is the same as (?<=
+ (*negative_lookbehind: or (*nlb: is the same as (? .*? \b\1\b ){2}
+
+ For a subject such as "word1 word2 word3 word2 word3 word4" the result
+ is "word3". How does it work? At the start, ^(?x) anchors the pattern
+ and sets the "x" option, which causes white space (introduced for read-
+ ability) to be ignored. Inside the assertion, the greedy .* at first
+ consumes the entire string, but then has to backtrack until the rest of
+ the assertion can match a word, which is captured by group 1. In other
+ words, when the assertion first succeeds, it captures the right-most
+ word in the string.
+
+ The current matching point is then reset to the start of the subject,
+ and the rest of the pattern match checks for two occurrences of the
+ captured word, using an ungreedy .*? to scan from the left. If this
+ succeeds, we are done, but if the last word in the string does not oc-
+ cur twice, this part of the pattern fails. If a traditional atomic
+ lookhead (?= or (*pla: had been used, the assertion could not be re-en-
+ tered, and the whole match would fail. The pattern would succeed only
+ if the very last word in the subject was found twice.
+
+ Using a non-atomic lookahead, however, means that when the last word
+ does not occur twice in the string, the lookahead can backtrack and
+ find the second-last word, and so on, until either the match succeeds,
+ or all words have been tested.
+
+ Two conditions must be met for a non-atomic assertion to be useful: the
+ contents of one or more capturing groups must change after a backtrack
+ into the assertion, and there must be a backreference to a changed
+ group later in the pattern. If this is not the case, the rest of the
+ pattern match fails exactly as before because nothing has changed, so
+ using a non-atomic assertion just wastes resources.
+
+ Non-atomic assertions are not supported by the alternative matching
+ function pcre2_dfa_match(). They are also not supported by JIT (but may
+ be in future). Note that assertions that appear as conditions for con-
+ ditional groups (see below) must be atomic.
+
+
+SCRIPT RUNS
+
+ In concept, a script run is a sequence of characters that are all from
+ the same Unicode script such as Latin or Greek. However, because some
+ scripts are commonly used together, and because some diacritical and
+ other marks are used with multiple scripts, it is not that simple.
+ There is a full description of the rules that PCRE2 uses in the section
+ entitled "Script Runs" in the pcre2unicode documentation.
+
+ If part of a pattern is enclosed between (*script_run: or (*sr: and a
+ closing parenthesis, it fails if the sequence of characters that it
+ matches are not a script run. After a failure, normal backtracking oc-
+ curs. Script runs can be used to detect spoofing attacks using charac-
+ ters that look the same, but are from different scripts. The string
+ "paypal.com" is an infamous example, where the letters could be a mix-
+ ture of Latin and Cyrillic. This pattern ensures that the matched char-
+ acters in a sequence of non-spaces that follow white space are a script
+ run:
+
+ \s+(*sr:\S+)
+
+ To be sure that they are all from the Latin script (for example), a
+ lookahead can be used:
+
+ \s+(?=\p{Latin})(*sr:\S+)
+
+ This works as long as the first character is expected to be a character
+ in that script, and not (for example) punctuation, which is allowed
+ with any script. If this is not the case, a more creative lookahead is
+ needed. For example, if digits, underscore, and dots are permitted at
+ the start:
+
+ \s+(?=[0-9_.]*\p{Latin})(*sr:\S+)
+
+
+ In many cases, backtracking into a script run pattern fragment is not
+ desirable. The script run can employ an atomic group to prevent this.
+ Because this is a common requirement, a shorthand notation is provided
+ by (*atomic_script_run: or (*asr:
+
+ (*asr:...) is the same as (*sr:(?>...))
- It is possible to cause the matching process to obey a subpattern con-
- ditionally or to choose between two alternative subpatterns, depending
- on the result of an assertion, or whether a specific capturing subpat-
- tern has already been matched. The two possible forms of conditional
- subpattern are:
+ Note that the atomic group is inside the script run. Putting it outside
+ would not prevent backtracking into the script run pattern.
+
+ Support for script runs is not available if PCRE2 is compiled without
+ Unicode support. A compile-time error is given if any of the above con-
+ structs is encountered. Script runs are not supported by the alternate
+ matching function, pcre2_dfa_match() because they use the same mecha-
+ nism as capturing parentheses.
+
+ Warning: The (*ACCEPT) control verb (see below) should not be used
+ within a script run group, because it causes an immediate exit from the
+ group, bypassing the script run checking.
+
+
+CONDITIONAL GROUPS
+
+ It is possible to cause the matching process to obey a pattern fragment
+ conditionally or to choose between two alternative fragments, depending
+ on the result of an assertion, or whether a specific capture group has
+ already been matched. The two possible forms of conditional group are:
(?(condition)yes-pattern)
(?(condition)yes-pattern|no-pattern)
@@ -8117,33 +8445,33 @@ CONDITIONAL SUBPATTERNS
If the condition is satisfied, the yes-pattern is used; otherwise the
no-pattern (if present) is used. An absent no-pattern is equivalent to
an empty string (it always matches). If there are more than two alter-
- natives in the subpattern, a compile-time error occurs. Each of the two
- alternatives may itself contain nested subpatterns of any form, includ-
- ing conditional subpatterns; the restriction to two alternatives
- applies only at the level of the condition. This pattern fragment is an
- example where the alternatives are complex:
+ natives in the group, a compile-time error occurs. Each of the two al-
+ ternatives may itself contain nested groups of any form, including con-
+ ditional groups; the restriction to two alternatives applies only at
+ the level of the condition itself. This pattern fragment is an example
+ where the alternatives are complex:
(?(1) (A|B|C) | (D | (?(2)E|F) | E) )
- There are five kinds of condition: references to subpatterns, refer-
+ There are five kinds of condition: references to capture groups, refer-
ences to recursion, two pseudo-conditions called DEFINE and VERSION,
and assertions.
- Checking for a used subpattern by number
+ Checking for a used capture group by number
If the text between the parentheses consists of a sequence of digits,
- the condition is true if a capturing subpattern of that number has pre-
- viously matched. If there is more than one capturing subpattern with
- the same number (see the earlier section about duplicate subpattern
- numbers), the condition is true if any of them have matched. An alter-
- native notation is to precede the digits with a plus or minus sign. In
- this case, the subpattern number is relative rather than absolute. The
- most recently opened parentheses can be referenced by (?(-1), the next
- most recent by (?(-2), and so on. Inside loops it can also make sense
- to refer to subsequent groups. The next parentheses to be opened can be
- referenced as (?(+1), and so on. (The value zero in any of these forms
- is not used; it provokes a compile-time error.)
+ the condition is true if a capture group of that number has previously
+ matched. If there is more than one capture group with the same number
+ (see the earlier section about duplicate group numbers), the condition
+ is true if any of them have matched. An alternative notation is to pre-
+ cede the digits with a plus or minus sign. In this case, the group num-
+ ber is relative rather than absolute. The most recently opened capture
+ group can be referenced by (?(-1), the next most recent by (?(-2), and
+ so on. Inside loops it can also make sense to refer to subsequent
+ groups. The next capture group can be referenced as (?(+1), and so on.
+ (The value zero in any of these forms is not used; it provokes a com-
+ pile-time error.)
Consider the following pattern, which contains non-significant white
space to make it more readable (assume the PCRE2_EXTENDED option) and
@@ -8154,13 +8482,13 @@ CONDITIONAL SUBPATTERNS
The first part matches an optional opening parenthesis, and if that
character is present, sets it as the first captured substring. The sec-
ond part matches one or more characters that are not parentheses. The
- third part is a conditional subpattern that tests whether or not the
- first set of parentheses matched. If they did, that is, if subject
- started with an opening parenthesis, the condition is true, and so the
- yes-pattern is executed and a closing parenthesis is required. Other-
- wise, since no-pattern is not present, the subpattern matches nothing.
- In other words, this pattern matches a sequence of non-parentheses,
- optionally enclosed in parentheses.
+ third part is a conditional group that tests whether or not the first
+ capture group matched. If it did, that is, if subject started with an
+ opening parenthesis, the condition is true, and so the yes-pattern is
+ executed and a closing parenthesis is required. Otherwise, since no-
+ pattern is not present, the conditional group matches nothing. In other
+ words, this pattern matches a sequence of non-parentheses, optionally
+ enclosed in parentheses.
If you were embedding this pattern in a larger one, you could use a
relative reference:
@@ -8170,70 +8498,68 @@ CONDITIONAL SUBPATTERNS
This makes the fragment independent of the parentheses in the larger
pattern.
- Checking for a used subpattern by name
+ Checking for a used capture group by name
Perl uses the syntax (?()...) or (?('name')...) to test for a
- used subpattern by name. For compatibility with earlier versions of
+ used capture group by name. For compatibility with earlier versions of
PCRE1, which had this facility before Perl, the syntax (?(name)...) is
- also recognized. Note, however, that undelimited names consisting of
+ also recognized. Note, however, that undelimited names consisting of
the letter R followed by digits are ambiguous (see the following sec-
- tion).
-
- Rewriting the above example to use a named subpattern gives this:
+ tion). Rewriting the above example to use a named group gives this:
(? \( )? [^()]+ (?() \) )
If the name used in a condition of this kind is a duplicate, the test
- is applied to all subpatterns of the same name, and is true if any one
- of them has matched.
+ is applied to all groups of the same name, and is true if any one of
+ them has matched.
Checking for pattern recursion
"Recursion" in this sense refers to any subroutine-like call from one
part of the pattern to another, whether or not it is actually recur-
- sive. See the sections entitled "Recursive patterns" and "Subpatterns
- as subroutines" below for details of recursion and subpattern calls.
-
- If a condition is the string (R), and there is no subpattern with the
- name R, the condition is true if matching is currently in a recursion
- or subroutine call to the whole pattern or any subpattern. If digits
- follow the letter R, and there is no subpattern with that name, the
- condition is true if the most recent call is into a subpattern with the
+ sive. See the sections entitled "Recursive patterns" and "Groups as
+ subroutines" below for details of recursion and subroutine calls.
+
+ If a condition is the string (R), and there is no capture group with
+ the name R, the condition is true if matching is currently in a recur-
+ sion or subroutine call to the whole pattern or any capture group. If
+ digits follow the letter R, and there is no group with that name, the
+ condition is true if the most recent call is into a group with the
given number, which must exist somewhere in the overall pattern. This
is a contrived example that is equivalent to a+b:
((?(R1)a+|(?1)b))
- However, in both cases, if there is a subpattern with a matching name,
- the condition tests for its being set, as described in the section
- above, instead of testing for recursion. For example, creating a group
- with the name R1 by adding (?) to the above pattern completely
- changes its meaning.
+ However, in both cases, if there is a capture group with a matching
+ name, the condition tests for its being set, as described in the sec-
+ tion above, instead of testing for recursion. For example, creating a
+ group with the name R1 by adding (?) to the above pattern com-
+ pletely changes its meaning.
If a name preceded by ampersand follows the letter R, for example:
(?(R&name)...)
- the condition is true if the most recent recursion is into a subpattern
- of that name (which must exist within the pattern).
+ the condition is true if the most recent recursion is into a group of
+ that name (which must exist within the pattern).
This condition does not check the entire recursion stack. It tests only
the current level. If the name used in a condition of this kind is a
- duplicate, the test is applied to all subpatterns of the same name, and
- is true if any one of them is the most recent recursion.
+ duplicate, the test is applied to all groups of the same name, and is
+ true if any one of them is the most recent recursion.
At "top level", all these recursion test conditions are false.
- Defining subpatterns for use by reference only
+ Defining capture groups for use by reference only
If the condition is the string (DEFINE), the condition is always false,
even if there is a group with the name DEFINE. In this case, there may
- be only one alternative in the subpattern. It is always skipped if con-
- trol reaches this point in the pattern; the idea of DEFINE is that it
- can be used to define subroutines that can be referenced from else-
- where. (The use of subroutines is described below.) For example, a pat-
- tern to match an IPv4 address such as "192.168.23.245" could be written
- like this (ignore white space and line breaks):
+ be only one alternative in the rest of the conditional group. It is al-
+ ways skipped if control reaches this point in the pattern; the idea of
+ DEFINE is that it can be used to define subroutines that can be refer-
+ enced from elsewhere. (The use of subroutines is described below.) For
+ example, a pattern to match an IPv4 address such as "192.168.23.245"
+ could be written like this (ignore white space and line breaks):
(?(DEFINE) (? 2[0-4]\d | 25[0-5] | 1\d\d | [1-9]?\d) )
\b (?&byte) (\.(?&byte)){3} \b
@@ -8264,71 +8590,74 @@ CONDITIONAL SUBPATTERNS
Assertion conditions
- If the condition is not in any of the above formats, it must be an
- assertion. This may be a positive or negative lookahead or lookbehind
- assertion. Consider this pattern, again containing non-significant
- white space, and with the two alternatives on the second line:
+ If the condition is not in any of the above formats, it must be a
+ parenthesized assertion. This may be a positive or negative lookahead
+ or lookbehind assertion. However, it must be a traditional atomic as-
+ sertion, not one of the PCRE2-specific non-atomic assertions.
+
+ Consider this pattern, again containing non-significant white space,
+ and with the two alternatives on the second line:
(?(?=[^a-z]*[a-z])
\d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} )
- The condition is a positive lookahead assertion that matches an
- optional sequence of non-letters followed by a letter. In other words,
- it tests for the presence of at least one letter in the subject. If a
- letter is found, the subject is matched against the first alternative;
- otherwise it is matched against the second. This pattern matches
- strings in one of the two forms dd-aaa-dd or dd-dd-dd, where aaa are
+ The condition is a positive lookahead assertion that matches an op-
+ tional sequence of non-letters followed by a letter. In other words, it
+ tests for the presence of at least one letter in the subject. If a let-
+ ter is found, the subject is matched against the first alternative;
+ otherwise it is matched against the second. This pattern matches
+ strings in one of the two forms dd-aaa-dd or dd-dd-dd, where aaa are
letters and dd are digits.
- When an assertion that is a condition contains capturing subpatterns,
- any capturing that occurs in a matching branch is retained afterwards,
- for both positive and negative assertions, because matching always con-
- tinues after the assertion, whether it succeeds or fails. (Compare non-
- conditional assertions, when captures are retained only for positive
- assertions that succeed.)
+ When an assertion that is a condition contains capture groups, any cap-
+ turing that occurs in a matching branch is retained afterwards, for
+ both positive and negative assertions, because matching always contin-
+ ues after the assertion, whether it succeeds or fails. (Compare non-
+ conditional assertions, for which captures are retained only for posi-
+ tive assertions that succeed.)
COMMENTS
There are two ways of including comments in patterns that are processed
- by PCRE2. In both cases, the start of the comment must not be in a
- character class, nor in the middle of any other sequence of related
- characters such as (?: or a subpattern name or number. The characters
- that make up a comment play no part in the pattern matching.
-
- The sequence (?# marks the start of a comment that continues up to the
- next closing parenthesis. Nested parentheses are not permitted. If the
- PCRE2_EXTENDED or PCRE2_EXTENDED_MORE option is set, an unescaped #
- character also introduces a comment, which in this case continues to
- immediately after the next newline character or character sequence in
+ by PCRE2. In both cases, the start of the comment must not be in a
+ character class, nor in the middle of any other sequence of related
+ characters such as (?: or a group name or number. The characters that
+ make up a comment play no part in the pattern matching.
+
+ The sequence (?# marks the start of a comment that continues up to the
+ next closing parenthesis. Nested parentheses are not permitted. If the
+ PCRE2_EXTENDED or PCRE2_EXTENDED_MORE option is set, an unescaped #
+ character also introduces a comment, which in this case continues to
+ immediately after the next newline character or character sequence in
the pattern. Which characters are interpreted as newlines is controlled
- by an option passed to the compiling function or by a special sequence
+ by an option passed to the compiling function or by a special sequence
at the start of the pattern, as described in the section entitled "New-
line conventions" above. Note that the end of this type of comment is a
- literal newline sequence in the pattern; escape sequences that happen
+ literal newline sequence in the pattern; escape sequences that happen
to represent a newline do not count. For example, consider this pattern
- when PCRE2_EXTENDED is set, and the default newline convention (a sin-
+ when PCRE2_EXTENDED is set, and the default newline convention (a sin-
gle linefeed character) is in force:
abc #comment \n still comment
- On encountering the # character, pcre2_compile() skips along, looking
- for a newline in the pattern. The sequence \n is still literal at this
- stage, so it does not terminate the comment. Only an actual character
+ On encountering the # character, pcre2_compile() skips along, looking
+ for a newline in the pattern. The sequence \n is still literal at this
+ stage, so it does not terminate the comment. Only an actual character
with the code value 0x0a (the default newline) does so.
RECURSIVE PATTERNS
- Consider the problem of matching a string in parentheses, allowing for
- unlimited nested parentheses. Without the use of recursion, the best
- that can be done is to use a pattern that matches up to some fixed
- depth of nesting. It is not possible to handle an arbitrary nesting
+ Consider the problem of matching a string in parentheses, allowing for
+ unlimited nested parentheses. Without the use of recursion, the best
+ that can be done is to use a pattern that matches up to some fixed
+ depth of nesting. It is not possible to handle an arbitrary nesting
depth.
For some time, Perl has provided a facility that allows regular expres-
- sions to recurse (amongst other things). It does this by interpolating
- Perl code in the expression at run time, and the code can refer to the
+ sions to recurse (amongst other things). It does this by interpolating
+ Perl code in the expression at run time, and the code can refer to the
expression itself. A Perl pattern using code interpolation to solve the
parentheses problem can be created like this:
@@ -8337,65 +8666,64 @@ RECURSIVE PATTERNS
The (?p{...}) item interpolates Perl code at run time, and in this case
refers recursively to the pattern in which it appears.
- Obviously, PCRE2 cannot support the interpolation of Perl code.
- Instead, it supports special syntax for recursion of the entire pat-
- tern, and also for individual subpattern recursion. After its introduc-
- tion in PCRE1 and Python, this kind of recursion was subsequently
- introduced into Perl at release 5.10.
+ Obviously, PCRE2 cannot support the interpolation of Perl code. In-
+ stead, it supports special syntax for recursion of the entire pattern,
+ and also for individual capture group recursion. After its introduction
+ in PCRE1 and Python, this kind of recursion was subsequently introduced
+ into Perl at release 5.10.
- A special item that consists of (? followed by a number greater than
- zero and a closing parenthesis is a recursive subroutine call of the
- subpattern of the given number, provided that it occurs inside that
- subpattern. (If not, it is a non-recursive subroutine call, which is
- described in the next section.) The special item (?R) or (?0) is a
- recursive call of the entire regular expression.
+ A special item that consists of (? followed by a number greater than
+ zero and a closing parenthesis is a recursive subroutine call of the
+ capture group of the given number, provided that it occurs inside that
+ group. (If not, it is a non-recursive subroutine call, which is de-
+ scribed in the next section.) The special item (?R) or (?0) is a recur-
+ sive call of the entire regular expression.
- This PCRE2 pattern solves the nested parentheses problem (assume the
+ This PCRE2 pattern solves the nested parentheses problem (assume the
PCRE2_EXTENDED option is set so that white space is ignored):
\( ( [^()]++ | (?R) )* \)
- First it matches an opening parenthesis. Then it matches any number of
- substrings which can either be a sequence of non-parentheses, or a
- recursive match of the pattern itself (that is, a correctly parenthe-
- sized substring). Finally there is a closing parenthesis. Note the use
- of a possessive quantifier to avoid backtracking into sequences of non-
+ First it matches an opening parenthesis. Then it matches any number of
+ substrings which can either be a sequence of non-parentheses, or a re-
+ cursive match of the pattern itself (that is, a correctly parenthesized
+ substring). Finally there is a closing parenthesis. Note the use of a
+ possessive quantifier to avoid backtracking into sequences of non-
parentheses.
- If this were part of a larger pattern, you would not want to recurse
+ If this were part of a larger pattern, you would not want to recurse
the entire pattern, so instead you could use this:
( \( ( [^()]++ | (?1) )* \) )
- We have put the pattern into parentheses, and caused the recursion to
+ We have put the pattern into parentheses, and caused the recursion to
refer to them instead of the whole pattern.
- In a larger pattern, keeping track of parenthesis numbers can be
- tricky. This is made easier by the use of relative references. Instead
+ In a larger pattern, keeping track of parenthesis numbers can be
+ tricky. This is made easier by the use of relative references. Instead
of (?1) in the pattern above you can write (?-2) to refer to the second
- most recently opened parentheses preceding the recursion. In other
- words, a negative number counts capturing parentheses leftwards from
+ most recently opened parentheses preceding the recursion. In other
+ words, a negative number counts capturing parentheses leftwards from
the point at which it is encountered.
- Be aware however, that if duplicate subpattern numbers are in use, rel-
- ative references refer to the earliest subpattern with the appropriate
+ Be aware however, that if duplicate capture group numbers are in use,
+ relative references refer to the earliest group with the appropriate
number. Consider, for example:
(?|(a)|(b)) (c) (?-2)
- The first two capturing groups (a) and (b) are both numbered 1, and
- group (c) is number 2. When the reference (?-2) is encountered, the
- second most recently opened parentheses has the number 1, but it is the
- first such group (the (a) group) to which the recursion refers. This
- would be the same if an absolute reference (?1) was used. In other
- words, relative references are just a shorthand for computing a group
- number.
+ The first two capture groups (a) and (b) are both numbered 1, and group
+ (c) is number 2. When the reference (?-2) is encountered, the second
+ most recently opened parentheses has the number 1, but it is the first
+ such group (the (a) group) to which the recursion refers. This would be
+ the same if an absolute reference (?1) was used. In other words, rela-
+ tive references are just a shorthand for computing a group number.
- It is also possible to refer to subsequently opened parentheses, by
- writing references such as (?+2). However, these cannot be recursive
- because the reference is not inside the parentheses that are refer-
- enced. They are always non-recursive subroutine calls, as described in
- the next section.
+ It is also possible to refer to subsequent capture groups, by writing
+ references such as (?+2). However, these cannot be recursive because
+ the reference is not inside the parentheses that are referenced. They
+ are always non-recursive subroutine calls, as described in the next
+ section.
An alternative approach is to use named parentheses. The Perl syntax
for this is (?&name); PCRE1's earlier syntax (?P>name) is also sup-
@@ -8403,8 +8731,8 @@ RECURSIVE PATTERNS
(? \( ( [^()]++ | (?&pn) )* \) )
- If there is more than one subpattern with the same name, the earliest
- one is used.
+ If there is more than one group with the same name, the earliest one is
+ used.
The example pattern that we have been looking at contains nested unlim-
ited repeats, and so the use of a possessive quantifier for matching
@@ -8426,10 +8754,10 @@ RECURSIVE PATTERNS
(ab(cd)ef)
the value for the inner capturing parentheses (numbered 2) is "ef",
- which is the last value taken on at the top level. If a capturing sub-
- pattern is not matched at the top level, its final captured value is
- unset, even if it was (temporarily) set at a deeper level during the
- matching process.
+ which is the last value taken on at the top level. If a capture group
+ is not matched at the top level, its final captured value is unset,
+ even if it was (temporarily) set at a deeper level during the matching
+ process.
Do not confuse the (?R) item with the condition (R), which tests for
recursion. Consider this pattern, which matches text in angle brack-
@@ -8439,16 +8767,16 @@ RECURSIVE PATTERNS
< (?: (?(R) \d++ | [^<>]*+) | (?R)) * >
- In this pattern, (?(R) is the start of a conditional subpattern, with
- two different alternatives for the recursive and non-recursive cases.
- The (?R) item is the actual recursive call.
+ In this pattern, (?(R) is the start of a conditional group, with two
+ different alternatives for the recursive and non-recursive cases. The
+ (?R) item is the actual recursive call.
Differences in recursion processing between PCRE2 and Perl
Some former differences between PCRE2 and Perl no longer exist.
Before release 10.30, recursion processing in PCRE2 differed from Perl
- in that a recursive subpattern call was always treated as an atomic
+ in that a recursive subroutine call was always treated as an atomic
group. That is, once it had matched some of the subject string, it was
never re-entered, even if it contained untried alternatives and there
was a subsequent matching failure. (Historical note: PCRE implemented
@@ -8460,54 +8788,53 @@ RECURSIVE PATTERNS
now compatible with the way Perl works. If you want a subroutine call
to be atomic, you must explicitly enclose it in an atomic group.
- Supporting backtracking into recursions simplifies certain types of
- recursive pattern. For example, this pattern matches palindromic
- strings:
+ Supporting backtracking into recursions simplifies certain types of re-
+ cursive pattern. For example, this pattern matches palindromic strings:
^((.)(?1)\2|.?)$
- The second branch in the group matches a single central character in
- the palindrome when there are an odd number of characters, or nothing
- when there are an even number of characters, but in order to work it
- has to be able to try the second case when the rest of the pattern
+ The second branch in the group matches a single central character in
+ the palindrome when there are an odd number of characters, or nothing
+ when there are an even number of characters, but in order to work it
+ has to be able to try the second case when the rest of the pattern
match fails. If you want to match typical palindromic phrases, the pat-
- tern has to ignore all non-word characters, which can be done like
+ tern has to ignore all non-word characters, which can be done like
this:
^\W*+((.)\W*+(?1)\W*+\2|\W*+.?)\W*+$
- If run with the PCRE2_CASELESS option, this pattern matches phrases
- such as "A man, a plan, a canal: Panama!". Note the use of the posses-
- sive quantifier *+ to avoid backtracking into sequences of non-word
+ If run with the PCRE2_CASELESS option, this pattern matches phrases
+ such as "A man, a plan, a canal: Panama!". Note the use of the posses-
+ sive quantifier *+ to avoid backtracking into sequences of non-word
characters. Without this, PCRE2 takes a great deal longer (ten times or
- more) to match typical phrases, and Perl takes so long that you think
+ more) to match typical phrases, and Perl takes so long that you think
it has gone into a loop.
- Another way in which PCRE2 and Perl used to differ in their recursion
- processing is in the handling of captured values. Formerly in Perl,
- when a subpattern was called recursively or as a subpattern (see the
- next section), it had no access to any values that were captured out-
- side the recursion, whereas in PCRE2 these values can be referenced.
- Consider this pattern:
+ Another way in which PCRE2 and Perl used to differ in their recursion
+ processing is in the handling of captured values. Formerly in Perl,
+ when a group was called recursively or as a subroutine (see the next
+ section), it had no access to any values that were captured outside the
+ recursion, whereas in PCRE2 these values can be referenced. Consider
+ this pattern:
^(.)(\1|a(?2))
- This pattern matches "bab". The first capturing parentheses match "b",
+ This pattern matches "bab". The first capturing parentheses match "b",
then in the second group, when the backreference \1 fails to match "b",
the second alternative matches "a" and then recurses. In the recursion,
- \1 does now match "b" and so the whole match succeeds. This match used
+ \1 does now match "b" and so the whole match succeeds. This match used
to fail in Perl, but in later versions (I tried 5.024) it now works.
-SUBPATTERNS AS SUBROUTINES
+GROUPS AS SUBROUTINES
- If the syntax for a recursive subpattern call (either by number or by
- name) is used outside the parentheses to which it refers, it operates a
- bit like a subroutine in a programming language. More accurately, PCRE2
- treats the referenced subpattern as an independent subpattern which it
- tries to match at the current matching position. The called subpattern
- may be defined before or after the reference. A numbered reference can
- be absolute or relative, as in these examples:
+ If the syntax for a recursive group call (either by number or by name)
+ is used outside the parentheses to which it refers, it operates a bit
+ like a subroutine in a programming language. More accurately, PCRE2
+ treats the referenced group as an independent subpattern which it tries
+ to match at the current matching position. The called group may be de-
+ fined before or after the reference. A numbered reference can be abso-
+ lute or relative, as in these examples:
(...(absolute)...)...(?2)...
(...(relative)...)...(?-1)...
@@ -8517,106 +8844,106 @@ SUBPATTERNS AS SUBROUTINES
(sens|respons)e and \1ibility
- matches "sense and sensibility" and "response and responsibility", but
+ matches "sense and sensibility" and "response and responsibility", but
not "sense and responsibility". If instead the pattern
(sens|respons)e and (?1)ibility
- is used, it does match "sense and responsibility" as well as the other
- two strings. Another example is given in the discussion of DEFINE
+ is used, it does match "sense and responsibility" as well as the other
+ two strings. Another example is given in the discussion of DEFINE
above.
- Like recursions, subroutine calls used to be treated as atomic, but
- this changed at PCRE2 release 10.30, so backtracking into subroutine
- calls can now occur. However, any capturing parentheses that are set
+ Like recursions, subroutine calls used to be treated as atomic, but
+ this changed at PCRE2 release 10.30, so backtracking into subroutine
+ calls can now occur. However, any capturing parentheses that are set
during the subroutine call revert to their previous values afterwards.
- Processing options such as case-independence are fixed when a subpat-
- tern is defined, so if it is used as a subroutine, such options cannot
- be changed for different calls. For example, consider this pattern:
+ Processing options such as case-independence are fixed when a group is
+ defined, so if it is used as a subroutine, such options cannot be
+ changed for different calls. For example, consider this pattern:
(abc)(?i:(?-1))
- It matches "abcabc". It does not match "abcABC" because the change of
- processing option does not affect the called subpattern.
+ It matches "abcabc". It does not match "abcABC" because the change of
+ processing option does not affect the called group.
- The behaviour of backtracking control verbs in subpatterns when called
- as subroutines is described in the section entitled "Backtracking verbs
- in subroutines" below.
+ The behaviour of backtracking control verbs in groups when called as
+ subroutines is described in the section entitled "Backtracking verbs in
+ subroutines" below.
ONIGURUMA SUBROUTINE SYNTAX
- For compatibility with Oniguruma, the non-Perl syntax \g followed by a
+ For compatibility with Oniguruma, the non-Perl syntax \g followed by a
name or a number enclosed either in angle brackets or single quotes, is
- an alternative syntax for referencing a subpattern as a subroutine,
- possibly recursively. Here are two of the examples used above, rewrit-
- ten using this syntax:
+ an alternative syntax for calling a group as a subroutine, possibly re-
+ cursively. Here are two of the examples used above, rewritten using
+ this syntax:
(? \( ( (?>[^()]+) | \g )* \) )
(sens|respons)e and \g'1'ibility
- PCRE2 supports an extension to Oniguruma: if a number is preceded by a
+ PCRE2 supports an extension to Oniguruma: if a number is preceded by a
plus or a minus sign it is taken as a relative reference. For example:
(abc)(?i:\g<-1>)
- Note that \g{...} (Perl syntax) and \g<...> (Oniguruma syntax) are not
- synonymous. The former is a backreference; the latter is a subroutine
+ Note that \g{...} (Perl syntax) and \g<...> (Oniguruma syntax) are not
+ synonymous. The former is a backreference; the latter is a subroutine
call.
CALLOUTS
Perl has a feature whereby using the sequence (?{...}) causes arbitrary
- Perl code to be obeyed in the middle of matching a regular expression.
+ Perl code to be obeyed in the middle of matching a regular expression.
This makes it possible, amongst other things, to extract different sub-
strings that match the same pair of parentheses when there is a repeti-
tion.
- PCRE2 provides a similar feature, but of course it cannot obey arbi-
- trary Perl code. The feature is called "callout". The caller of PCRE2
- provides an external function by putting its entry point in a match
- context using the function pcre2_set_callout(), and then passing that
- context to pcre2_match() or pcre2_dfa_match(). If no match context is
+ PCRE2 provides a similar feature, but of course it cannot obey arbi-
+ trary Perl code. The feature is called "callout". The caller of PCRE2
+ provides an external function by putting its entry point in a match
+ context using the function pcre2_set_callout(), and then passing that
+ context to pcre2_match() or pcre2_dfa_match(). If no match context is
passed, or if the callout entry point is set to NULL, callouts are dis-
abled.
- Within a regular expression, (?C) indicates a point at which the
- external function is to be called. There are two kinds of callout:
- those with a numerical argument and those with a string argument. (?C)
- on its own with no argument is treated as (?C0). A numerical argument
- allows the application to distinguish between different callouts.
- String arguments were added for release 10.20 to make it possible for
- script languages that use PCRE2 to embed short scripts within patterns
+ Within a regular expression, (?C) indicates a point at which the
+ external function is to be called. There are two kinds of callout:
+ those with a numerical argument and those with a string argument. (?C)
+ on its own with no argument is treated as (?C0). A numerical argument
+ allows the application to distinguish between different callouts.
+ String arguments were added for release 10.20 to make it possible for
+ script languages that use PCRE2 to embed short scripts within patterns
in a similar way to Perl.
During matching, when PCRE2 reaches a callout point, the external func-
- tion is called. It is provided with the number or string argument of
- the callout, the position in the pattern, and one item of data that is
+ tion is called. It is provided with the number or string argument of
+ the callout, the position in the pattern, and one item of data that is
also set in the match block. The callout function may cause matching to
proceed, to backtrack, or to fail.
- By default, PCRE2 implements a number of optimizations at matching
- time, and one side-effect is that sometimes callouts are skipped. If
- you need all possible callouts to happen, you need to set options that
- disable the relevant optimizations. More details, including a complete
- description of the programming interface to the callout function, are
+ By default, PCRE2 implements a number of optimizations at matching
+ time, and one side-effect is that sometimes callouts are skipped. If
+ you need all possible callouts to happen, you need to set options that
+ disable the relevant optimizations. More details, including a complete
+ description of the programming interface to the callout function, are
given in the pcre2callout documentation.
Callouts with numerical arguments
- If you just want to have a means of identifying different callout
- points, put a number less than 256 after the letter C. For example,
+ If you just want to have a means of identifying different callout
+ points, put a number less than 256 after the letter C. For example,
this pattern has two callout points:
(?C1)abc(?C2)def
- If the PCRE2_AUTO_CALLOUT flag is passed to pcre2_compile(), numerical
- callouts are automatically installed before each item in the pattern.
- They are all numbered 255. If there is a conditional group in the pat-
+ If the PCRE2_AUTO_CALLOUT flag is passed to pcre2_compile(), numerical
+ callouts are automatically installed before each item in the pattern.
+ They are all numbered 255. If there is a conditional group in the pat-
tern whose condition is an assertion, an additional callout is inserted
- just before the condition. An explicit callout may also be set at this
+ just before the condition. An explicit callout may also be set at this
position, as in this example:
(?(?C9)(?=a)abc|def)
@@ -8626,25 +8953,26 @@ CALLOUTS
Callouts with string arguments
- A delimited string may be used instead of a number as a callout argu-
- ment. The starting delimiter must be one of ` ' " ^ % # $ { and the
+ A delimited string may be used instead of a number as a callout argu-
+ ment. The starting delimiter must be one of ` ' " ^ % # $ { and the
ending delimiter is the same as the start, except for {, where the end-
- ing delimiter is }. If the ending delimiter is needed within the
+ ing delimiter is }. If the ending delimiter is needed within the
string, it must be doubled. For example:
(?C'ab ''c'' d')xyz(?C{any text})pqr
- The doubling is removed before the string is passed to the callout
+ The doubling is removed before the string is passed to the callout
function.
BACKTRACKING CONTROL
- There are a number of special "Backtracking Control Verbs" (to use
- Perl's terminology) that modify the behaviour of backtracking during
- matching. They are generally of the form (*VERB) or (*VERB:NAME). Some
- verbs take either form, possibly behaving differently depending on
- whether or not a name is present.
+ There are a number of special "Backtracking Control Verbs" (to use
+ Perl's terminology) that modify the behaviour of backtracking during
+ matching. They are generally of the form (*VERB) or (*VERB:NAME). Some
+ verbs take either form, and may behave differently depending on whether
+ or not a name argument is present. The names are not required to be
+ unique within the pattern.
By default, for compatibility with Perl, a name is any sequence of
characters that does not include a closing parenthesis. The name is not
@@ -8670,7 +8998,7 @@ BACKTRACKING CONTROL
the 16-bit and 32-bit libraries. If the name is empty, that is, if the
closing parenthesis immediately follows the colon, the effect is as if
the colon were not there. Any number of these verbs may occur in a pat-
- tern.
+ tern. Except for (*ACCEPT), they may not be quantified.
Since these verbs are specifically related to backtracking, most of
them can be used only when the pattern is to be matched using the tra-
@@ -8680,8 +9008,8 @@ BACKTRACKING CONTROL
by the DFA matching function.
The behaviour of these verbs in repeated groups, assertions, and in
- subpatterns called as subroutines (whether or not recursively) is docu-
- mented below.
+ capture groups called as subroutines (whether or not recursively) is
+ documented below.
Optimizations that affect backtracking verbs
@@ -8706,8 +9034,8 @@ BACKTRACKING CONTROL
(*ACCEPT) or (*ACCEPT:NAME)
This verb causes the match to end successfully, skipping the remainder
- of the pattern. However, when it is inside a subpattern that is called
- as a subroutine, only that subpattern is ended successfully. Matching
+ of the pattern. However, when it is inside a capture group that is
+ called as a subroutine, only that group is ended successfully. Matching
then continues at the outer level. If (*ACCEPT) in triggered in a posi-
tive assertion, the assertion succeeds; in a negative assertion, the
assertion fails.
@@ -8720,6 +9048,22 @@ BACKTRACKING CONTROL
This matches "AB", "AAD", or "ACD"; when it matches "AB", "B" is cap-
tured by the outer parentheses.
+ (*ACCEPT) is the only backtracking verb that is allowed to be quanti-
+ fied because an ungreedy quantification with a minimum of zero acts
+ only when a backtrack happens. Consider, for example,
+
+ (A(*ACCEPT)??B)C
+
+ where A, B, and C may be complex expressions. After matching "A", the
+ matcher processes "BC"; if that fails, causing a backtrack, (*ACCEPT)
+ is triggered and the match succeeds. In both cases, all but C is cap-
+ tured. Whereas (*COMMIT) (see below) means "fail on backtrack", a re-
+ peated (*ACCEPT) of this type means "succeed on backtrack".
+
+ Warning: (*ACCEPT) should not be used within a script run group, be-
+ cause it causes an immediate exit from the group, bypassing the script
+ run checking.
+
(*FAIL) or (*FAIL:NAME)
This verb causes a matching failure, forcing backtracking to occur. It
@@ -8734,35 +9078,33 @@ BACKTRACKING CONTROL
A match with the string "aaaa" always fails, but the callout is taken
before each backtrack happens (in this example, 10 times).
- (*ACCEPT:NAME) and (*FAIL:NAME) behave exactly the same as
- (*MARK:NAME)(*ACCEPT) and (*MARK:NAME)(*FAIL), respectively.
+ (*ACCEPT:NAME) and (*FAIL:NAME) behave the same as (*MARK:NAME)(*AC-
+ CEPT) and (*MARK:NAME)(*FAIL), respectively, that is, a (*MARK) is
+ recorded just before the verb acts.
Recording which path was taken
- There is one verb whose main purpose is to track how a match was
- arrived at, though it also has a secondary use in conjunction with
- advancing the match starting point (see (*SKIP) below).
+ There is one verb whose main purpose is to track how a match was ar-
+ rived at, though it also has a secondary use in conjunction with ad-
+ vancing the match starting point (see (*SKIP) below).
(*MARK:NAME) or (*:NAME)
- A name is always required with this verb. There may be as many
- instances of (*MARK) as you like in a pattern, and their names do not
- have to be unique.
+ A name is always required with this verb. For all the other backtrack-
+ ing control verbs, a NAME argument is optional.
- When a match succeeds, the name of the last-encountered (*MARK:NAME) on
+ When a match succeeds, the name of the last-encountered mark name on
the matching path is passed back to the caller as described in the sec-
tion entitled "Other information about the match" in the pcre2api docu-
- mentation. This applies to all instances of (*MARK), including those
- inside assertions and atomic groups. (There are differences in those
- cases when (*MARK) is used in conjunction with (*SKIP) as described
- below.)
+ mentation. This applies to all instances of (*MARK) and other verbs,
+ including those inside assertions and atomic groups. However, there are
+ differences in those cases when (*MARK) is used in conjunction with
+ (*SKIP) as described below.
- As well as (*MARK), the (*COMMIT), (*PRUNE) and (*THEN) verbs may have
- associated NAME arguments. Whichever is last on the matching path is
- passed back. See below for more details of these other verbs.
-
- Here is an example of pcre2test output, where the "mark" modifier
- requests the retrieval and outputting of (*MARK) data:
+ The mark name that was last encountered on the matching path is passed
+ back. A verb without a NAME argument is ignored for this purpose. Here
+ is an example of pcre2test output, where the "mark" modifier requests
+ the retrieval and outputting of (*MARK) data:
re> /X(*MARK:A)Y|X(*MARK:B)Z/mark
data> XY
@@ -8808,7 +9150,7 @@ BACKTRACKING CONTROL
that is true, its effect is confined to that group, because once the
group has been matched, there is never any backtracking into it. Back-
tracking from beyond an assertion or an atomic group ignores the entire
- group, and seeks a preceeding backtracking point.
+ group, and seeks a preceding backtracking point.
These verbs differ in exactly what kind of failure occurs when back-
tracking reaches them. The behaviour described below is what happens
@@ -8833,16 +9175,16 @@ BACKTRACKING CONTROL
The behaviour of (*COMMIT:NAME) is not the same as (*MARK:NAME)(*COM-
MIT). It is like (*MARK:NAME) in that the name is remembered for pass-
ing back to the caller. However, (*SKIP:NAME) searches only for names
- set with (*MARK), ignoring those set by (*COMMIT), (*PRUNE) and
- (*THEN).
+ that are set with (*MARK), ignoring those set by any of the other back-
+ tracking verbs.
If there is more than one backtracking verb in a pattern, a different
one that follows (*COMMIT) may be triggered first, so merely passing
(*COMMIT) during a match does not always guarantee that a match must be
at this starting point.
- Note that (*COMMIT) at the start of a pattern is not the same as an
- anchor, unless PCRE2's start-of-match optimizations are turned off, as
+ Note that (*COMMIT) at the start of a pattern is not the same as an an-
+ chor, unless PCRE2's start-of-match optimizations are turned off, as
shown in this output from pcre2test:
re> /(*COMMIT)abc/
@@ -8878,7 +9220,7 @@ BACKTRACKING CONTROL
The behaviour of (*PRUNE:NAME) is not the same as (*MARK:NAME)(*PRUNE).
It is like (*MARK:NAME) in that the name is remembered for passing back
to the caller. However, (*SKIP:NAME) searches only for names set with
- (*MARK), ignoring those set by (*COMMIT), (*PRUNE) or (*THEN).
+ (*MARK), ignoring those set by other backtracking verbs.
(*SKIP)
@@ -8895,21 +9237,26 @@ BACKTRACKING CONTROL
(starting at the first character in the string), the starting point
skips on to start the next attempt at "c". Note that a possessive quan-
tifer does not have the same effect as this example; although it would
- suppress backtracking during the first match attempt, the second
- attempt would start at the second character instead of skipping on to
+ suppress backtracking during the first match attempt, the second at-
+ tempt would start at the second character instead of skipping on to
"c".
+ If (*SKIP) is used to specify a new starting position that is the same
+ as the starting position of the current match, or (by being inside a
+ lookbehind) earlier, the position specified by (*SKIP) is ignored, and
+ instead the normal "bumpalong" occurs.
+
(*SKIP:NAME)
- When (*SKIP) has an associated name, its behaviour is modified. When
- such a (*SKIP) is triggered, the previous path through the pattern is
- searched for the most recent (*MARK) that has the same name. If one is
- found, the "bumpalong" advance is to the subject position that corre-
- sponds to that (*MARK) instead of to where (*SKIP) was encountered. If
+ When (*SKIP) has an associated name, its behaviour is modified. When
+ such a (*SKIP) is triggered, the previous path through the pattern is
+ searched for the most recent (*MARK) that has the same name. If one is
+ found, the "bumpalong" advance is to the subject position that corre-
+ sponds to that (*MARK) instead of to where (*SKIP) was encountered. If
no (*MARK) with a matching name is found, the (*SKIP) is ignored.
- The search for a (*MARK) name uses the normal backtracking mechanism,
- which means that it does not see (*MARK) settings that are inside
+ The search for a (*MARK) name uses the normal backtracking mechanism,
+ which means that it does not see (*MARK) settings that are inside
atomic groups or assertions, because they are never re-entered by back-
tracking. Compare the following pcre2test examples:
@@ -8923,19 +9270,18 @@ BACKTRACKING CONTROL
0: b
1: b
- In the first example, the (*MARK) setting is in an atomic group, so it
+ In the first example, the (*MARK) setting is in an atomic group, so it
is not seen when (*SKIP:X) triggers, causing the (*SKIP) to be ignored.
- This allows the second branch of the pattern to be tried at the first
- character position. In the second example, the (*MARK) setting is not
- in an atomic group. This allows (*SKIP:X) to find the (*MARK) when it
+ This allows the second branch of the pattern to be tried at the first
+ character position. In the second example, the (*MARK) setting is not
+ in an atomic group. This allows (*SKIP:X) to find the (*MARK) when it
backtracks, and this causes a new matching attempt to start at the sec-
- ond character. This time, the (*MARK) is never seen because "a" does
+ ond character. This time, the (*MARK) is never seen because "a" does
not match "b", so the matcher immediately jumps to the second branch of
the pattern.
- Note that (*SKIP:NAME) searches only for names set by (*MARK:NAME). It
- ignores names that are set by (*COMMIT:NAME), (*PRUNE:NAME) or
- (*THEN:NAME).
+ Note that (*SKIP:NAME) searches only for names set by (*MARK:NAME). It
+ ignores names that are set by other backtracking verbs.
(*THEN) or (*THEN:NAME)
@@ -8951,50 +9297,50 @@ BACKTRACKING CONTROL
skips to the second alternative and tries COND2, without backtracking
into COND1. If that succeeds and BAR fails, COND3 is tried. If subse-
quently BAZ fails, there are no more alternatives, so there is a back-
- track to whatever came before the entire group. If (*THEN) is not
- inside an alternation, it acts like (*PRUNE).
+ track to whatever came before the entire group. If (*THEN) is not in-
+ side an alternation, it acts like (*PRUNE).
The behaviour of (*THEN:NAME) is not the same as (*MARK:NAME)(*THEN).
It is like (*MARK:NAME) in that the name is remembered for passing back
to the caller. However, (*SKIP:NAME) searches only for names set with
- (*MARK), ignoring those set by (*COMMIT), (*PRUNE) and (*THEN).
+ (*MARK), ignoring those set by other backtracking verbs.
- A subpattern that does not contain a | character is just a part of the
- enclosing alternative; it is not a nested alternation with only one
- alternative. The effect of (*THEN) extends beyond such a subpattern to
- the enclosing alternative. Consider this pattern, where A, B, etc. are
- complex pattern fragments that do not contain any | characters at this
+ A group that does not contain a | character is just a part of the en-
+ closing alternative; it is not a nested alternation with only one al-
+ ternative. The effect of (*THEN) extends beyond such a group to the en-
+ closing alternative. Consider this pattern, where A, B, etc. are com-
+ plex pattern fragments that do not contain any | characters at this
level:
A (B(*THEN)C) | D
If A and B are matched, but there is a failure in C, matching does not
backtrack into A; instead it moves to the next alternative, that is, D.
- However, if the subpattern containing (*THEN) is given an alternative,
- it behaves differently:
+ However, if the group containing (*THEN) is given an alternative, it
+ behaves differently:
A (B(*THEN)C | (*FAIL)) | D
- The effect of (*THEN) is now confined to the inner subpattern. After a
- failure in C, matching moves to (*FAIL), which causes the whole subpat-
- tern to fail because there are no more alternatives to try. In this
- case, matching does now backtrack into A.
+ The effect of (*THEN) is now confined to the inner group. After a fail-
+ ure in C, matching moves to (*FAIL), which causes the whole group to
+ fail because there are no more alternatives to try. In this case,
+ matching does backtrack into A.
- Note that a conditional subpattern is not considered as having two
- alternatives, because only one is ever used. In other words, the |
- character in a conditional subpattern has a different meaning. Ignoring
- white space, consider:
+ Note that a conditional group is not considered as having two alterna-
+ tives, because only one is ever used. In other words, the | character
+ in a conditional group has a different meaning. Ignoring white space,
+ consider:
^.*? (?(?=a) a | b(*THEN)c )
- If the subject is "ba", this pattern does not match. Because .*? is
- ungreedy, it initially matches zero characters. The condition (?=a)
- then fails, the character "b" is matched, but "c" is not. At this
- point, matching does not backtrack to .*? as might perhaps be expected
- from the presence of the | character. The conditional subpattern is
- part of the single alternative that comprises the whole pattern, and so
- the match fails. (If there was a backtrack into .*?, allowing it to
- match "b", the match would succeed.)
+ If the subject is "ba", this pattern does not match. Because .*? is un-
+ greedy, it initially matches zero characters. The condition (?=a) then
+ fails, the character "b" is matched, but "c" is not. At this point,
+ matching does not backtrack to .*? as might perhaps be expected from
+ the presence of the | character. The conditional group is part of the
+ single alternative that comprises the whole pattern, and so the match
+ fails. (If there was a backtrack into .*?, allowing it to match "b",
+ the match would succeed.)
The verbs just described provide four different "strengths" of control
when subsequent matching fails. (*THEN) is the weakest, carrying on the
@@ -9041,24 +9387,32 @@ BACKTRACKING CONTROL
(*FAIL) in any assertion has its normal effect: it forces an immediate
backtrack. The behaviour of the other backtracking verbs depends on
whether or not the assertion is standalone or acting as the condition
- in a conditional subpattern.
+ in a conditional group.
(*ACCEPT) in a standalone positive assertion causes the assertion to
- succeed without any further processing; captured strings and a (*MARK)
- name (if set) are retained. In a standalone negative assertion,
- (*ACCEPT) causes the assertion to fail without any further processing;
- captured substrings and any (*MARK) name are discarded.
+ succeed without any further processing; captured strings and a mark
+ name (if set) are retained. In a standalone negative assertion, (*AC-
+ CEPT) causes the assertion to fail without any further processing; cap-
+ tured substrings and any mark name are discarded.
If the assertion is a condition, (*ACCEPT) causes the condition to be
true for a positive assertion and false for a negative one; captured
substrings are retained in both cases.
The remaining verbs act only when a later failure causes a backtrack to
- reach them. This means that their effect is confined to the assertion,
- because lookaround assertions are atomic. A backtrack that occurs after
- an assertion is complete does not jump back into the assertion. Note in
- particular that a (*MARK) name that is set in an assertion is not
- "seen" by an instance of (*SKIP:NAME) latter in the pattern.
+ reach them. This means that, for the Perl-compatible assertions, their
+ effect is confined to the assertion, because Perl lookaround assertions
+ are atomic. A backtrack that occurs after such an assertion is complete
+ does not jump back into the assertion. Note in particular that a
+ (*MARK) name that is set in an assertion is not "seen" by an instance
+ of (*SKIP:NAME) later in the pattern.
+
+ PCRE2 now supports non-atomic positive assertions, as described in the
+ section entitled "Non-atomic assertions" above. These assertions must
+ be standalone (not used as conditions). They are not Perl-compatible.
+ For these assertions, a later backtrack does jump back into the asser-
+ tion, and therefore verbs such as (*COMMIT) can be triggered by back-
+ tracks from later in the pattern.
The effect of (*THEN) is not allowed to escape beyond an assertion. If
there are no more branches to try, (*THEN) causes a positive assertion
@@ -9074,26 +9428,24 @@ BACKTRACKING CONTROL
Backtracking verbs in subroutines
- These behaviours occur whether or not the subpattern is called recur-
- sively.
+ These behaviours occur whether or not the group is called recursively.
- (*ACCEPT) in a subpattern called as a subroutine causes the subroutine
- match to succeed without any further processing. Matching then contin-
- ues after the subroutine call. Perl documents this behaviour. Perl's
- treatment of the other verbs in subroutines is different in some cases.
+ (*ACCEPT) in a group called as a subroutine causes the subroutine match
+ to succeed without any further processing. Matching then continues af-
+ ter the subroutine call. Perl documents this behaviour. Perl's treat-
+ ment of the other verbs in subroutines is different in some cases.
- (*FAIL) in a subpattern called as a subroutine has its normal effect:
- it forces an immediate backtrack.
+ (*FAIL) in a group called as a subroutine has its normal effect: it
+ forces an immediate backtrack.
- (*COMMIT), (*SKIP), and (*PRUNE) cause the subroutine match to fail
- when triggered by being backtracked to in a subpattern called as a sub-
- routine. There is then a backtrack at the outer level.
+ (*COMMIT), (*SKIP), and (*PRUNE) cause the subroutine match to fail
+ when triggered by being backtracked to in a group called as a subrou-
+ tine. There is then a backtrack at the outer level.
(*THEN), when triggered, skips to the next alternative in the innermost
- enclosing group within the subpattern that has alternatives (its normal
- behaviour). However, if there is no such group within the subroutine
- subpattern, the subroutine match fails and there is a backtrack at the
- outer level.
+ enclosing group that has alternatives (its normal behaviour). However,
+ if there is no such group within the subroutine's group, the subroutine
+ match fails and there is a backtrack at the outer level.
SEE ALSO
@@ -9111,8 +9463,8 @@ AUTHOR
REVISION
- Last updated: 04 September 2018
- Copyright (c) 1997-2018 University of Cambridge.
+ Last updated: 29 July 2019
+ Copyright (c) 1997-2019 University of Cambridge.
------------------------------------------------------------------------------
@@ -9136,9 +9488,9 @@ COMPILED PATTERN MEMORY USAGE
code, so that most simple patterns do not use much memory for storing
the compiled version. However, there is one case where the memory usage
of a compiled pattern can be unexpectedly large. If a parenthesized
- subpattern has a quantifier with a minimum greater than 1 and/or a lim-
- ited maximum, the whole subpattern is repeated in the compiled code.
- For example, the pattern
+ group has a quantifier with a minimum greater than 1 and/or a limited
+ maximum, the whole group is repeated in the compiled code. For example,
+ the pattern
(abc|def){2,4}
@@ -9195,9 +9547,9 @@ STACK AND HEAP USAGE AT RUN TIME
also reduce the memory requirements.
In contrast to pcre2_match(), pcre2_dfa_match() does use recursive
- function calls, but only for processing atomic groups, lookaround
- assertions, and recursion within the pattern. The original version of
- the code used to allocate quite large internal workspace vectors on the
+ function calls, but only for processing atomic groups, lookaround as-
+ sertions, and recursion within the pattern. The original version of the
+ code used to allocate quite large internal workspace vectors on the
stack, which caused some problems for some patterns in environments
with small stacks. From release 10.32 the code for pcre2_dfa_match()
has been re-factored to use heap memory when necessary for internal
@@ -9217,8 +9569,8 @@ PROCESSING TIME
(a|e|i|o|u). In general, the simplest construction that provides the
required behaviour is usually the most efficient. Jeffrey Friedl's book
contains a lot of useful general discussion about optimizing regular
- expressions for efficient performance. This document contains a few
- observations about PCRE2.
+ expressions for efficient performance. This document contains a few ob-
+ servations about PCRE2.
Using Unicode character properties (the \p, \P, and \X escapes) is
slow, because PCRE2 has to use a multi-stage table lookup whenever it
@@ -9239,11 +9591,11 @@ PROCESSING TIME
option is set, the pattern is implicitly anchored by PCRE2, since it
can match only at the start of a subject string. If the pattern has
multiple top-level branches, they must all be anchorable. The optimiza-
- tion can be disabled by the PCRE2_NO_DOTSTAR_ANCHOR option, and is
- automatically disabled if the pattern contains (*PRUNE) or (*SKIP).
+ tion can be disabled by the PCRE2_NO_DOTSTAR_ANCHOR option, and is au-
+ tomatically disabled if the pattern contains (*PRUNE) or (*SKIP).
- If PCRE2_DOTALL is not set, PCRE2 cannot make this optimization,
- because the dot metacharacter does not then match a newline, and if the
+ If PCRE2_DOTALL is not set, PCRE2 cannot make this optimization, be-
+ cause the dot metacharacter does not then match a newline, and if the
subject string contains newlines, the pattern may match from the char-
acter immediately following one of them instead of from the very start.
For example, the pattern
@@ -9257,8 +9609,8 @@ PROCESSING TIME
If you are using such a pattern with subject strings that do not con-
tain newlines, the best performance is obtained by setting
- PCRE2_DOTALL, or starting the pattern with ^.* or ^.*? to indicate
- explicit anchoring. That saves PCRE2 from having to scan along the sub-
+ PCRE2_DOTALL, or starting the pattern with ^.* or ^.*? to indicate ex-
+ plicit anchoring. That saves PCRE2 from having to scan along the sub-
ject looking for a newline to restart at.
Beware of patterns that contain nested indefinite repeats. These can
@@ -9272,8 +9624,8 @@ PROCESSING TIME
2, 3, or 4 times, and for each of those cases other than 0 or 4, the +
repeats can match different numbers of times.) When the remainder of
the pattern is such that the entire match is going to fail, PCRE2 has
- in principle to try every possible variation, and this can take an
- extremely long time, even for relatively short strings.
+ in principle to try every possible variation, and this can take an ex-
+ tremely long time, even for relatively short strings.
An optimization catches some of the more simple cases such as
@@ -9327,8 +9679,8 @@ PROCESSING TIME
matching, and on the amount of heap memory that is used. The default
values of the limits are very large, and unlikely ever to operate. They
can be changed when PCRE2 is built, and they can also be set when
- pcre2_match() or pcre2_dfa_match() is called. For details of these
- interfaces, see the pcre2build documentation and the section entitled
+ pcre2_match() or pcre2_dfa_match() is called. For details of these in-
+ terfaces, see the pcre2build documentation and the section entitled
"The match context" in the pcre2api documentation.
The pcre2test test program has a modifier called "find_limits" which,
@@ -9346,8 +9698,8 @@ AUTHOR
REVISION
- Last updated: 25 April 2018
- Copyright (c) 1997-2018 University of Cambridge.
+ Last updated: 03 February 2019
+ Copyright (c) 1997-2019 University of Cambridge.
------------------------------------------------------------------------------
@@ -9362,33 +9714,56 @@ SYNOPSIS
#include
- int regcomp(regex_t *preg, const char *pattern,
+ int pcre2_regcomp(regex_t *preg, const char *pattern,
int cflags);
- int regexec(const regex_t *preg, const char *string,
+ int pcre2_regexec(const regex_t *preg, const char *string,
size_t nmatch, regmatch_t pmatch[], int eflags);
- size_t regerror(int errcode, const regex_t *preg,
+ size_t pcre2_regerror(int errcode, const regex_t *preg,
char *errbuf, size_t errbuf_size);
- void regfree(regex_t *preg);
+ void pcre2_regfree(regex_t *preg);
DESCRIPTION
This set of functions provides a POSIX-style API for the PCRE2 regular
- expression 8-bit library. See the pcre2api documentation for a descrip-
- tion of PCRE2's native API, which contains much additional functional-
- ity. There are no POSIX-style wrappers for PCRE2's 16-bit and 32-bit
- libraries.
-
- The functions described here are just wrapper functions that ultimately
- call the PCRE2 native API. Their prototypes are defined in the
- pcre2posix.h header file, and on Unix systems the library itself is
- called libpcre2-posix.a, so can be accessed by adding -lpcre2-posix to
- the command for linking an application that uses them. Because the
- POSIX functions call the native ones, it is also necessary to add
- -lpcre2-8.
+ expression 8-bit library. There are no POSIX-style wrappers for PCRE2's
+ 16-bit and 32-bit libraries. See the pcre2api documentation for a de-
+ scription of PCRE2's native API, which contains much additional func-
+ tionality.
+
+ The functions described here are wrapper functions that ultimately call
+ the PCRE2 native API. Their prototypes are defined in the pcre2posix.h
+ header file, and they all have unique names starting with pcre2_. How-
+ ever, the pcre2posix.h header also contains macro definitions that con-
+ vert the standard POSIX names such regcomp() into pcre2_regcomp() etc.
+ This means that a program can use the usual POSIX names without running
+ the risk of accidentally linking with POSIX functions from a different
+ library.
+
+ On Unix-like systems the PCRE2 POSIX library is called libpcre2-posix,
+ so can be accessed by adding -lpcre2-posix to the command for linking
+ an application. Because the POSIX functions call the native ones, it is
+ also necessary to add -lpcre2-8.
+
+ Although they are not defined as protypes in pcre2posix.h, the library
+ does contain functions with the POSIX names regcomp() etc. These simply
+ pass their arguments to the PCRE2 functions. These functions are pro-
+ vided for backwards compatibility with earlier versions of PCRE2, so
+ that existing programs do not have to be recompiled.
+
+ Calling the header file pcre2posix.h avoids any conflict with other
+ POSIX libraries. It can, of course, be renamed or aliased as regex.h,
+ which is the "correct" name, if there is no clash. It provides two
+ structure types, regex_t for compiled internal forms, and regmatch_t
+ for returning captured substrings. It also defines some constants whose
+ names start with "REG_"; these are used for setting options and identi-
+ fying error codes.
+
+
+USING THE POSIX FUNCTIONS
Those POSIX option bits that can reasonably be mapped to PCRE2 native
options have been implemented. In addition, the option REG_EXTENDED is
@@ -9410,23 +9785,19 @@ DESCRIPTION
POSIX-compatible, and in multi-unit encoding domains it is probably
even less compatible.
- The header for these functions is supplied as pcre2posix.h to avoid any
- potential clash with other POSIX libraries. It can, of course, be
- renamed or aliased as regex.h, which is the "correct" name. It provides
- two structure types, regex_t for compiled internal forms, and reg-
- match_t for returning captured substrings. It also defines some con-
- stants whose names start with "REG_"; these are used for setting
- options and identifying error codes.
+ The descriptions below use the actual names of the functions, but, as
+ described above, the standard POSIX names (without the pcre2_ prefix)
+ may also be used.
COMPILING A PATTERN
- The function regcomp() is called to compile a pattern into an internal
- form. By default, the pattern is a C string terminated by a binary zero
- (but see REG_PEND below). The preg argument is a pointer to a regex_t
- structure that is used as a base for storing information about the com-
- piled regular expression. (It is also used for input when REG_PEND is
- set.)
+ The function pcre2_regcomp() is called to compile a pattern into an in-
+ ternal form. By default, the pattern is a C string terminated by a bi-
+ nary zero (but see REG_PEND below). The preg argument is a pointer to a
+ regex_t structure that is used as a base for storing information about
+ the compiled regular expression. (It is also used for input when
+ REG_PEND is set.)
The argument cflags is either zero, or contains one or more of the bits
defined by the following macros:
@@ -9460,21 +9831,23 @@ COMPILING A PATTERN
REG_NOSUB
- When a pattern that is compiled with this flag is passed to regexec()
- for matching, the nmatch and pmatch arguments are ignored, and no cap-
- tured strings are returned. Versions of the PCRE library prior to 10.22
- used to set the PCRE2_NO_AUTO_CAPTURE compile option, but this no
- longer happens because it disables the use of backreferences.
+ When a pattern that is compiled with this flag is passed to
+ pcre2_regexec() for matching, the nmatch and pmatch arguments are ig-
+ nored, and no captured strings are returned. Versions of the PCRE li-
+ brary prior to 10.22 used to set the PCRE2_NO_AUTO_CAPTURE compile op-
+ tion, but this no longer happens because it disables the use of back-
+ references.
REG_PEND
- If this option is set, the reg_endp field in the preg structure (which
+ If this option is set, the reg_endp field in the preg structure (which
has the type const char *) must be set to point to the character beyond
- the end of the pattern before calling regcomp(). The pattern itself may
- now contain binary zeros, which are treated as data characters. Without
- REG_PEND, a binary zero terminates the pattern and the re_endp field is
- ignored. This is a GNU extension to the POSIX standard and should be
- used with caution in software intended to be portable to other systems.
+ the end of the pattern before calling pcre2_regcomp(). The pattern it-
+ self may now contain binary zeros, which are treated as data charac-
+ ters. Without REG_PEND, a binary zero terminates the pattern and the
+ re_endp field is ignored. This is a GNU extension to the POSIX standard
+ and should be used with caution in software intended to be portable to
+ other systems.
REG_UCP
@@ -9497,30 +9870,31 @@ COMPILING A PATTERN
Note that REG_UTF is not part of the POSIX standard.
In the absence of these flags, no options are passed to the native
- function. This means the the regex is compiled with PCRE2 default
- semantics. In particular, the way it handles newline characters in the
+ function. This means the the regex is compiled with PCRE2 default se-
+ mantics. In particular, the way it handles newline characters in the
subject string is the Perl way, not the POSIX way. Note that setting
PCRE2_MULTILINE has only some of the effects specified for REG_NEWLINE.
It does not affect the way newlines are matched by the dot metacharac-
ter (they are not) or by a negative class such as [^a] (they are).
- The yield of regcomp() is zero on success, and non-zero otherwise. The
- preg structure is filled in on success, and one other member of the
- structure (as well as re_endp) is public: re_nsub contains the number
- of capturing subpatterns in the regular expression. Various error codes
- are defined in the header file.
+ The yield of pcre2_regcomp() is zero on success, and non-zero other-
+ wise. The preg structure is filled in on success, and one other member
+ of the structure (as well as re_endp) is public: re_nsub contains the
+ number of capturing subpatterns in the regular expression. Various er-
+ ror codes are defined in the header file.
- NOTE: If the yield of regcomp() is non-zero, you must not attempt to
- use the contents of the preg structure. If, for example, you pass it to
- regexec(), the result is undefined and your program is likely to crash.
+ NOTE: If the yield of pcre2_regcomp() is non-zero, you must not attempt
+ to use the contents of the preg structure. If, for example, you pass it
+ to pcre2_regexec(), the result is undefined and your program is likely
+ to crash.
MATCHING NEWLINE CHARACTERS
This area is not simple, because POSIX and Perl take different views of
- things. It is not possible to get PCRE2 to obey POSIX semantics, but
+ things. It is not possible to get PCRE2 to obey POSIX semantics, but
then PCRE2 was never intended to be a POSIX engine. The following table
- lists the different possibilities for matching newline characters in
+ lists the different possibilities for matching newline characters in
Perl and PCRE2:
Default Change with
@@ -9541,25 +9915,25 @@ MATCHING NEWLINE CHARACTERS
$ matches \n in middle no REG_NEWLINE
^ matches \n in middle no REG_NEWLINE
- This behaviour is not what happens when PCRE2 is called via its POSIX
- API. By default, PCRE2's behaviour is the same as Perl's, except that
- there is no equivalent for PCRE2_DOLLAR_ENDONLY in Perl. In both PCRE2
+ This behaviour is not what happens when PCRE2 is called via its POSIX
+ API. By default, PCRE2's behaviour is the same as Perl's, except that
+ there is no equivalent for PCRE2_DOLLAR_ENDONLY in Perl. In both PCRE2
and Perl, there is no way to stop newline from matching [^a].
- Default POSIX newline handling can be obtained by setting PCRE2_DOTALL
- and PCRE2_DOLLAR_ENDONLY when calling pcre2_compile() directly, but
- there is no way to make PCRE2 behave exactly as for the REG_NEWLINE
- action. When using the POSIX API, passing REG_NEWLINE to PCRE2's reg-
- comp() function causes PCRE2_MULTILINE to be passed to pcre2_compile(),
- and REG_DOTALL passes PCRE2_DOTALL. There is no way to pass PCRE2_DOL-
- LAR_ENDONLY.
+ Default POSIX newline handling can be obtained by setting PCRE2_DOTALL
+ and PCRE2_DOLLAR_ENDONLY when calling pcre2_compile() directly, but
+ there is no way to make PCRE2 behave exactly as for the REG_NEWLINE ac-
+ tion. When using the POSIX API, passing REG_NEWLINE to PCRE2's
+ pcre2_regcomp() function causes PCRE2_MULTILINE to be passed to
+ pcre2_compile(), and REG_DOTALL passes PCRE2_DOTALL. There is no way to
+ pass PCRE2_DOLLAR_ENDONLY.
MATCHING A PATTERN
- The function regexec() is called to match a compiled pattern preg
- against a given string, which is by default terminated by a zero byte
- (but see REG_STARTEND below), subject to the options in eflags. These
+ The function pcre2_regexec() is called to match a compiled pattern preg
+ against a given string, which is by default terminated by a zero byte
+ (but see REG_STARTEND below), subject to the options in eflags. These
can be:
REG_NOTBOL
@@ -9569,9 +9943,9 @@ MATCHING A PATTERN
REG_NOTEMPTY
- The PCRE2_NOTEMPTY option is set when calling the underlying PCRE2
- matching function. Note that REG_NOTEMPTY is not part of the POSIX
- standard. However, setting this option can give more POSIX-like behav-
+ The PCRE2_NOTEMPTY option is set when calling the underlying PCRE2
+ matching function. Note that REG_NOTEMPTY is not part of the POSIX
+ standard. However, setting this option can give more POSIX-like behav-
iour in some situations.
REG_NOTEOL
@@ -9581,32 +9955,33 @@ MATCHING A PATTERN
REG_STARTEND
- When this option is set, the subject string starts at string +
- pmatch[0].rm_so and ends at string + pmatch[0].rm_eo, which should
- point to the first character beyond the string. There may be binary
- zeros within the subject string, and indeed, using REG_STARTEND is the
+ When this option is set, the subject string starts at string +
+ pmatch[0].rm_so and ends at string + pmatch[0].rm_eo, which should
+ point to the first character beyond the string. There may be binary ze-
+ ros within the subject string, and indeed, using REG_STARTEND is the
only way to pass a subject string that contains a binary zero.
- Whatever the value of pmatch[0].rm_so, the offsets of the matched
- string and any captured substrings are still given relative to the
- start of string itself. (Before PCRE2 release 10.30 these were given
- relative to string + pmatch[0].rm_so, but this differs from other
- implementations.)
-
- This is a BSD extension, compatible with but not specified by IEEE
- Standard 1003.2 (POSIX.2), and should be used with caution in software
- intended to be portable to other systems. Note that a non-zero rm_so
- does not imply REG_NOTBOL; REG_STARTEND affects only the location and
- length of the string, not how it is matched. Setting REG_STARTEND and
- passing pmatch as NULL are mutually exclusive; the error REG_INVARG is
+ Whatever the value of pmatch[0].rm_so, the offsets of the matched
+ string and any captured substrings are still given relative to the
+ start of string itself. (Before PCRE2 release 10.30 these were given
+ relative to string + pmatch[0].rm_so, but this differs from other im-
+ plementations.)
+
+ This is a BSD extension, compatible with but not specified by IEEE
+ Standard 1003.2 (POSIX.2), and should be used with caution in software
+ intended to be portable to other systems. Note that a non-zero rm_so
+ does not imply REG_NOTBOL; REG_STARTEND affects only the location and
+ length of the string, not how it is matched. Setting REG_STARTEND and
+ passing pmatch as NULL are mutually exclusive; the error REG_INVARG is
returned.
- If the pattern was compiled with the REG_NOSUB flag, no data about any
- matched strings is returned. The nmatch and pmatch arguments of
- regexec() are ignored (except possibly as input for REG_STARTEND).
+ If the pattern was compiled with the REG_NOSUB flag, no data about any
+ matched strings is returned. The nmatch and pmatch arguments of
+ pcre2_regexec() are ignored (except possibly as input for REG_STAR-
+ TEND).
- The value of nmatch may be zero, and the value pmatch may be NULL
- (unless REG_STARTEND is set); in both these cases no data about any
+ The value of nmatch may be zero, and the value pmatch may be NULL (un-
+ less REG_STARTEND is set); in both these cases no data about any
matched strings is returned.
Otherwise, the portion of the string that was matched, and also any
@@ -9619,29 +9994,29 @@ MATCHING A PATTERN
elements relate to the capturing subpatterns of the regular expression.
Unused entries in the array have both structure members set to -1.
- A successful match yields a zero return; various error codes are
- defined in the header file, of which REG_NOMATCH is the "expected"
- failure code.
+ A successful match yields a zero return; various error codes are de-
+ fined in the header file, of which REG_NOMATCH is the "expected" fail-
+ ure code.
ERROR MESSAGES
- The regerror() function maps a non-zero errorcode from either regcomp()
- or regexec() to a printable message. If preg is not NULL, the error
- should have arisen from the use of that structure. A message terminated
- by a binary zero is placed in errbuf. If the buffer is too short, only
- the first errbuf_size - 1 characters of the error message are used. The
- yield of the function is the size of buffer needed to hold the whole
- message, including the terminating zero. This value is greater than
- errbuf_size if the message was truncated.
+ The pcre2_regerror() function maps a non-zero errorcode from either
+ pcre2_regcomp() or pcre2_regexec() to a printable message. If preg is
+ not NULL, the error should have arisen from the use of that structure.
+ A message terminated by a binary zero is placed in errbuf. If the buf-
+ fer is too short, only the first errbuf_size - 1 characters of the er-
+ ror message are used. The yield of the function is the size of buffer
+ needed to hold the whole message, including the terminating zero. This
+ value is greater than errbuf_size if the message was truncated.
MEMORY USAGE
Compiling a regular expression causes memory to be allocated and asso-
- ciated with the preg structure. The function regfree() frees all such
- memory, after which preg may no longer be used as a compiled expres-
- sion.
+ ciated with the preg structure. The function pcre2_regfree() frees all
+ such memory, after which preg may no longer be used as a compiled ex-
+ pression.
AUTHOR
@@ -9653,8 +10028,8 @@ AUTHOR
REVISION
- Last updated: 15 June 2017
- Copyright (c) 1997-2017 University of Cambridge.
+ Last updated: 30 January 2019
+ Copyright (c) 1997-2019 University of Cambridge.
------------------------------------------------------------------------------
@@ -9701,8 +10076,8 @@ PCRE2 SAMPLE PROGRAM
If PCRE2 is installed elsewhere, you may need to add additional options
to the command line. For example, on a Unix-like system that has PCRE2
- installed in /usr/local, you can compile the demonstration program
- using a command like this:
+ installed in /usr/local, you can compile the demonstration program us-
+ ing a command like this:
cc -o pcre2demo -I/usr/local/include pcre2demo.c \
-L/usr/local/lib -lpcre2-8
@@ -9714,8 +10089,8 @@ PCRE2 SAMPLE PROGRAM
./pcre2demo -g 'cat|dog' 'the dog sat on the cat'
Note that there is a much more comprehensive test program, called
- pcre2test, which supports many more facilities for testing regular
- expressions using all three PCRE2 libraries (8-bit, 16-bit, and 32-bit,
+ pcre2test, which supports many more facilities for testing regular ex-
+ pressions using all three PCRE2 libraries (8-bit, 16-bit, and 32-bit,
though not all three need be installed). The pcre2demo program is pro-
vided as a relatively simple coding example.
@@ -9851,26 +10226,26 @@ SAVING COMPILED PATTERNS
errorcode = fwrite(bytes, 1, bytescount, fd);
Note that the serialized data is binary data that may contain any of
- the 256 possible byte values. On systems that make a distinction
- between binary and non-binary data, be sure that the file is opened for
+ the 256 possible byte values. On systems that make a distinction be-
+ tween binary and non-binary data, be sure that the file is opened for
binary output.
Serializing a set of patterns leaves the original data untouched, so
they can still be used for matching. Their memory must eventually be
freed in the usual way by calling pcre2_code_free(). When you have fin-
ished with the byte stream, it too must be freed by calling pcre2_seri-
- alize_free(). If this function is called with a NULL argument, it
- returns immediately without doing anything.
+ alize_free(). If this function is called with a NULL argument, it re-
+ turns immediately without doing anything.
RE-USING PRECOMPILED PATTERNS
- In order to re-use a set of saved patterns you must first make the
- serialized byte stream available in main memory (for example, by read-
- ing from a file). The management of this memory block is up to the
- application. You can use the pcre2_serialize_get_number_of_codes()
- function to find out how many compiled patterns are in the serialized
- data without actually decoding the patterns:
+ In order to re-use a set of saved patterns you must first make the se-
+ rialized byte stream available in main memory (for example, by reading
+ from a file). The management of this memory block is up to the applica-
+ tion. You can use the pcre2_serialize_get_number_of_codes() function to
+ find out how many compiled patterns are in the serialized data without
+ actually decoding the patterns:
uint8_t *bytes = ;
int32_t number_of_codes = pcre2_serialize_get_number_of_codes(bytes);
@@ -9878,8 +10253,8 @@ RE-USING PRECOMPILED PATTERNS
The pcre2_serialize_decode() function reads a byte stream and recreates
the compiled patterns in new memory blocks, setting pointers to them in
a vector. The first two arguments are a pointer to a suitable vector
- and its length, and the third argument points to a byte stream. The
- final argument is a pointer to a general context, which can be used to
+ and its length, and the third argument points to a byte stream. The fi-
+ nal argument is a pointer to a general context, which can be used to
specify custom memory mangagement functions for the decoded patterns.
If this argument is NULL, malloc() and free() are used. After deserial-
ization, the byte stream is no longer needed and can be discarded.
@@ -9891,9 +10266,9 @@ RE-USING PRECOMPILED PATTERNS
pcre2_serialize_decode(list_of_codes, 2, bytes, NULL);
If the vector is not large enough for all the patterns in the byte
- stream, it is filled with those that fit, and the remainder are
- ignored. The yield of the function is the number of decoded patterns,
- or one of the following negative error codes:
+ stream, it is filled with those that fit, and the remainder are ig-
+ nored. The yield of the function is the number of decoded patterns, or
+ one of the following negative error codes:
PCRE2_ERROR_BADDATA second argument is zero or less
PCRE2_ERROR_BADMAGIC mismatch of id bytes in the data
@@ -9907,9 +10282,9 @@ RE-USING PRECOMPILED PATTERNS
Decoded patterns can be used for matching in the usual way, and must be
freed by calling pcre2_code_free(). However, be aware that there is a
- potential race issue if you are using multiple patterns that were
- decoded from a single byte stream in a multithreaded application. A
- single copy of the character tables is used by all the decoded patterns
+ potential race issue if you are using multiple patterns that were de-
+ coded from a single byte stream in a multithreaded application. A sin-
+ gle copy of the character tables is used by all the decoded patterns
and a reference count is used to arrange for its memory to be automati-
cally freed when the last pattern is freed, but there is no locking on
this reference count. Therefore, if you want to call pcre2_code_free()
@@ -9959,7 +10334,8 @@ QUOTING
ESCAPED CHARACTERS
- This table applies to ASCII and Unicode environments.
+ This table applies to ASCII and Unicode environments. An unrecognized
+ escape sequence causes an error.
\a alarm, that is, the BEL character (hex 07)
\cx "control-x", where x is any ASCII printing character
@@ -9971,26 +10347,32 @@ ESCAPED CHARACTERS
\0dd character with octal code 0dd
\ddd character with octal code ddd, or backreference
\o{ddd..} character with octal code ddd..
- \U "U" if PCRE2_ALT_BSUX is set (otherwise is an error)
\N{U+hh..} character with Unicode code point hh.. (Unicode mode only)
- \uhhhh character with hex code hhhh (if PCRE2_ALT_BSUX is set)
\xhh character with hex code hh
\x{hh..} character with hex code hh..
+ If PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX is set ("ALT_BSUX mode"), the
+ following are also recognized:
+
+ \U the character "U"
+ \uhhhh character with hex code hhhh
+ \u{hh..} character with hex code hh.. but only for EXTRA_ALT_BSUX
+
+ When \x is not followed by {, from zero to two hexadecimal digits are
+ read, but in ALT_BSUX mode \x must be followed by two hexadecimal dig-
+ its to be recognized as a hexadecimal escape; otherwise it matches a
+ literal "x". Likewise, if \u (in ALT_BSUX mode) is not followed by
+ four hexadecimal digits or (in EXTRA_ALT_BSUX mode) a sequence of hex
+ digits in curly brackets, it matches a literal "u".
+
Note that \0dd is always an octal code. The treatment of backslash fol-
- lowed by a non-zero digit is complicated; for details see the section
- "Non-printing characters" in the pcre2pattern documentation, where
- details of escape processing in EBCDIC environments are also given.
+ lowed by a non-zero digit is complicated; for details see the section
+ "Non-printing characters" in the pcre2pattern documentation, where de-
+ tails of escape processing in EBCDIC environments are also given.
\N{U+hh..} is synonymous with \x{hh..} in PCRE2 but is not supported in
- EBCDIC environments. Note that \N not followed by an opening curly
+ EBCDIC environments. Note that \N not followed by an opening curly
bracket has a different meaning (see below).
- When \x is not followed by {, from zero to two hexadecimal digits are
- read, but if PCRE2_ALT_BSUX is set, \x must be followed by two hexadec-
- imal digits to be recognized as a hexadecimal escape; otherwise it
- matches a literal "x". Likewise, if \u (in ALT_BSUX mode) is not fol-
- lowed by four hexadecimal digits, it matches a literal "u".
-
CHARACTER TYPES
@@ -10013,14 +10395,14 @@ CHARACTER TYPES
\W a "non-word" character
\X a Unicode extended grapheme cluster
- \C is dangerous because it may leave the current matching point in the
+ \C is dangerous because it may leave the current matching point in the
middle of a UTF-8 or UTF-16 character. The application can lock out the
- use of \C by setting the PCRE2_NEVER_BACKSLASH_C option. It is also
+ use of \C by setting the PCRE2_NEVER_BACKSLASH_C option. It is also
possible to build PCRE2 with the use of \C permanently disabled.
- By default, \d, \s, and \w match only ASCII characters, even in UTF-8
+ By default, \d, \s, and \w match only ASCII characters, even in UTF-8
mode or in the 16-bit and 32-bit libraries. However, if locale-specific
- matching is happening, \s and \w may also match characters with code
+ matching is happening, \s and \w may also match characters with code
points in the range 128-255. If the PCRE2_UCP option is set, the behav-
iour of these escape sequences is changed to use Unicode properties and
they match many more characters.
@@ -10089,29 +10471,30 @@ PCRE2 SPECIAL CATEGORY PROPERTIES FOR \p and \P
SCRIPT NAMES FOR \p AND \P
- Adlam, Ahom, Anatolian_Hieroglyphs, Arabic, Armenian, Avestan, Bali-
- nese, Bamum, Bassa_Vah, Batak, Bengali, Bhaiksuki, Bopomofo, Brahmi,
- Braille, Buginese, Buhid, Canadian_Aboriginal, Carian, Caucasian_Alba-
- nian, Chakma, Cham, Cherokee, Common, Coptic, Cuneiform, Cypriot,
- Cyrillic, Deseret, Devanagari, Dogra, Duployan, Egyptian_Hieroglyphs,
- Elbasan, Ethiopic, Georgian, Glagolitic, Gothic, Grantha, Greek,
- Gujarati, Gunjala_Gondi, Gurmukhi, Han, Hangul, Hanifi_Rohingya,
- Hanunoo, Hatran, Hebrew, Hiragana, Imperial_Aramaic, Inherited,
- Inscriptional_Pahlavi, Inscriptional_Parthian, Javanese, Kaithi, Kan-
- nada, Katakana, Kayah_Li, Kharoshthi, Khmer, Khojki, Khudawadi, Lao,
- Latin, Lepcha, Limbu, Linear_A, Linear_B, Lisu, Lycian, Lydian, Maha-
- jani, Makasar, Malayalam, Mandaic, Manichaean, Marchen, Masaram_Gondi,
- Medefaidrin, Meetei_Mayek, Mende_Kikakui, Meroitic_Cursive,
- Meroitic_Hieroglyphs, Miao, Modi, Mongolian, Mro, Multani, Myanmar,
- Nabataean, New_Tai_Lue, Newa, Nko, Nushu, Ogham, Ol_Chiki, Old_Hungar-
- ian, Old_Italic, Old_North_Arabian, Old_Permic, Old_Persian, Old_Sog-
- dian, Old_South_Arabian, Old_Turkic, Oriya, Osage, Osmanya,
- Pahawh_Hmong, Palmyrene, Pau_Cin_Hau, Phags_Pa, Phoenician,
- Psalter_Pahlavi, Rejang, Runic, Samaritan, Saurashtra, Sharada, Sha-
- vian, Siddham, SignWriting, Sinhala, Sogdian, Sora_Sompeng, Soyombo,
- Sundanese, Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tai_Tham,
- Tai_Viet, Takri, Tamil, Tangut, Telugu, Thaana, Thai, Tibetan, Tifi-
- nagh, Tirhuta, Ugaritic, Vai, Warang_Citi, Yi, Zanabazar_Square.
+ Adlam, Ahom, Anatolian_Hieroglyphs, Arabic, Armenian, Avestan, Bali-
+ nese, Bamum, Bassa_Vah, Batak, Bengali, Bhaiksuki, Bopomofo, Brahmi,
+ Braille, Buginese, Buhid, Canadian_Aboriginal, Carian, Caucasian_Alba-
+ nian, Chakma, Cham, Cherokee, Common, Coptic, Cuneiform, Cypriot,
+ Cyrillic, Deseret, Devanagari, Dogra, Duployan, Egyptian_Hieroglyphs,
+ Elbasan, Elymaic, Ethiopic, Georgian, Glagolitic, Gothic, Grantha,
+ Greek, Gujarati, Gunjala_Gondi, Gurmukhi, Han, Hangul, Hanifi_Rohingya,
+ Hanunoo, Hatran, Hebrew, Hiragana, Imperial_Aramaic, Inherited, In-
+ scriptional_Pahlavi, Inscriptional_Parthian, Javanese, Kaithi, Kannada,
+ Katakana, Kayah_Li, Kharoshthi, Khmer, Khojki, Khudawadi, Lao, Latin,
+ Lepcha, Limbu, Linear_A, Linear_B, Lisu, Lycian, Lydian, Mahajani,
+ Makasar, Malayalam, Mandaic, Manichaean, Marchen, Masaram_Gondi, Mede-
+ faidrin, Meetei_Mayek, Mende_Kikakui, Meroitic_Cursive, Meroitic_Hiero-
+ glyphs, Miao, Modi, Mongolian, Mro, Multani, Myanmar, Nabataean, Nandi-
+ nagari, New_Tai_Lue, Newa, Nko, Nushu, Nyakeng_Puachue_Hmong, Ogham,
+ Ol_Chiki, Old_Hungarian, Old_Italic, Old_North_Arabian, Old_Permic,
+ Old_Persian, Old_Sogdian, Old_South_Arabian, Old_Turkic, Oriya, Osage,
+ Osmanya, Pahawh_Hmong, Palmyrene, Pau_Cin_Hau, Phags_Pa, Phoenician,
+ Psalter_Pahlavi, Rejang, Runic, Samaritan, Saurashtra, Sharada, Sha-
+ vian, Siddham, SignWriting, Sinhala, Sogdian, Sora_Sompeng, Soyombo,
+ Sundanese, Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tai_Tham,
+ Tai_Viet, Takri, Tamil, Tangut, Telugu, Thaana, Thai, Tibetan, Tifi-
+ nagh, Tirhuta, Ugaritic, Vai, Wancho, Warang_Citi, Yi, Zan-
+ abazar_Square.
CHARACTER CLASSES
@@ -10193,18 +10576,23 @@ ALTERNATION
CAPTURING
- (...) capturing group
- (?...) named capturing group (Perl)
- (?'name'...) named capturing group (Perl)
- (?P...) named capturing group (Python)
- (?:...) non-capturing group
- (?|...) non-capturing group; reset group numbers for
- capturing groups in each alternative
+ (...) capture group
+ (?...) named capture group (Perl)
+ (?'name'...) named capture group (Perl)
+ (?P...) named capture group (Python)
+ (?:...) non-capture group
+ (?|...) non-capture group; reset group numbers for
+ capture groups in each alternative
+
+ In non-UTF modes, names may contain underscores and ASCII letters and
+ digits; in UTF modes, any Unicode letters and Unicode decimal digits
+ are permitted. In both cases, a name must not start with a digit.
ATOMIC GROUPS
- (?>...) atomic, non-capturing group
+ (?>...) atomic non-capture group
+ (*atomic:...) atomic non-capture group
COMMENT
@@ -10231,11 +10619,11 @@ OPTION SETTING
a mixture of setting and unsetting such as (?i-x) is allowed, but there
may be only one hyphen. Setting (but no unsetting) is allowed after (?^
for example (?^in). An option setting may appear at the start of a non-
- capturing group, for example (?i:...).
+ capture group, for example (?i:...).
- The following are recognized only at the very start of a pattern or
- after one of the newline or \R options with similar syntax. More than
- one of them may appear. For the first three, d is a decimal number.
+ The following are recognized only at the very start of a pattern or af-
+ ter one of the newline or \R options with similar syntax. More than one
+ of them may appear. For the first three, d is a decimal number.
(*LIMIT_DEPTH=d) set the backtracking limit to d
(*LIMIT_HEAP=d) set the heap size limit to d * 1024 bytes
@@ -10259,8 +10647,8 @@ OPTION SETTING
NEWLINE CONVENTION
- These are recognized only at the very start of the pattern or after
- option settings with a similar syntax.
+ These are recognized only at the very start of the pattern or after op-
+ tion settings with a similar syntax.
(*CR) carriage return only
(*LF) linefeed only
@@ -10272,8 +10660,8 @@ NEWLINE CONVENTION
WHAT \R MATCHES
- These are recognized only at the very start of the pattern or after
- option setting with a similar syntax.
+ These are recognized only at the very start of the pattern or after op-
+ tion setting with a similar syntax.
(*BSR_ANYCRLF) CR, LF, or CRLF
(*BSR_UNICODE) any Unicode newline sequence
@@ -10281,12 +10669,43 @@ WHAT \R MATCHES
LOOKAHEAD AND LOOKBEHIND ASSERTIONS
- (?=...) positive look ahead
- (?!...) negative look ahead
- (?<=...) positive look behind
- (?name) call subpattern by name (Python)
- \g call subpattern by name (Oniguruma)
- \g'name' call subpattern by name (Oniguruma)
- \g call subpattern by absolute number (Oniguruma)
- \g'n' call subpattern by absolute number (Oniguruma)
- \g<+n> call subpattern by relative number (PCRE2 extension)
- \g'+n' call subpattern by relative number (PCRE2 extension)
- \g<-n> call subpattern by relative number (PCRE2 extension)
- \g'-n' call subpattern by relative number (PCRE2 extension)
+ (?n) call subroutine by absolute number
+ (?+n) call subroutine by relative number
+ (?-n) call subroutine by relative number
+ (?&name) call subroutine by name (Perl)
+ (?P>name) call subroutine by name (Python)
+ \g call subroutine by name (Oniguruma)
+ \g'name' call subroutine by name (Oniguruma)
+ \g call subroutine by absolute number (Oniguruma)
+ \g'n' call subroutine by absolute number (Oniguruma)
+ \g<+n> call subroutine by relative number (PCRE2 extension)
+ \g'+n' call subroutine by relative number (PCRE2 extension)
+ \g<-n> call subroutine by relative number (PCRE2 extension)
+ \g'-n' call subroutine by relative number (PCRE2 extension)
CONDITIONAL PATTERNS
@@ -10337,7 +10756,7 @@ CONDITIONAL PATTERNS
(?(R) overall recursion condition
(?(Rn) specific numbered group recursion condition
(?(R&name) specific named group recursion condition
- (?(DEFINE) define subpattern for reference
+ (?(DEFINE) define groups for reference
(?(VERSION[>]=n.m) test PCRE2 version
(?(assert) assertion condition
@@ -10401,8 +10820,8 @@ AUTHOR
REVISION
- Last updated: 02 September 2018
- Copyright (c) 1997-2018 University of Cambridge.
+ Last updated: 29 July 2019
+ Copyright (c) 1997-2019 University of Cambridge.
------------------------------------------------------------------------------
@@ -10415,138 +10834,226 @@ NAME
UNICODE AND UTF SUPPORT
- When PCRE2 is built with Unicode support (which is the default), it has
- knowledge of Unicode character properties and can process text strings
- in UTF-8, UTF-16, or UTF-32 format (depending on the code unit width).
- However, by default, PCRE2 assumes that one code unit is one character.
- To process a pattern as a UTF string, where a character may require
- more than one code unit, you must call pcre2_compile() with the
- PCRE2_UTF option flag, or the pattern must start with the sequence
- (*UTF). When either of these is the case, both the pattern and any sub-
- ject strings that are matched against it are treated as UTF strings
- instead of strings of individual one-code-unit characters. There are
- also some other changes to the way characters are handled, as docu-
- mented below.
+ PCRE2 is normally built with Unicode support, though if you do not need
+ it, you can build it without, in which case the library will be
+ smaller. With Unicode support, PCRE2 has knowledge of Unicode character
+ properties and can process text strings in UTF-8, UTF-16, or UTF-32
+ format (depending on the code unit width), but this is not the default.
+ Unless specifically requested, PCRE2 treats each code unit in a string
+ as one character.
+
+ There are two ways of telling PCRE2 to switch to UTF mode, where char-
+ acters may consist of more than one code unit and the range of values
+ is constrained. The program can call pcre2_compile() with the PCRE2_UTF
+ option, or the pattern may start with the sequence (*UTF). However,
+ the latter facility can be locked out by the PCRE2_NEVER_UTF option.
+ That is, the programmer can prevent the supplier of the pattern from
+ switching to UTF mode.
- If you do not need Unicode support you can build PCRE2 without it, in
- which case the library will be smaller.
+ Note that the PCRE2_MATCH_INVALID_UTF option (see below) forces
+ PCRE2_UTF to be set.
+
+ In UTF mode, both the pattern and any subject strings that are matched
+ against it are treated as UTF strings instead of strings of individual
+ one-code-unit characters. There are also some other changes to the way
+ characters are handled, as documented below.
UNICODE PROPERTY SUPPORT
When PCRE2 is built with Unicode support, the escape sequences \p{..},
- \P{..}, and \X can be used. The Unicode properties that can be tested
- are limited to the general category properties such as Lu for an upper
- case letter or Nd for a decimal number, the Unicode script names such
- as Arabic or Han, and the derived properties Any and L&. Full lists are
- given in the pcre2pattern and pcre2syntax documentation. Only the short
- names for properties are supported. For example, \p{L} matches a let-
- ter. Its Perl synonym, \p{Letter}, is not supported. Furthermore, in
- Perl, many properties may optionally be prefixed by "Is", for compati-
- bility with Perl 5.6. PCRE2 does not support this.
+ \P{..}, and \X can be used. This is not dependent on the PCRE2_UTF set-
+ ting. The Unicode properties that can be tested are limited to the
+ general category properties such as Lu for an upper case letter or Nd
+ for a decimal number, the Unicode script names such as Arabic or Han,
+ and the derived properties Any and L&. Full lists are given in the
+ pcre2pattern and pcre2syntax documentation. Only the short names for
+ properties are supported. For example, \p{L} matches a letter. Its Perl
+ synonym, \p{Letter}, is not supported. Furthermore, in Perl, many
+ properties may optionally be prefixed by "Is", for compatibility with
+ Perl 5.6. PCRE2 does not support this.
WIDE CHARACTERS AND UTF MODES
Code points less than 256 can be specified in patterns by either braced
or unbraced hexadecimal escape sequences (for example, \x{b3} or \xb3).
- Larger values have to use braced sequences. Unbraced octal code points
+ Larger values have to use braced sequences. Unbraced octal code points
up to \777 are also recognized; larger ones can be coded using \o{...}.
- The escape sequence \N{U+} is recognized as another way of
- specifying a Unicode character by code point in a UTF mode. It is not
- allowed in non-UTF modes.
+ The escape sequence \N{U+} is recognized as another way of
+ specifying a Unicode character by code point in a UTF mode. It is not
+ allowed in non-UTF mode.
- In UTF modes, repeat quantifiers apply to complete UTF characters, not
+ In UTF mode, repeat quantifiers apply to complete UTF characters, not
to individual code units.
- In UTF modes, the dot metacharacter matches one UTF character instead
- of a single code unit.
+ In UTF mode, the dot metacharacter matches one UTF character instead of
+ a single code unit.
+
+ In UTF mode, capture group names are not restricted to ASCII, and may
+ contain any Unicode letters and decimal digits, as well as underscore.
- The escape sequence \C can be used to match a single code unit in a UTF
+ The escape sequence \C can be used to match a single code unit in UTF
mode, but its use can lead to some strange effects because it breaks up
multi-unit characters (see the description of \C in the pcre2pattern
- documentation).
+ documentation). For this reason, there is a build-time option that dis-
+ ables support for \C completely. There is also a less draconian com-
+ pile-time option for locking out the use of \C when a pattern is com-
+ piled.
- The use of \C is not supported by the alternative matching function
+ The use of \C is not supported by the alternative matching function
pcre2_dfa_match() when in UTF-8 or UTF-16 mode, that is, when a charac-
- ter may consist of more than one code unit. The use of \C in these
- modes provokes a match-time error. Also, the JIT optimization does not
+ ter may consist of more than one code unit. The use of \C in these
+ modes provokes a match-time error. Also, the JIT optimization does not
support \C in these modes. If JIT optimization is requested for a UTF-8
- or UTF-16 pattern that contains \C, it will not succeed, and so when
- pcre2_match() is called, the matching will be carried out by the normal
- interpretive function.
+ or UTF-16 pattern that contains \C, it will not succeed, and so when
+ pcre2_match() is called, the matching will be carried out by the inter-
+ pretive function.
The character escapes \b, \B, \d, \D, \s, \S, \w, and \W correctly test
- characters of any code value, but, by default, the characters that
- PCRE2 recognizes as digits, spaces, or word characters remain the same
- set as in non-UTF mode, all with code points less than 256. This
- remains true even when PCRE2 is built to include Unicode support,
- because to do otherwise would slow down matching in many common cases.
- Note that this also applies to \b and \B, because they are defined in
- terms of \w and \W. If you want to test for a wider sense of, say,
- "digit", you can use explicit Unicode property tests such as \p{Nd}.
- Alternatively, if you set the PCRE2_UCP option, the way that the char-
- acter escapes work is changed so that Unicode properties are used to
- determine which characters match. There are more details in the section
- on generic character types in the pcre2pattern documentation.
-
- Similarly, characters that match the POSIX named character classes are
+ characters of any code value, but, by default, the characters that
+ PCRE2 recognizes as digits, spaces, or word characters remain the same
+ set as in non-UTF mode, all with code points less than 256. This re-
+ mains true even when PCRE2 is built to include Unicode support, because
+ to do otherwise would slow down matching in many common cases. Note
+ that this also applies to \b and \B, because they are defined in terms
+ of \w and \W. If you want to test for a wider sense of, say, "digit",
+ you can use explicit Unicode property tests such as \p{Nd}. Alterna-
+ tively, if you set the PCRE2_UCP option, the way that the character es-
+ capes work is changed so that Unicode properties are used to determine
+ which characters match. There are more details in the section on
+ generic character types in the pcre2pattern documentation.
+
+ Similarly, characters that match the POSIX named character classes are
all low-valued characters, unless the PCRE2_UCP option is set.
- However, the special horizontal and vertical white space matching
- escapes (\h, \H, \v, and \V) do match all the appropriate Unicode char-
- acters, whether or not PCRE2_UCP is set.
+ However, the special horizontal and vertical white space matching es-
+ capes (\h, \H, \v, and \V) do match all the appropriate Unicode charac-
+ ters, whether or not PCRE2_UCP is set.
-CASE-EQUIVALENCE IN UTF MODES
+CASE-EQUIVALENCE IN UTF MODE
- Case-insensitive matching in a UTF mode makes use of Unicode properties
+ Case-insensitive matching in UTF mode makes use of Unicode properties
except for characters whose code points are less than 128 and that have
at most two case-equivalent values. For these, a direct table lookup is
- used for speed. A few Unicode characters such as Greek sigma have more
- than two code points that are case-equivalent, and these are treated as
- such.
+ used for speed. A few Unicode characters such as Greek sigma have more
+ than two code points that are case-equivalent, and these are treated
+ specially.
+
+
+SCRIPT RUNS
+
+ The pattern constructs (*script_run:...) and (*atomic_script_run:...),
+ with synonyms (*sr:...) and (*asr:...), verify that the string matched
+ within the parentheses is a script run. In concept, a script run is a
+ sequence of characters that are all from the same Unicode script. How-
+ ever, because some scripts are commonly used together, and because some
+ diacritical and other marks are used with multiple scripts, it is not
+ that simple.
+
+ Every Unicode character has a Script property, mostly with a value cor-
+ responding to the name of a script, such as Latin, Greek, or Cyrillic.
+ There are also three special values:
+
+ "Unknown" is used for code points that have not been assigned, and also
+ for the surrogate code points. In the PCRE2 32-bit library, characters
+ whose code points are greater than the Unicode maximum (U+10FFFF),
+ which are accessible only in non-UTF mode, are assigned the Unknown
+ script.
+
+ "Common" is used for characters that are used with many scripts. These
+ include punctuation, emoji, mathematical, musical, and currency sym-
+ bols, and the ASCII digits 0 to 9.
+
+ "Inherited" is used for characters such as diacritical marks that mod-
+ ify a previous character. These are considered to take on the script of
+ the character that they modify.
+
+ Some Inherited characters are used with many scripts, but many of them
+ are only normally used with a small number of scripts. For example,
+ U+102E0 (Coptic Epact thousands mark) is used only with Arabic and Cop-
+ tic. In order to make it possible to check this, a Unicode property
+ called Script Extension exists. Its value is a list of scripts that ap-
+ ply to the character. For the majority of characters, the list contains
+ just one script, the same one as the Script property. However, for
+ characters such as U+102E0 more than one Script is listed. There are
+ also some Common characters that have a single, non-Common script in
+ their Script Extension list.
+
+ The next section describes the basic rules for deciding whether a given
+ string of characters is a script run. Note, however, that there are
+ some special cases involving the Chinese Han script, and an additional
+ constraint for decimal digits. These are covered in subsequent sec-
+ tions.
+
+ Basic script run rules
+
+ A string that is less than two characters long is a script run. This is
+ the only case in which an Unknown character can be part of a script
+ run. Longer strings are checked using only the Script Extensions prop-
+ erty, not the basic Script property.
+
+ If a character's Script Extension property is the single value "Inher-
+ ited", it is always accepted as part of a script run. This is also true
+ for the property "Common", subject to the checking of decimal digits
+ described below. All the remaining characters in a script run must have
+ at least one script in common in their Script Extension lists. In set-
+ theoretic terminology, the intersection of all the sets of scripts must
+ not be empty.
+
+ A simple example is an Internet name such as "google.com". The letters
+ are all in the Latin script, and the dot is Common, so this string is a
+ script run. However, the Cyrillic letter "o" looks exactly the same as
+ the Latin "o"; a string that looks the same, but with Cyrillic "o"s is
+ not a script run.
+
+ More interesting examples involve characters with more than one script
+ in their Script Extension. Consider the following characters:
+
+ U+060C Arabic comma
+ U+06D4 Arabic full stop
+
+ The first has the Script Extension list Arabic, Hanifi Rohingya, Syr-
+ iac, and Thaana; the second has just Arabic and Hanifi Rohingya. Both
+ of them could appear in script runs of either Arabic or Hanifi Ro-
+ hingya. The first could also appear in Syriac or Thaana script runs,
+ but the second could not.
+
+ The Chinese Han script
+
+ The Chinese Han script is commonly used in conjunction with other
+ scripts for writing certain languages. Japanese uses the Hiragana and
+ Katakana scripts together with Han; Korean uses Hangul and Han; Tai-
+ wanese Mandarin uses Bopomofo and Han. These three combinations are
+ treated as special cases when checking script runs and are, in effect,
+ "virtual scripts". Thus, a script run may contain a mixture of Hira-
+ gana, Katakana, and Han, or a mixture of Hangul and Han, or a mixture
+ of Bopomofo and Han, but not, for example, a mixture of Hangul and
+ Bopomofo and Han. PCRE2 (like Perl) follows Unicode's Technical Stan-
+ dard 39 ("Unicode Security Mechanisms", http://unicode.org/re-
+ ports/tr39/) in allowing such mixtures.
+
+ Decimal digits
+
+ Unicode contains many sets of 10 decimal digits in different scripts,
+ and some scripts (including the Common script) contain more than one
+ set. Some of these decimal digits them are visually indistinguishable
+ from the common ASCII digits. In addition to the script checking de-
+ scribed above, if a script run contains any decimal digits, they must
+ all come from the same set of 10 adjacent characters.
VALIDITY OF UTF STRINGS
- When the PCRE2_UTF option is set, the strings passed as patterns and
+ When the PCRE2_UTF option is set, the strings passed as patterns and
subjects are (by default) checked for validity on entry to the relevant
- functions. If an invalid UTF string is passed, an negative error code
- is returned. The code unit offset to the offending character can be
- extracted from the match data block by calling pcre2_get_startchar(),
+ functions. If an invalid UTF string is passed, a negative error code is
+ returned. The code unit offset to the offending character can be ex-
+ tracted from the match data block by calling pcre2_get_startchar(),
which is used for this purpose after a UTF error.
- UTF-16 and UTF-32 strings can indicate their endianness by special code
- knows as a byte-order mark (BOM). The PCRE2 functions do not handle
- this, expecting strings to be in host byte order.
-
- A UTF string is checked before any other processing takes place. In the
- case of pcre2_match() and pcre2_dfa_match() calls with a non-zero
- starting offset, the check is applied only to that part of the subject
- that could be inspected during matching, and there is a check that the
- starting offset points to the first code unit of a character or to the
- end of the subject. If there are no lookbehind assertions in the pat-
- tern, the check starts at the starting offset. Otherwise, it starts at
- the length of the longest lookbehind before the starting offset, or at
- the start of the subject if there are not that many characters before
- the starting offset. Note that the sequences \b and \B are one-charac-
- ter lookbehinds.
-
- In addition to checking the format of the string, there is a check to
- ensure that all code points lie in the range U+0 to U+10FFFF, excluding
- the surrogate area. The so-called "non-character" code points are not
- excluded because Unicode corrigendum #9 makes it clear that they should
- not be.
-
- Characters in the "Surrogate Area" of Unicode are reserved for use by
- UTF-16, where they are used in pairs to encode code points with values
- greater than 0xFFFF. The code points that are encoded by UTF-16 pairs
- are available independently in the UTF-8 and UTF-32 encodings. (In
- other words, the whole surrogate thing is a fudge for UTF-16 which
- unfortunately messes up UTF-8 and UTF-32.)
-
In some situations, you may already know that your strings are valid,
and therefore want to skip these checks in order to improve perfor-
mance, for example in the case of a long subject string that is being
@@ -10554,21 +11061,55 @@ VALIDITY OF UTF STRINGS
pile time or at match time, PCRE2 assumes that the pattern or subject
it is given (respectively) contains only valid UTF code unit sequences.
- Passing PCRE2_NO_UTF_CHECK to pcre2_compile() just disables the check
- for the pattern; it does not also apply to subject strings. If you want
- to disable the check for a subject string you must pass this option to
- pcre2_match() or pcre2_dfa_match().
+ If you pass an invalid UTF string when PCRE2_NO_UTF_CHECK is set, the
+ result is undefined and your program may crash or loop indefinitely or
+ give incorrect results. There is, however, one mode of matching that
+ can handle invalid UTF subject strings. This is enabled by passing
+ PCRE2_MATCH_INVALID_UTF to pcre2_compile() and is discussed below in
+ the next section. The rest of this section covers the case when
+ PCRE2_MATCH_INVALID_UTF is not set.
- If you pass an invalid UTF string when PCRE2_NO_UTF_CHECK is set, the
- result is undefined and your program may crash or loop indefinitely.
+ Passing PCRE2_NO_UTF_CHECK to pcre2_compile() just disables the UTF
+ check for the pattern; it does not also apply to subject strings. If
+ you want to disable the check for a subject string you must pass this
+ same option to pcre2_match() or pcre2_dfa_match().
- Note that setting PCRE2_NO_UTF_CHECK at compile time does not disable
- the error that is given if an escape sequence for an invalid Unicode
- code point is encountered in the pattern. If you want to allow escape
- sequences such as \x{d800} (a surrogate code point) you can set the
- PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES extra option. However, this is pos-
- sible only in UTF-8 and UTF-32 modes, because these values are not rep-
- resentable in UTF-16.
+ UTF-16 and UTF-32 strings can indicate their endianness by special code
+ knows as a byte-order mark (BOM). The PCRE2 functions do not handle
+ this, expecting strings to be in host byte order.
+
+ Unless PCRE2_NO_UTF_CHECK is set, a UTF string is checked before any
+ other processing takes place. In the case of pcre2_match() and
+ pcre2_dfa_match() calls with a non-zero starting offset, the check is
+ applied only to that part of the subject that could be inspected during
+ matching, and there is a check that the starting offset points to the
+ first code unit of a character or to the end of the subject. If there
+ are no lookbehind assertions in the pattern, the check starts at the
+ starting offset. Otherwise, it starts at the length of the longest
+ lookbehind before the starting offset, or at the start of the subject
+ if there are not that many characters before the starting offset. Note
+ that the sequences \b and \B are one-character lookbehinds.
+
+ In addition to checking the format of the string, there is a check to
+ ensure that all code points lie in the range U+0 to U+10FFFF, excluding
+ the surrogate area. The so-called "non-character" code points are not
+ excluded because Unicode corrigendum #9 makes it clear that they should
+ not be.
+
+ Characters in the "Surrogate Area" of Unicode are reserved for use by
+ UTF-16, where they are used in pairs to encode code points with values
+ greater than 0xFFFF. The code points that are encoded by UTF-16 pairs
+ are available independently in the UTF-8 and UTF-32 encodings. (In
+ other words, the whole surrogate thing is a fudge for UTF-16 which un-
+ fortunately messes up UTF-8 and UTF-32.)
+
+ Setting PCRE2_NO_UTF_CHECK at compile time does not disable the error
+ that is given if an escape sequence for an invalid Unicode code point
+ is encountered in the pattern. If you want to allow escape sequences
+ such as \x{d800} (a surrogate code point) you can set the PCRE2_EX-
+ TRA_ALLOW_SURROGATE_ESCAPES extra option. However, this is possible
+ only in UTF-8 and UTF-32 modes, because these values are not repre-
+ sentable in UTF-16.
Errors in UTF-8 strings
@@ -10604,7 +11145,7 @@ VALIDITY OF UTF STRINGS
PCRE2_ERROR_UTF8_ERR13
- A 4-byte character has a value greater than 0x10fff; these code points
+ A 4-byte character has a value greater than 0x10ffff; these code points
are excluded by RFC 3629.
PCRE2_ERROR_UTF8_ERR14
@@ -10655,6 +11196,54 @@ VALIDITY OF UTF STRINGS
PCRE2_ERROR_UTF32_ERR2 Code point is greater than 0x10ffff
+MATCHING IN INVALID UTF STRINGS
+
+ You can run pattern matches on subject strings that may contain invalid
+ UTF sequences if you call pcre2_compile() with the PCRE2_MATCH_IN-
+ VALID_UTF option. This is supported by pcre2_match(), including JIT
+ matching, but not by pcre2_dfa_match(). When PCRE2_MATCH_INVALID_UTF is
+ set, it forces PCRE2_UTF to be set as well. Note, however, that the
+ pattern itself must be a valid UTF string.
+
+ Setting PCRE2_MATCH_INVALID_UTF does not affect what pcre2_compile()
+ generates, but if pcre2_jit_compile() is subsequently called, it does
+ generate different code. If JIT is not used, the option affects the be-
+ haviour of the interpretive code in pcre2_match(). When PCRE2_MATCH_IN-
+ VALID_UTF is set at compile time, PCRE2_NO_UTF_CHECK is ignored at
+ match time.
+
+ In this mode, an invalid code unit sequence in the subject never
+ matches any pattern item. It does not match dot, it does not match
+ \p{Any}, it does not even match negative items such as [^X]. A lookbe-
+ hind assertion fails if it encounters an invalid sequence while moving
+ the current point backwards. In other words, an invalid UTF code unit
+ sequence acts as a barrier which no match can cross.
+
+ You can also think of this as the subject being split up into fragments
+ of valid UTF, delimited internally by invalid code unit sequences. The
+ pattern is matched fragment by fragment. The result of a successful
+ match, however, is given as code unit offsets in the entire subject
+ string in the usual way. There are a few points to consider:
+
+ The internal boundaries are not interpreted as the beginnings or ends
+ of lines and so do not match circumflex or dollar characters in the
+ pattern.
+
+ If pcre2_match() is called with an offset that points to an invalid
+ UTF-sequence, that sequence is skipped, and the match starts at the
+ next valid UTF character, or the end of the subject.
+
+ At internal fragment boundaries, \b and \B behave in the same way as at
+ the beginning and end of the subject. For example, a sequence such as
+ \bWORD\b would match an instance of WORD that is surrounded by invalid
+ UTF code units.
+
+ Using PCRE2_MATCH_INVALID_UTF, an application can run matches on arbi-
+ trary data, knowing that any matched strings that are returned are
+ valid UTF. This can be useful when searching for UTF text in executable
+ or other binary files.
+
+
AUTHOR
Philip Hazel
@@ -10664,8 +11253,8 @@ AUTHOR
REVISION
- Last updated: 02 September 2018
- Copyright (c) 1997-2018 University of Cambridge.
+ Last updated: 24 May 2019
+ Copyright (c) 1997-2019 University of Cambridge.
------------------------------------------------------------------------------
diff --git a/doc/pcre2_compile.3 b/doc/pcre2_compile.3
index a5e8269..58a60c1 100644
--- a/doc/pcre2_compile.3
+++ b/doc/pcre2_compile.3
@@ -1,4 +1,4 @@
-.TH PCRE2_COMPILE 3 "16 June 2017" "PCRE2 10.30"
+.TH PCRE2_COMPILE 3 "23 May 2019" "PCRE2 10.34"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH SYNOPSIS
@@ -53,6 +53,7 @@ The option bits are:
PCRE2_EXTENDED Ignore white space and # comments
PCRE2_FIRSTLINE Force matching to be before newline
PCRE2_LITERAL Pattern characters are all literal
+ PCRE2_MATCH_INVALID_UTF Enable support for matching invalid UTF
PCRE2_MATCH_UNSET_BACKREF Match unset backreferences
PCRE2_MULTILINE ^ and $ match newlines within data
PCRE2_NEVER_BACKSLASH_C Lock out the use of \eC in patterns
@@ -73,7 +74,13 @@ The option bits are:
PCRE2 must be built with Unicode support (the default) in order to use
PCRE2_UTF, PCRE2_UCP and related options.
.P
-The yield of the function is a pointer to a private data structure that
+Additional options may be set in the compile context via the
+.\" HREF
+\fBpcre2_set_compile_extra_options\fP
+.\"
+function.
+.P
+The yield of this function is a pointer to a private data structure that
contains the compiled pattern, or NULL if an error was detected.
.P
There is a complete description of the PCRE2 native API, with more detail on
diff --git a/doc/pcre2_dfa_match.3 b/doc/pcre2_dfa_match.3
index dfc3ae6..6413cb6 100644
--- a/doc/pcre2_dfa_match.3
+++ b/doc/pcre2_dfa_match.3
@@ -1,4 +1,4 @@
-.TH PCRE2_DFA_MATCH 3 "26 April 2018" "PCRE2 10.32"
+.TH PCRE2_DFA_MATCH 3 "16 October 2018" "PCRE2 10.33"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH SYNOPSIS
@@ -39,6 +39,8 @@ depth limits. The \fIlength\fP and \fIstartoffset\fP values are code units, not
characters. The options are:
.sp
PCRE2_ANCHORED Match only at the first position
+ PCRE2_COPY_MATCHED_SUBJECT
+ On success, make a private subject copy
PCRE2_ENDANCHORED Pattern can match only at end of subject
PCRE2_NOTBOL Subject is not the beginning of a line
PCRE2_NOTEOL Subject is not the end of a line
diff --git a/doc/pcre2_get_match_data_size.3 b/doc/pcre2_get_match_data_size.3
new file mode 100644
index 0000000..cf5fa5e
--- /dev/null
+++ b/doc/pcre2_get_match_data_size.3
@@ -0,0 +1,27 @@
+.TH PCRE2_GET_MATCH_DATA_SIZE 3 "16 July 2019" "PCRE2 10.34"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B PCRE2_SIZE pcre2_get_match_data_size(pcre2_match_data *\fImatch_data\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function returns the size, in bytes, of the match data block that is its
+argument.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_jit_compile.3 b/doc/pcre2_jit_compile.3
index a11d949..6cc1788 100644
--- a/doc/pcre2_jit_compile.3
+++ b/doc/pcre2_jit_compile.3
@@ -1,4 +1,4 @@
-.TH PCRE2_JIT_COMPILE 3 "21 October 2014" "PCRE2 10.00"
+.TH PCRE2_JIT_COMPILE 3 "29 July 2019" "PCRE2 10.34"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH SYNOPSIS
@@ -30,9 +30,15 @@ bits:
PCRE2_JIT_PARTIAL_SOFT compile code for soft partial matching
PCRE2_JIT_PARTIAL_HARD compile code for hard partial matching
.sp
+There is also an obsolete option called PCRE2_JIT_INVALID_UTF, which has been
+superseded by the \fBpcre2_compile()\fP option PCRE2_MATCH_INVALID_UTF. The old
+option is deprecated and may be removed in the future.
+.P
The yield of the function is 0 for success, or a negative error code otherwise.
In particular, PCRE2_ERROR_JIT_BADOPTION is returned if JIT is not supported or
-if an unknown bit is set in \fIoptions\fP.
+if an unknown bit is set in \fIoptions\fP. The function can also return
+PCRE2_ERROR_NOMEMORY if JIT is unable to allocate executable memory for the
+compiler, even if it was because of a system security restriction.
.P
There is a complete description of the PCRE2 native API in the
.\" HREF
diff --git a/doc/pcre2_maketables.3 b/doc/pcre2_maketables.3
index 740954b..7dc8438 100644
--- a/doc/pcre2_maketables.3
+++ b/doc/pcre2_maketables.3
@@ -7,7 +7,7 @@ PCRE2 - Perl-compatible regular expressions (revised API)
.B #include
.PP
.SM
-.B const unsigned char *pcre2_maketables(pcre2_general_context *\fIgcontext\fP);
+.B const uint8_t *pcre2_maketables(pcre2_general_context *\fIgcontext\fP);
.
.SH DESCRIPTION
.rs
diff --git a/doc/pcre2_maketables_free.3 b/doc/pcre2_maketables_free.3
new file mode 100644
index 0000000..07986b9
--- /dev/null
+++ b/doc/pcre2_maketables_free.3
@@ -0,0 +1,31 @@
+.TH PCRE2_MAKETABLES_FREE 3 "02 September 2019" "PCRE2 10.34"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B void pcre2_maketables_free(pcre2_general_context *\fIgcontext\fP,
+.B " const uint8_t *\fItables\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function discards a set of character tables that were created by a call
+to
+.\" HREF
+\fBpcre2_maketables()\fP.
+.\"
+.P
+The \fIgcontext\fP parameter should match what was used in that call to
+account for any custom allocators that might be in use; if it is NULL
+the system \fBfree()\fP is used.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page.
diff --git a/doc/pcre2_match.3 b/doc/pcre2_match.3
index 9d15ec9..2be2dd0 100644
--- a/doc/pcre2_match.3
+++ b/doc/pcre2_match.3
@@ -1,4 +1,4 @@
-.TH PCRE2_MATCH 3 "14 November 2017" "PCRE2 10.31"
+.TH PCRE2_MATCH 3 "16 October 2018" "PCRE2 10.33"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH SYNOPSIS
@@ -43,11 +43,13 @@ A match context is needed only if you want to:
Change the backtracking depth limit
Set custom memory management specifically for the match
.sp
-The \fIlength\fP and \fIstartoffset\fP values are code
-units, not characters. The length may be given as PCRE2_ZERO_TERMINATE for a
-subject that is terminated by a binary zero code unit. The options are:
+The \fIlength\fP and \fIstartoffset\fP values are code units, not characters.
+The length may be given as PCRE2_ZERO_TERMINATED for a subject that is
+terminated by a binary zero code unit. The options are:
.sp
PCRE2_ANCHORED Match only at the first position
+ PCRE2_COPY_MATCHED_SUBJECT
+ On success, make a private subject copy
PCRE2_ENDANCHORED Pattern can match only at end of subject
PCRE2_NOTBOL Subject string is not the beginning of a line
PCRE2_NOTEOL Subject string is not the end of a line
diff --git a/doc/pcre2_match_data_free.3 b/doc/pcre2_match_data_free.3
index 56ed08b..cebdef9 100644
--- a/doc/pcre2_match_data_free.3
+++ b/doc/pcre2_match_data_free.3
@@ -1,4 +1,4 @@
-.TH PCRE2_MATCH_DATA_FREE 3 "28 June 2018" "PCRE2 10.32"
+.TH PCRE2_MATCH_DATA_FREE 3 "16 October 2018" "PCRE2 10.33"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH SYNOPSIS
@@ -18,6 +18,10 @@ If \fImatch_data\fP is NULL, this function does nothing. Otherwise,
using the memory freeing function from the general context or compiled pattern
with which it was created, or \fBfree()\fP if that was not set.
.P
+If the PCRE2_COPY_MATCHED_SUBJECT was used for a successful match using this
+match data block, the copy of the subject that was remembered with the block is
+also freed.
+.P
There is a complete description of the PCRE2 native API in the
.\" HREF
\fBpcre2api\fP
diff --git a/doc/pcre2_pattern_info.3 b/doc/pcre2_pattern_info.3
index 01b74a2..edd8989 100644
--- a/doc/pcre2_pattern_info.3
+++ b/doc/pcre2_pattern_info.3
@@ -1,4 +1,4 @@
-.TH PCRE2_PATTERN_INFO 3 "16 December 2017" "PCRE2 10.31"
+.TH PCRE2_PATTERN_INFO 3 "14 February 2019" "PCRE2 10.33"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH SYNOPSIS
@@ -7,7 +7,8 @@ PCRE2 - Perl-compatible regular expressions (revised API)
.B #include
.PP
.nf
-.B int pcre2_pattern_info(const pcre2 *\fIcode\fP, uint32_t \fIwhat\fP, void *\fIwhere\fP);
+.B int pcre2_pattern_info(const pcre2_code *\fIcode\fP, uint32_t \fIwhat\fP,
+.B " void *\fIwhere\fP);"
.fi
.
.SH DESCRIPTION
diff --git a/doc/pcre2_set_character_tables.3 b/doc/pcre2_set_character_tables.3
index 1ede4f9..1b740a1 100644
--- a/doc/pcre2_set_character_tables.3
+++ b/doc/pcre2_set_character_tables.3
@@ -8,7 +8,7 @@ PCRE2 - Perl-compatible regular expressions (revised API)
.PP
.nf
.B int pcre2_set_character_tables(pcre2_compile_context *\fIccontext\fP,
-.B " const unsigned char *\fItables\fP);"
+.B " const uint8_t *\fItables\fP);"
.fi
.
.SH DESCRIPTION
diff --git a/doc/pcre2_set_compile_extra_options.3 b/doc/pcre2_set_compile_extra_options.3
index 79f71ce..764a75e 100644
--- a/doc/pcre2_set_compile_extra_options.3
+++ b/doc/pcre2_set_compile_extra_options.3
@@ -1,4 +1,4 @@
-.TH PCRE2_SET_COMPILE_EXTRA_OPTIONS 3 "16 June 2017" "PCRE2 10.30"
+.TH PCRE2_SET_COMPILE_EXTRA_OPTIONS 3 "11 February 2019" "PCRE2 10.33"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH SYNOPSIS
@@ -8,7 +8,7 @@ PCRE2 - Perl-compatible regular expressions (revised API)
.PP
.nf
.B int pcre2_set_compile_extra_options(pcre2_compile_context *\fIccontext\fP,
-.B " PCRE2_SIZE \fIextra_options\fP);"
+.B " uint32_t \fIextra_options\fP);"
.fi
.
.SH DESCRIPTION
@@ -21,9 +21,13 @@ options are:
.\" JOIN
PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES Allow \ex{df800} to \ex{dfff}
in UTF-8 and UTF-32 modes
+.\" JOIN
+ PCRE2_EXTRA_ALT_BSUX Extended alternate \eu, \eU, and \ex
+ handling
.\" JOIN
PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL Treat all invalid escapes as
a literal following character
+ PCRE2_EXTRA_ESCAPED_CR_IS_LF Interpret \er as \en
PCRE2_EXTRA_MATCH_LINE Pattern matches whole lines
PCRE2_EXTRA_MATCH_WORD Pattern matches "words"
.sp
diff --git a/doc/pcre2_set_substitute_callout.3 b/doc/pcre2_set_substitute_callout.3
new file mode 100644
index 0000000..cdd7ac6
--- /dev/null
+++ b/doc/pcre2_set_substitute_callout.3
@@ -0,0 +1,31 @@
+.TH PCRE2_SET_SUBSTITUTE_CALLOUT 3 "12 November 2018" "PCRE2 10.33"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_substitute_callout(pcre2_match_context *\fImcontext\fP,
+.B " int (*\fIcallout_function\fP)(pcre2_substitute_callout_block *),"
+.B " void *\fIcallout_data\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function sets the substitute callout fields in a match context (the first
+argument). The second argument specifies a callout function, and the third
+argument is an opaque data item that is passed to it. The result of this
+function is always zero.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_substring_nametable_scan.3 b/doc/pcre2_substring_nametable_scan.3
index 4342f98..9ab58cd 100644
--- a/doc/pcre2_substring_nametable_scan.3
+++ b/doc/pcre2_substring_nametable_scan.3
@@ -1,4 +1,4 @@
-.TH PCRE2_SUBSTRING_NAMETABLE_SCAN 3 "21 October 2014" "PCRE2 10.00"
+.TH PCRE2_SUBSTRING_NAMETABLE_SCAN 3 "03 February 2019" "PCRE2 10.33"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH SYNOPSIS
@@ -15,8 +15,8 @@ PCRE2 - Perl-compatible regular expressions (revised API)
.rs
.sp
This convenience function finds, for a compiled pattern, the first and last
-entries for a given name in the table that translates capturing parenthesis
-names into numbers.
+entries for a given name in the table that translates capture group names into
+numbers.
.sp
\fIcode\fP Compiled regular expression
\fIname\fP Name whose entries required
diff --git a/doc/pcre2api.3 b/doc/pcre2api.3
index ba90c86..27e3ef4 100644
--- a/doc/pcre2api.3
+++ b/doc/pcre2api.3
@@ -1,4 +1,4 @@
-.TH PCRE2API 3 "07 September 2018" "PCRE2 10.32"
+.TH PCRE2API 3 "02 September 2019" "PCRE2 10.34"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.sp
@@ -88,7 +88,7 @@ document for an overview of all the PCRE2 documentation.
.B " uint32_t \fIvalue\fP);"
.sp
.B int pcre2_set_character_tables(pcre2_compile_context *\fIccontext\fP,
-.B " const unsigned char *\fItables\fP);"
+.B " const uint8_t *\fItables\fP);"
.sp
.B int pcre2_set_compile_extra_options(pcre2_compile_context *\fIccontext\fP,
.B " uint32_t \fIextra_options\fP);"
@@ -123,6 +123,10 @@ document for an overview of all the PCRE2 documentation.
.B " int (*\fIcallout_function\fP)(pcre2_callout_block *, void *),"
.B " void *\fIcallout_data\fP);"
.sp
+.B int pcre2_set_substitute_callout(pcre2_match_context *\fImcontext\fP,
+.B " int (*\fIcallout_function\fP)(pcre2_substitute_callout_block *, void *),"
+.B " void *\fIcallout_data\fP);"
+.sp
.B int pcre2_set_offset_limit(pcre2_match_context *\fImcontext\fP,
.B " PCRE2_SIZE \fIvalue\fP);"
.sp
@@ -241,9 +245,13 @@ document for an overview of all the PCRE2 documentation.
.B int pcre2_get_error_message(int \fIerrorcode\fP, PCRE2_UCHAR *\fIbuffer\fP,
.B " PCRE2_SIZE \fIbufflen\fP);"
.sp
-.B const unsigned char *pcre2_maketables(pcre2_general_context *\fIgcontext\fP);
+.B const uint8_t *pcre2_maketables(pcre2_general_context *\fIgcontext\fP);
.sp
-.B int pcre2_pattern_info(const pcre2 *\fIcode\fP, uint32_t \fIwhat\fP, void *\fIwhere\fP);
+.B void pcre2_maketables_free(pcre2_general_context *\fIgcontext\fP,
+.B " const uint8_t *\fItables\fP);"
+.sp
+.B int pcre2_pattern_info(const pcre2_code *\fIcode\fP, uint32_t \fIwhat\fP,
+.B " void *\fIwhere\fP);"
.sp
.B int pcre2_callout_enumerate(const pcre2_code *\fIcode\fP,
.B " int (*\fIcallback\fP)(pcre2_callout_enumerate_block *, void *),"
@@ -720,10 +728,10 @@ interpreted matching functions, \fIpcre2_match()\fP and
.sp
.nf
.B int pcre2_set_character_tables(pcre2_compile_context *\fIccontext\fP,
-.B " const unsigned char *\fItables\fP);"
+.B " const uint8_t *\fItables\fP);"
.fi
.sp
-The value must be the result of a call to \fIpcre2_maketables()\fP, whose only
+The value must be the result of a call to \fBpcre2_maketables()\fP, whose only
argument is a general context. This function builds a set of character tables
in the current locale.
.sp
@@ -785,7 +793,7 @@ functions, \fIpcre2_match()\fP and \fIpcre2_dfa_match()\fP.
.B " uint32_t \fIvalue\fP);"
.fi
.sp
-This parameter ajusts the limit, set when PCRE2 is built (default 250), on the
+This parameter adjusts the limit, set when PCRE2 is built (default 250), on the
depth of parenthesis nesting in a pattern. This limit stops rogue patterns
using up too much system stack when being compiled. The limit applies to
parentheses of all kinds, not just capturing parentheses.
@@ -847,7 +855,7 @@ PCRE2_ERROR_BADDATA if invalid data is detected.
.B " void *\fIcallout_data\fP);"
.fi
.sp
-This sets up a "callout" function for PCRE2 to call at specified points
+This sets up a callout function for PCRE2 to call at specified points
during a matching operation. Details are given in the
.\" HREF
\fBpcre2callout\fP
@@ -855,6 +863,20 @@ during a matching operation. Details are given in the
documentation.
.sp
.nf
+.B int pcre2_set_substitute_callout(pcre2_match_context *\fImcontext\fP,
+.B " int (*\fIcallout_function\fP)(pcre2_substitute_callout_block *, void *),"
+.B " void *\fIcallout_data\fP);"
+.fi
+.sp
+This sets up a callout function for PCRE2 to call after each substitution
+made by \fBpcre2_substitute()\fP. Details are given in the section entitled
+"Creating a new string with substitutions"
+.\" HTML
+.\"
+below.
+.\"
+.sp
+.nf
.B int pcre2_set_offset_limit(pcre2_match_context *\fImcontext\fP,
.B " PCRE2_SIZE \fIvalue\fP);"
.fi
@@ -867,7 +889,7 @@ offset is not found. The \fBpcre2_substitute()\fP function makes no more
substitutions.
.P
For example, if the pattern /abc/ is matched against "123abc" with an offset
-limit less than 3, the result is PCRE2_ERROR_NO_MATCH. A match can never be
+limit less than 3, the result is PCRE2_ERROR_NOMATCH. A match can never be
found if the \fIstartoffset\fP argument of \fBpcre2_match()\fP,
\fBpcre2_dfa_match()\fP, or \fBpcre2_substitute()\fP is greater than the offset
limit set in the match context.
@@ -1213,22 +1235,28 @@ are needed. The \fBpcre2_code_copy_with_tables()\fP provides this facility.
Copies of both the code and the tables are made, with the new code pointing to
the new tables. The memory for the new tables is automatically freed when
\fBpcre2_code_free()\fP is called for the new copy of the compiled code. If
-\fBpcre2_code_copy_withy_tables()\fP is called with a NULL argument, it returns
+\fBpcre2_code_copy_with_tables()\fP is called with a NULL argument, it returns
NULL.
.P
NOTE: When one of the matching functions is called, pointers to the compiled
pattern and the subject string are set in the match data block so that they can
-be referenced by the substring extraction functions. After running a match, you
-must not free a compiled pattern (or a subject string) until after all
-operations on the
+be referenced by the substring extraction functions after a successful match.
+After running a match, you must not free a compiled pattern or a subject string
+until after all operations on the
.\" HTML
.\"
match data block
.\"
-have taken place.
+have taken place, unless, in the case of the subject string, you have used the
+PCRE2_COPY_MATCHED_SUBJECT option, which is described in the section entitled
+"Option bits for \fBpcre2_match()\fP"
+.\" HTML
+.\"
+below.
+.\"
.P
The \fIoptions\fP argument for \fBpcre2_compile()\fP contains various bit
-settings that affect the compilation. It should be zero if no options are
+settings that affect the compilation. It should be zero if none of them are
required. The available options are described below. Some of them (in
particular, those that are compatible with Perl, but some others as well) can
also be set and unset from within the pattern (see the detailed description in
@@ -1243,8 +1271,9 @@ contents of the \fIoptions\fP argument specifies their settings at the start of
compilation. The PCRE2_ANCHORED, PCRE2_ENDANCHORED, and PCRE2_NO_UTF_CHECK
options can be set at the time of matching as well as at compile time.
.P
-Other, less frequently required compile-time parameters (for example, the
-newline setting) can be provided in a compile context (as described
+Some additional options and less frequently required compile-time parameters
+(for example, the newline setting) can be provided in a compile context (as
+described
.\" HTML
.\"
above).
@@ -1259,13 +1288,14 @@ and \fBpcre2_compile()\fP returns a non-NULL value.
.P
There are nearly 100 positive error codes that \fBpcre2_compile()\fP may return
if it finds an error in the pattern. There are also some negative error codes
-that are used for invalid UTF strings. These are the same as given by
-\fBpcre2_match()\fP and \fBpcre2_dfa_match()\fP, and are described in the
+that are used for invalid UTF strings when validity checking is in force. These
+are the same as given by \fBpcre2_match()\fP and \fBpcre2_dfa_match()\fP, and
+are described in the
.\" HREF
\fBpcre2unicode\fP
.\"
-page. There is no separate documentation for the positive error codes, because
-the textual error messages that are obtained by calling the
+documentation. There is no separate documentation for the positive error codes,
+because the textual error messages that are obtained by calling the
\fBpcre2_get_error_message()\fP function (see "Obtaining a textual error
message"
.\" HTML
@@ -1301,6 +1331,11 @@ This code fragment shows a typical straightforward call to
&erroffset, /* for error offset */
NULL); /* no compile context */
.sp
+.
+.
+.SS "Main compile options"
+.rs
+.sp
The following names for option bits are defined in the \fBpcre2.h\fP header
file:
.sp
@@ -1337,6 +1372,16 @@ hexadecimal digits, in which case the hexadecimal number defines the code point
to match. By default, as in Perl, a hexadecimal number is always expected after
\ex, but it may have zero, one, or two digits (so, for example, \exz matches a
binary zero character followed by z).
+.P
+ECMAscript 6 added additional functionality to \eu. This can be accessed using
+the PCRE2_EXTRA_ALT_BSUX extra option (see "Extra compile options"
+.\" HTML
+.\"
+below).
+.\"
+Note that this alternative escape handling applies only to patterns. Neither of
+these options affects the processing of replacement strings passed to
+\fBpcre2_substitute()\fP.
.sp
PCRE2_ALT_CIRCUMFLEX
.sp
@@ -1405,10 +1450,10 @@ independent of the setting of PCRE2_DOTALL.
.sp
PCRE2_DUPNAMES
.sp
-If this bit is set, names used to identify capturing subpatterns need not be
-unique. This can be helpful for certain types of pattern when it is known that
-only one instance of the named subpattern can ever be matched. There are more
-details of named subpatterns below; see also the
+If this bit is set, names used to identify capture groups need not be unique.
+This can be helpful for certain types of pattern when it is known that only one
+instance of the named group can ever be matched. There are more details of
+named capture groups below; see also the
.\" HREF
\fBpcre2pattern\fP
.\"
@@ -1442,11 +1487,11 @@ the end of the subject.
If this bit is set, most white space characters in the pattern are totally
ignored except when escaped or inside a character class. However, white space
is not allowed within sequences such as (?> that introduce various
-parenthesized subpatterns, nor within numerical quantifiers such as {1,3}.
-Ignorable white space is permitted between an item and a following quantifier
-and between a quantifier and a following + that indicates possessiveness.
-PCRE2_EXTENDED is equivalent to Perl's /x option, and it can be changed within
-a pattern by a (?x) option setting.
+parenthesized groups, nor within numerical quantifiers such as {1,3}. Ignorable
+white space is permitted between an item and a following quantifier and between
+a quantifier and a following + that indicates possessiveness. PCRE2_EXTENDED is
+equivalent to Perl's /x option, and it can be changed within a pattern by a
+(?x) option setting.
.P
When PCRE2 is compiled without Unicode support, PCRE2_EXTENDED recognizes as
white space only those characters with code points less than 256 that are
@@ -1516,14 +1561,24 @@ expression engine is not the most efficient way of doing it. If you are doing a
lot of literal matching and are worried about efficiency, you should consider
using other approaches. The only other main options that are allowed with
PCRE2_LITERAL are: PCRE2_ANCHORED, PCRE2_ENDANCHORED, PCRE2_AUTO_CALLOUT,
-PCRE2_CASELESS, PCRE2_FIRSTLINE, PCRE2_NO_START_OPTIMIZE, PCRE2_NO_UTF_CHECK,
-PCRE2_UTF, and PCRE2_USE_OFFSET_LIMIT. The extra options PCRE2_EXTRA_MATCH_LINE
-and PCRE2_EXTRA_MATCH_WORD are also supported. Any other options cause an
-error.
+PCRE2_CASELESS, PCRE2_FIRSTLINE, PCRE2_MATCH_INVALID_UTF,
+PCRE2_NO_START_OPTIMIZE, PCRE2_NO_UTF_CHECK, PCRE2_UTF, and
+PCRE2_USE_OFFSET_LIMIT. The extra options PCRE2_EXTRA_MATCH_LINE and
+PCRE2_EXTRA_MATCH_WORD are also supported. Any other options cause an error.
+.sp
+ PCRE2_MATCH_INVALID_UTF
+.sp
+This option forces PCRE2_UTF (see below) and also enables support for matching
+by \fBpcre2_match()\fP in subject strings that contain invalid UTF sequences.
+This facility is not supported for DFA matching. For details, see the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+documentation.
.sp
PCRE2_MATCH_UNSET_BACKREF
.sp
-If this option is set, a backreference to an unset subpattern group matches an
+If this option is set, a backreference to an unset capture group matches an
empty string (by default this causes the current matching alternative to fail).
A pattern such as (\e1)(a) succeeds when this option is set (assuming it can
find an "a" in the subject), whereas it fails by default, for Perl
@@ -1584,7 +1639,7 @@ If this option is set, it disables the use of numbered capturing parentheses in
the pattern. Any opening parenthesis that is not followed by ? behaves as if it
were followed by ?: but named parentheses can still be used for capturing (and
they acquire numbers in the usual way). This is the same as Perl's /n option.
-Note that, when this option is set, references to capturing groups
+Note that, when this option is set, references to capture groups
(backreferences or recursion/subroutine calls) may only refer to named groups,
though the reference can be by name or by number.
.sp
@@ -1603,7 +1658,7 @@ purposes.
If this option is set, it disables an optimization that is applied when .* is
the first significant item in a top-level branch of a pattern, and all the
other branches also start with .* or with \eA or \eG or ^. The optimization is
-automatically disabled for .* if it is inside an atomic group or a capturing
+automatically disabled for .* if it is inside an atomic group or a capture
group that is the subject of a backreference, or if the pattern contains
(*PRUNE) or (*SKIP). When the optimization is not disabled, such a pattern is
automatically anchored if PCRE2_DOTALL is set for all the .* items and
@@ -1649,17 +1704,22 @@ subject string does not happen. The first match attempt is run starting from
"D" and when this fails, (*COMMIT) prevents any further matches being tried, so
the overall result is "no match".
.P
-There are also other start-up optimizations. For example, a minimum length for
-the subject may be recorded. Consider the pattern
+As another start-up optimization makes use of a minimum length for a matching
+subject, which is recorded when possible. Consider the pattern
.sp
- (*MARK:A)(X|Y)
+ (*MARK:1)B(*MARK:2)(X|Y)
.sp
-The minimum length for a match is one character. If the subject is "ABC", there
-will be attempts to match "ABC", "BC", and "C". An attempt to match an empty
-string at the end of the subject does not take place, because PCRE2 knows that
-the subject is now too short, and so the (*MARK) is never encountered. In this
-case, the optimization does not affect the overall match result, which is still
-"no match", but it does affect the auxiliary information that is returned.
+The minimum length for a match is two characters. If the subject is "XXBB", the
+"starting character" optimization skips "XX", then tries to match "BB", which
+is long enough. In the process, (*MARK:2) is encountered and remembered. When
+the match attempt fails, the next "B" is found, but there is only one character
+left, so there are no more attempts, and "no match" is returned with the "last
+mark seen" set to "2". If NO_START_OPTIMIZE is set, however, matches are tried
+at every possible starting position, including at the end of the subject, where
+(*MARK:1) is encountered, but there is no "B", so the "last mark seen" that is
+returned is "1". In this case, the optimizations do not affect the overall
+match result, which is still "no match", but they do affect the auxiliary
+information that is returned.
.sp
PCRE2_NO_UTF_CHECK
.sp
@@ -1764,9 +1824,8 @@ characters with code points greater than 127.
.SS "Extra compile options"
.rs
.sp
-Unlike the main compile-time options, the extra options are not saved with the
-compiled pattern. The option bits that can be set in a compile context by
-calling the \fBpcre2_set_compile_extra_options()\fP function are as follows:
+The option bits that can be set in a compile context by calling the
+\fBpcre2_set_compile_extra_options()\fP function are as follows:
.sp
PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES
.sp
@@ -1789,6 +1848,14 @@ If the extra option PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is set, surrogate code
point values in UTF-8 and UTF-32 patterns no longer provoke errors and are
incorporated in the compiled pattern. However, they can only match subject
characters if the matching function is called with PCRE2_NO_UTF_CHECK set.
+.sp
+ PCRE2_EXTRA_ALT_BSUX
+.sp
+The original option PCRE2_ALT_BSUX causes PCRE2 to process \eU, \eu, and \ex in
+the way that ECMAscript (aka JavaScript) does. Additional functionality was
+defined by ECMAscript 6; setting PCRE2_EXTRA_ALT_BSUX has the effect of
+PCRE2_ALT_BSUX, but in addition it recognizes \eu{hhh..} as a hexadecimal
+character code, where hhh.. is any number of hexadecimal digits.
.sp
PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL
.sp
@@ -1801,11 +1868,22 @@ Perl's warning switch is enabled. However, a malformed octal number after \eo{
always causes an error in Perl.
.P
If the PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL extra option is passed to
-\fBpcre2_compile()\fP, all unrecognized or erroneous escape sequences are
+\fBpcre2_compile()\fP, all unrecognized or malformed escape sequences are
treated as single-character escapes. For example, \ej is a literal "j" and
\ex{2z} is treated as the literal string "x{2z}". Setting this option means
-that typos in patterns may go undetected and have unexpected results. This is a
-dangerous option. Use with care.
+that typos in patterns may go undetected and have unexpected results. Also note
+that a sequence such as [\eN{] is interpreted as a malformed attempt at
+[\eN{...}] and so is treated as [N{] whereas [\eN] gives an error because an
+unqualified \eN is a valid escape sequence but is not supported in a character
+class. To reiterate: this is a dangerous option. Use with great care.
+.sp
+ PCRE2_EXTRA_ESCAPED_CR_IS_LF
+.sp
+There are some legacy applications where the escape sequence \er in a pattern
+is expected to match a newline. If this option is set, \er in a pattern is
+converted to \en so that it matches a LF (linefeed) instead of a CR (carriage
+return) character. The option does not affect a literal CR in the pattern, nor
+does it affect CR specified as an explicit code point such as \ex{0D}.
.sp
PCRE2_EXTRA_MATCH_LINE
.sp
@@ -1868,35 +1946,45 @@ Most (but not all) patterns can be optimized by the JIT compiler.
.SH "LOCALE SUPPORT"
.rs
.sp
+.nf
+.B const uint8_t *pcre2_maketables(pcre2_general_context *\fIgcontext\fP);
+.sp
+.B void pcre2_maketables_free(pcre2_general_context *\fIgcontext\fP,
+.B " const uint8_t *\fItables\fP);"
+.fi
+.P
PCRE2 handles caseless matching, and determines whether characters are letters,
digits, or whatever, by reference to a set of tables, indexed by character code
-point. This applies only to characters whose code points are less than 256. By
-default, higher-valued code points never match escapes such as \ew or \ed.
-However, if PCRE2 is built with Unicode support, all characters can be tested
-with \ep and \eP, or, alternatively, the PCRE2_UCP option can be set when a
-pattern is compiled; this causes \ew and friends to use Unicode property
+point. However, this applies only to characters whose code points are less than
+256. By default, higher-valued code points never match escapes such as \ew or
+\ed. When PCRE2 is built with Unicode support (the default), all characters can
+be tested with \ep and \eP, or, alternatively, the PCRE2_UCP option can be set
+when a pattern is compiled; this causes \ew and friends to use Unicode property
support instead of the built-in tables.
.P
The use of locales with Unicode is discouraged. If you are handling characters
with code points greater than 128, you should either use Unicode support, or
use locales, but not try to mix the two.
.P
-PCRE2 contains an internal set of character tables that are used by default.
+PCRE2 contains a built-in set of character tables that are used by default.
These are sufficient for many applications. Normally, the internal tables
recognize only ASCII characters. However, when PCRE2 is built, it is possible
to cause the internal tables to be rebuilt in the default "C" locale of the
local system, which may cause them to be different.
.P
-The internal tables can be overridden by tables supplied by the application
+The built-in tables can be overridden by tables supplied by the application
that calls PCRE2. These may be created in a different locale from the default.
As more and more applications change to using Unicode, the need for this locale
support is expected to die away.
.P
External tables are built by calling the \fBpcre2_maketables()\fP function, in
-the relevant locale. The result can be passed to \fBpcre2_compile()\fP as often
-as necessary, by creating a compile context and calling
-\fBpcre2_set_character_tables()\fP to set the tables pointer therein. For
-example, to build and use tables that are appropriate for the French locale
+the relevant locale. The only argument to this function is a general context,
+which can be used to pass a custom memory allocator. If the argument is NULL,
+the system \fBmalloc()\fP is used. The result can be passed to
+\fBpcre2_compile()\fP as often as necessary, by creating a compile context and
+calling \fBpcre2_set_character_tables()\fP to set the tables pointer therein.
+.P
+For example, to build and use tables that are appropriate for the French locale
(where accented characters with values greater than 128 are treated as
letters), the following code could be used:
.sp
@@ -1907,15 +1995,19 @@ letters), the following code could be used:
re = pcre2_compile(..., ccontext);
.sp
The locale name "fr_FR" is used on Linux and other Unix-like systems; if you
-are using Windows, the name for the French locale is "french". It is the
-caller's responsibility to ensure that the memory containing the tables remains
-available for as long as it is needed.
+are using Windows, the name for the French locale is "french".
.P
The pointer that is passed (via the compile context) to \fBpcre2_compile()\fP
is saved with the compiled pattern, and the same tables are used by
\fBpcre2_match()\fP and \fBpcre_dfa_match()\fP. Thus, for any single pattern,
compilation and matching both happen in the same locale, but different patterns
can be processed in different locales.
+.P
+It is the caller's responsibility to ensure that the memory containing the
+tables remains available while they are still in use. When they are no longer
+needed, you can discard them using \fBpcre2_maketables_free()\fP, which should
+pass as its first parameter the same global context that was used to create the
+tables.
.
.
.\" HTML
@@ -1945,7 +2037,7 @@ the following negative numbers:
PCRE2_ERROR_BADOPTION the value of \fIwhat\fP was invalid
PCRE2_ERROR_UNSET the requested field is not set
.sp
-The "magic number" is placed at the start of each compiled pattern as an simple
+The "magic number" is placed at the start of each compiled pattern as a simple
check against passing an arbitrary memory pointer. Here is a typical call of
\fBpcre2_pattern_info()\fP, to obtain the length of the compiled pattern:
.sp
@@ -1990,7 +2082,7 @@ following are true:
.sp
.* is not in an atomic group
.\" JOIN
- .* is not in a capturing group that is the subject
+ .* is not in a capture group that is the subject
of a backreference
PCRE2_DOTALL is in force for .*
Neither (*PRUNE) nor (*SKIP) appears in the pattern
@@ -2002,12 +2094,12 @@ options returned for PCRE2_INFO_ALLOPTIONS.
PCRE2_INFO_BACKREFMAX
.sp
Return the number of the highest backreference in the pattern. The third
-argument should point to an \fBuint32_t\fP variable. Named subpatterns acquire
-numbers as well as names, and these count towards the highest backreference.
-Backreferences such as \e4 or \eg{12} match the captured characters of the
-given group, but in addition, the check that a capturing group is set in a
-conditional subpattern such as (?(3)a|b) is also a backreference. Zero is
-returned if there are no backreferences.
+argument should point to a \fBuint32_t\fP variable. Named capture groups
+acquire numbers as well as names, and these count towards the highest
+backreference. Backreferences such as \e4 or \eg{12} match the captured
+characters of the given group, but in addition, the check that a capture
+group is set in a conditional group such as (?(3)a|b) is also a backreference.
+Zero is returned if there are no backreferences.
.sp
PCRE2_INFO_BSR
.sp
@@ -2018,9 +2110,9 @@ that \eR matches only CR, LF, or CRLF.
.sp
PCRE2_INFO_CAPTURECOUNT
.sp
-Return the highest capturing subpattern number in the pattern. In patterns
-where (?| is not used, this is also the total number of capturing subpatterns.
-The third argument should point to an \fBuint32_t\fP variable.
+Return the highest capture group number in the pattern. In patterns where (?|
+is not used, this is also the total number of capture groups. The third
+argument should point to a \fBuint32_t\fP variable.
.sp
PCRE2_INFO_DEPTHLIMIT
.sp
@@ -2045,7 +2137,7 @@ returned. Otherwise NULL is returned. The third argument should point to a
PCRE2_INFO_FIRSTCODETYPE
.sp
Return information about the first code unit of any matched string, for a
-non-anchored pattern. The third argument should point to an \fBuint32_t\fP
+non-anchored pattern. The third argument should point to a \fBuint32_t\fP
variable. If there is a fixed first value, for example, the letter "c" from a
pattern such as (cat|cow|coyote), 1 is returned, and the value can be retrieved
using PCRE2_INFO_FIRSTCODEUNIT. If there is no fixed first value, but it is
@@ -2057,7 +2149,7 @@ is returned.
.sp
Return the value of the first code unit of any matched string for a pattern
where PCRE2_INFO_FIRSTCODETYPE returns 1; otherwise return 0. The third
-argument should point to an \fBuint32_t\fP variable. In the 8-bit library, the
+argument should point to a \fBuint32_t\fP variable. In the 8-bit library, the
value is always less than 256. In the 16-bit library the value can be up to
0xffff. In the 32-bit library in UTF-32 mode the value can be up to 0x10ffff,
and up to 0xffffffff when not using UTF-32 mode.
@@ -2068,17 +2160,17 @@ Return the size (in bytes) of the data frames that are used to remember
backtracking positions when the pattern is processed by \fBpcre2_match()\fP
without the use of JIT. The third argument should point to a \fBsize_t\fP
variable. The frame size depends on the number of capturing parentheses in the
-pattern. Each additional capturing group adds two PCRE2_SIZE variables.
+pattern. Each additional capture group adds two PCRE2_SIZE variables.
.sp
PCRE2_INFO_HASBACKSLASHC
.sp
Return 1 if the pattern contains any instances of \eC, otherwise 0. The third
-argument should point to an \fBuint32_t\fP variable.
+argument should point to a \fBuint32_t\fP variable.
.sp
PCRE2_INFO_HASCRORLF
.sp
Return 1 if the pattern contains any explicit matches for CR or LF characters,
-otherwise 0. The third argument should point to an \fBuint32_t\fP variable. An
+otherwise 0. The third argument should point to a \fBuint32_t\fP variable. An
explicit match is either a literal CR or LF character, or \er or \en or one of
the equivalent hexadecimal or octal escape sequences.
.sp
@@ -2094,7 +2186,7 @@ defaulted by the caller of the match function.
PCRE2_INFO_JCHANGED
.sp
Return 1 if the (?J) or (?-J) option setting is used in the pattern, otherwise
-0. The third argument should point to an \fBuint32_t\fP variable. (?J) and
+0. The third argument should point to a \fBuint32_t\fP variable. (?J) and
(?-J) set and unset the local PCRE2_DUPNAMES option, respectively.
.sp
PCRE2_INFO_JITSIZE
@@ -2106,7 +2198,7 @@ return zero. The third argument should point to a \fBsize_t\fP variable.
PCRE2_INFO_LASTCODETYPE
.sp
Returns 1 if there is a rightmost literal code unit that must exist in any
-matched string, other than at its start. The third argument should point to an
+matched string, other than at its start. The third argument should point to a
\fBuint32_t\fP variable. If there is no such value, 0 is returned. When 1 is
returned, the code unit value itself can be retrieved using
PCRE2_INFO_LASTCODEUNIT. For anchored patterns, a last literal value is
@@ -2119,12 +2211,12 @@ PCRE2_INFO_LASTCODEUNIT), but for /^a\edz\ed/ the returned value is 0.
Return the value of the rightmost literal code unit that must exist in any
matched string, other than at its start, for a pattern where
PCRE2_INFO_LASTCODETYPE returns 1. Otherwise, return 0. The third argument
-should point to an \fBuint32_t\fP variable.
+should point to a \fBuint32_t\fP variable.
.sp
PCRE2_INFO_MATCHEMPTY
.sp
Return 1 if the pattern might match an empty string, otherwise 0. The third
-argument should point to an \fBuint32_t\fP variable. When a pattern contains
+argument should point to a \fBuint32_t\fP variable. When a pattern contains
recursive subroutine calls it is not always possible to determine whether or
not it can match an empty string. PCRE2 takes a cautious approach and returns 1
in such cases.
@@ -2140,26 +2232,35 @@ defaulted by the caller of the match function.
.sp
PCRE2_INFO_MAXLOOKBEHIND
.sp
-Return the number of characters (not code units) in the longest lookbehind
-assertion in the pattern. The third argument should point to a uint32_t
-integer. This information is useful when doing multi-segment matching using the
-partial matching facilities. Note that the simple assertions \eb and \eB
-require a one-character lookbehind. \eA also registers a one-character
-lookbehind, though it does not actually inspect the previous character. This is
-to ensure that at least one character from the old segment is retained when a
-new segment is processed. Otherwise, if there are no lookbehinds in the
-pattern, \eA might match incorrectly at the start of a second or subsequent
-segment.
+A lookbehind assertion moves back a certain number of characters (not code
+units) when it starts to process each of its branches. This request returns the
+largest of these backward moves. The third argument should point to a uint32_t
+integer. The simple assertions \eb and \eB require a one-character lookbehind
+and cause PCRE2_INFO_MAXLOOKBEHIND to return 1 in the absence of anything
+longer. \eA also registers a one-character lookbehind, though it does not
+actually inspect the previous character.
+.P
+Note that this information is useful for multi-segment matching only
+if the pattern contains no nested lookbehinds. For example, the pattern
+(?<=a(?<=ba)c) returns a maximum lookbehind of 2, but when it is processed, the
+first lookbehind moves back by two characters, matches one character, then the
+nested lookbehind also moves back by two characters. This puts the matching
+point three characters earlier than it was at the start.
+PCRE2_INFO_MAXLOOKBEHIND is really only useful as a debugging tool. See the
+.\" HREF
+\fBpcre2partial\fP
+.\"
+documentation for a discussion of multi-segment matching.
.sp
PCRE2_INFO_MINLENGTH
.sp
If a minimum length for matching subject strings was computed, its value is
-returned. Otherwise the returned value is 0. The value is a number of
-characters, which in UTF mode may be different from the number of code units.
-The third argument should point to an \fBuint32_t\fP variable. The value is a
-lower bound to the length of any matching string. There may not be any strings
-of that length that do actually match, but every string that does match is at
-least that long.
+returned. Otherwise the returned value is 0. This value is not computed when
+PCRE2_NO_START_OPTIMIZE is set. The value is a number of characters, which in
+UTF mode may be different from the number of code units. The third argument
+should point to a \fBuint32_t\fP variable. The value is a lower bound to the
+length of any matching string. There may not be any strings of that length that
+do actually match, but every string that does match is at least that long.
.sp
PCRE2_INFO_NAMECOUNT
PCRE2_INFO_NAMEENTRYSIZE
@@ -2189,11 +2290,11 @@ library, the pointer points to 32-bit code units, the first of which contains
the parenthesis number. The rest of the entry is the corresponding name, zero
terminated.
.P
-The names are in alphabetical order. If (?| is used to create multiple groups
-with the same number, as described in the
-.\" HTML
+The names are in alphabetical order. If (?| is used to create multiple capture
+groups with the same number, as described in the
+.\" HTML
.\"
-section on duplicate subpattern numbers
+section on duplicate group numbers
.\"
in the
.\" HREF
@@ -2202,11 +2303,11 @@ in the
page, the groups may be given the same name, but there is only one entry in the
table. Different names for groups of the same number are not permitted.
.P
-Duplicate names for subpatterns with different numbers are permitted, but only
-if PCRE2_DUPNAMES is set. They appear in the table in the order in which they
-were found in the pattern. In the absence of (?| this is the order of
+Duplicate names for capture groups with different numbers are permitted, but
+only if PCRE2_DUPNAMES is set. They appear in the table in the order in which
+they were found in the pattern. In the absence of (?| this is the order of
increasing number; when (?| is used this is not necessarily the case because
-later subpatterns may have lower numbers.
+later capture groups may have lower numbers.
.P
As a simple example of the name/number table, consider the following pattern
after compilation by the 8-bit library (assume PCRE2_EXTENDED is set, so white
@@ -2216,16 +2317,16 @@ space - including newlines - is ignored):
(? (?(\ed\ed)?\ed\ed) -
(?\ed\ed) - (?\ed\ed) )
.sp
-There are four named subpatterns, so the table has four entries, and each entry
-in the table is eight bytes long. The table is as follows, with non-printing
-bytes shows in hexadecimal, and undefined bytes shown as ??:
+There are four named capture groups, so the table has four entries, and each
+entry in the table is eight bytes long. The table is as follows, with
+non-printing bytes shows in hexadecimal, and undefined bytes shown as ??:
.sp
00 01 d a t e 00 ??
00 05 d a y 00 ?? ??
00 04 m o n t h 00
00 02 y e a r 00 ??
.sp
-When writing code to extract data from named subpatterns using the
+When writing code to extract data from named capture groups using the
name-to-number map, remember that the length of the entries is likely to be
different for each compiled pattern.
.sp
@@ -2362,9 +2463,16 @@ on the error, and is detailed below.
.P
When one of the matching functions is called, pointers to the compiled pattern
and the subject string are set in the match data block so that they can be
-referenced by the extraction functions. After running a match, you must not
-free a compiled pattern or a subject string until after all operations on the
-match data block (for that match) have taken place.
+referenced by the extraction functions after a successful match. After running
+a match, you must not free a compiled pattern or a subject string until after
+all operations on the match data block (for that match) have taken place,
+unless, in the case of the subject string, you have used the
+PCRE2_COPY_MATCHED_SUBJECT option, which is described in the section entitled
+"Option bits for \fBpcre2_match()\fP"
+.\" HTML
+.\"
+below.
+.\"
.P
When a match data block itself is no longer needed, it should be freed by
calling \fBpcre2_match_data_free()\fP. If this function is called with a NULL
@@ -2481,10 +2589,10 @@ the use of .* with PCRE2_DOTALL, not by starting the pattern with ^ or \eA.
.rs
.sp
The unused bits of the \fIoptions\fP argument for \fBpcre2_match()\fP must be
-zero. The only bits that may be set are PCRE2_ANCHORED, PCRE2_ENDANCHORED,
-PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART,
-PCRE2_NO_JIT, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, and PCRE2_PARTIAL_SOFT.
-Their action is described below.
+zero. The only bits that may be set are PCRE2_ANCHORED,
+PCRE2_COPY_MATCHED_SUBJECT, PCRE2_ENDANCHORED, PCRE2_NOTBOL, PCRE2_NOTEOL,
+PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_JIT, PCRE2_NO_UTF_CHECK,
+PCRE2_PARTIAL_HARD, and PCRE2_PARTIAL_SOFT. Their action is described below.
.P
Setting PCRE2_ANCHORED or PCRE2_ENDANCHORED at match time is not supported by
the just-in-time (JIT) compiler. If it is set, JIT matching is disabled and the
@@ -2498,6 +2606,22 @@ matching position. If a pattern was compiled with PCRE2_ANCHORED, or turned out
to be anchored by virtue of its contents, it cannot be made unachored at
matching time. Note that setting the option at match time disables JIT
matching.
+.sp
+ PCRE2_COPY_MATCHED_SUBJECT
+.sp
+By default, a pointer to the subject is remembered in the match data block so
+that, after a successful match, it can be referenced by the substring
+extraction functions. This means that the subject's memory must not be freed
+until all such operations are complete. For some applications where the
+lifetime of the subject string is not guaranteed, it may be necessary to make a
+copy of the subject string, but it is wasteful to do this unless the match is
+successful. After a successful match, if PCRE2_COPY_MATCHED_SUBJECT is set, the
+subject is copied and the new pointer is remembered in the match data block
+instead of the original subject pointer. The memory allocator that was used for
+the match block itself is used. The copy is automatically freed when
+\fBpcre2_match_data_free()\fP is called to free the match data block. It is also
+automatically freed if the match data block is re-used for another match
+operation.
.sp
PCRE2_ENDANCHORED
.sp
@@ -2553,15 +2677,23 @@ of JIT; it forces matching to be done by the interpreter.
PCRE2_NO_UTF_CHECK
.sp
When PCRE2_UTF is set at compile time, the validity of the subject as a UTF
-string is checked by default when \fBpcre2_match()\fP is subsequently called.
-If a non-zero starting offset is given, the check is applied only to that part
-of the subject that could be inspected during matching, and there is a check
-that the starting offset points to the first code unit of a character or to the
-end of the subject. If there are no lookbehind assertions in the pattern, the
-check starts at the starting offset. Otherwise, it starts at the length of the
-longest lookbehind before the starting offset, or at the start of the subject
-if there are not that many characters before the starting offset. Note that the
-sequences \eb and \eB are one-character lookbehinds.
+string is checked unless PCRE2_NO_UTF_CHECK is passed to \fBpcre2_match()\fP or
+PCRE2_MATCH_INVALID_UTF was passed to \fBpcre2_compile()\fP. The latter special
+case is discussed in detail in the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+documentation.
+.P
+In the default case, if a non-zero starting offset is given, the check is
+applied only to that part of the subject that could be inspected during
+matching, and there is a check that the starting offset points to the first
+code unit of a character or to the end of the subject. If there are no
+lookbehind assertions in the pattern, the check starts at the starting offset.
+Otherwise, it starts at the length of the longest lookbehind before the
+starting offset, or at the start of the subject if there are not that many
+characters before the starting offset. Note that the sequences \eb and \eB are
+one-character lookbehinds.
.P
The check is carried out before any other processing takes place, and a
negative error code is returned if the check fails. There are several UTF error
@@ -2584,29 +2716,34 @@ in the
.\" HREF
\fBpcre2unicode\fP
.\"
-page.
+documentation.
.P
-If you know that your subject is valid, and you want to skip these checks for
+If you know that your subject is valid, and you want to skip this check for
performance reasons, you can set the PCRE2_NO_UTF_CHECK option when calling
\fBpcre2_match()\fP. You might want to do this for the second and subsequent
-calls to \fBpcre2_match()\fP if you are making repeated calls to find other
+calls to \fBpcre2_match()\fP if you are making repeated calls to find multiple
matches in the same subject string.
.P
-\fBWarning:\fP When PCRE2_NO_UTF_CHECK is set, the effect of passing an invalid
+\fBWarning:\fP Unless PCRE2_MATCH_INVALID_UTF was set at compile time, when
+PCRE2_NO_UTF_CHECK is set at match time the effect of passing an invalid
string as a subject, or an invalid value of \fIstartoffset\fP, is undefined.
-Your program may crash or loop indefinitely.
+Your program may crash or loop indefinitely or give wrong results.
.sp
PCRE2_PARTIAL_HARD
PCRE2_PARTIAL_SOFT
.sp
These options turn on the partial matching feature. A partial match occurs if
the end of the subject string is reached successfully, but there are not enough
-subject characters to complete the match. If this happens when
-PCRE2_PARTIAL_SOFT (but not PCRE2_PARTIAL_HARD) is set, matching continues by
-testing any remaining alternatives. Only if no complete match can be found is
-PCRE2_ERROR_PARTIAL returned instead of PCRE2_ERROR_NOMATCH. In other words,
-PCRE2_PARTIAL_SOFT specifies that the caller is prepared to handle a partial
-match, but only if no complete match can be found.
+subject characters to complete the match. In addition, either at least one
+character must have been inspected or the pattern must contain a lookbehind, or
+the pattern must be one that could match an empty string.
+.P
+If this situation arises when PCRE2_PARTIAL_SOFT (but not PCRE2_PARTIAL_HARD)
+is set, matching continues by testing any remaining alternatives. Only if no
+complete match can be found is PCRE2_ERROR_PARTIAL returned instead of
+PCRE2_ERROR_NOMATCH. In other words, PCRE2_PARTIAL_SOFT specifies that the
+caller is prepared to handle a partial match, but only if no complete match can
+be found.
.P
If PCRE2_PARTIAL_HARD is set, it overrides PCRE2_PARTIAL_SOFT. In this case, if
a partial match is found, \fBpcre2_match()\fP immediately returns
@@ -2682,12 +2819,12 @@ valid newline sequence and explicit \er or \en escapes appear in the pattern.
In general, a pattern matches a certain portion of the subject, and in
addition, further substrings from the subject may be picked out by
parenthesized parts of the pattern. Following the usage in Jeffrey Friedl's
-book, this is called "capturing" in what follows, and the phrase "capturing
-subpattern" or "capturing group" is used for a fragment of a pattern that picks
-out a substring. PCRE2 supports several other kinds of parenthesized subpattern
-that do not cause substrings to be captured. The \fBpcre2_pattern_info()\fP
-function can be used to find out how many capturing subpatterns there are in a
-compiled pattern.
+book, this is called "capturing" in what follows, and the phrase "capture
+group" (Perl terminology) is used for a fragment of a pattern that picks out a
+substring. PCRE2 supports several other kinds of parenthesized group that do
+not cause substrings to be captured. The \fBpcre2_pattern_info()\fP function
+can be used to find out how many capture groups there are in a compiled
+pattern.
.P
You can use auxiliary functions for accessing captured substrings
.\" HTML
@@ -2740,30 +2877,28 @@ reported start of a successful match can be greater than the end of the match.
For example, if the pattern (?=ab\eK) is matched against "ab", the start and
end offset values for the match are 2 and 0.
.P
-If a capturing subpattern group is matched repeatedly within a single match
-operation, it is the last portion of the subject that it matched that is
-returned.
+If a capture group is matched repeatedly within a single match operation, it is
+the last portion of the subject that it matched that is returned.
.P
If the ovector is too small to hold all the captured substring offsets, as much
as possible is filled in, and the function returns a value of zero. If captured
substrings are not of interest, \fBpcre2_match()\fP may be called with a match
data block whose ovector is of minimum length (that is, one pair).
.P
-It is possible for capturing subpattern number \fIn+1\fP to match some part of
-the subject when subpattern \fIn\fP has not been used at all. For example, if
-the string "abc" is matched against the pattern (a|(z))(bc) the return from the
-function is 4, and subpatterns 1 and 3 are matched, but 2 is not. When this
-happens, both values in the offset pairs corresponding to unused subpatterns
-are set to PCRE2_UNSET.
-.P
-Offset values that correspond to unused subpatterns at the end of the
-expression are also set to PCRE2_UNSET. For example, if the string "abc" is
-matched against the pattern (abc)(x(yz)?)? subpatterns 2 and 3 are not matched.
-The return from the function is 2, because the highest used capturing
-subpattern number is 1. The offsets for for the second and third capturing
-subpatterns (assuming the vector is large enough, of course) are set to
+It is possible for capture group number \fIn+1\fP to match some part of the
+subject when group \fIn\fP has not been used at all. For example, if the string
+"abc" is matched against the pattern (a|(z))(bc) the return from the function
+is 4, and groups 1 and 3 are matched, but 2 is not. When this happens, both
+values in the offset pairs corresponding to unused groups are set to
PCRE2_UNSET.
.P
+Offset values that correspond to unused groups at the end of the expression are
+also set to PCRE2_UNSET. For example, if the string "abc" is matched against
+the pattern (abc)(x(yz)?)? groups 2 and 3 are not matched. The return from the
+function is 2, because the highest used capture group number is 1. The offsets
+for for the second and third capture groupss (assuming the vector is large
+enough, of course) are set to PCRE2_UNSET.
+.P
Elements in the ovector that do not correspond to capturing parentheses in the
pattern are never changed. That is, if a pattern contains \fIn\fP capturing
parentheses, no more than \fIovector[0]\fP to \fIovector[2n+1]\fP are set by
@@ -2787,21 +2922,22 @@ appropriate circumstances. If they are called at other times, the result is
undefined.
.P
After a successful match, a partial match (PCRE2_ERROR_PARTIAL), or a failure
-to match (PCRE2_ERROR_NOMATCH), a (*MARK), (*PRUNE), or (*THEN) name may be
-available. The function \fBpcre2_get_mark()\fP can be called to access this
-name. The same function applies to all three verbs. It returns a pointer to the
-zero-terminated name, which is within the compiled pattern. If no name is
+to match (PCRE2_ERROR_NOMATCH), a mark name may be available. The function
+\fBpcre2_get_mark()\fP can be called to access this name, which can be
+specified in the pattern by any of the backtracking control verbs, not just
+(*MARK). The same function applies to all the verbs. It returns a pointer to
+the zero-terminated name, which is within the compiled pattern. If no name is
available, NULL is returned. The length of the name (excluding the terminating
zero) is stored in the code unit that precedes the name. You should use this
length instead of relying on the terminating zero if the name might contain a
binary zero.
.P
-After a successful match, the name that is returned is the last (*MARK),
-(*PRUNE), or (*THEN) name encountered on the matching path through the pattern.
-Instances of (*PRUNE) and (*THEN) without names are ignored. Thus, for example,
-if the matching path contains (*MARK:A)(*PRUNE), the name "A" is returned.
-After a "no match" or a partial match, the last encountered name is returned.
-For example, consider this pattern:
+After a successful match, the name that is returned is the last mark name
+encountered on the matching path through the pattern. Instances of backtracking
+verbs without names do not count. Thus, for example, if the matching path
+contains (*MARK:A)(*PRUNE), the name "A" is returned. After a "no match" or a
+partial match, the last encountered name is returned. For example, consider
+this pattern:
.sp
^(*MARK:A)((*MARK:B)a|b)c
.sp
@@ -2815,7 +2951,7 @@ is removed from the pattern above, there is an initial check for the presence
of "c" in the subject before running the matching engine. This check fails for
"bx", causing a match failure without seeing any marks. You can disable the
start-of-match optimizations by setting the PCRE2_NO_START_OPTIMIZE option for
-\fBpcre2_compile()\fP or starting the pattern with (*NO_START_OPT).
+\fBpcre2_compile()\fP or by starting the pattern with (*NO_START_OPT).
.P
After a successful match, a partial match, or one of the invalid UTF errors
(for example, PCRE2_ERROR_UTF8_ERR5), \fBpcre2_get_startchar()\fP can be
@@ -2935,7 +3071,8 @@ The backtracking match limit was reached.
If a pattern contains many nested backtracking points, heap memory is used to
remember them. This error is given when the memory allocation function (default
or custom) fails. Note that a different error, PCRE2_ERROR_HEAPLIMIT, is given
-if the amount of memory needed exceeds the heap limit.
+if the amount of memory needed exceeds the heap limit. PCRE2_ERROR_NOMEMORY is
+also returned if PCRE2_COPY_MATCHED_SUBJECT is set and memory allocation fails.
.sp
PCRE2_ERROR_NULL
.sp
@@ -2946,11 +3083,11 @@ as NULL.
.sp
This error is returned when \fBpcre2_match()\fP detects a recursion loop within
the pattern. Specifically, it means that either the whole pattern or a
-subpattern has been called recursively for the second time at the same position
-in the subject string. Some simple patterns that might do this are detected and
-faulted at compile time, but more complicated cases, in particular mutual
-recursions between two different subpatterns, cannot be detected until matching
-is attempted.
+capture group has been called recursively for the second time at the same
+position in the subject string. Some simple patterns that might do this are
+detected and faulted at compile time, but more complicated cases, in particular
+mutual recursions between two different groups, cannot be detected until
+matching is attempted.
.
.
.\" HTML
@@ -3030,7 +3167,7 @@ The \fBpcre2_substring_copy_bynumber()\fP function copies a captured substring
into a supplied buffer, whereas \fBpcre2_substring_get_bynumber()\fP copies it
into new memory, obtained using the same memory allocation function that was
used for the match data block. The first two arguments of these functions are a
-pointer to the match data block and a capturing group number.
+pointer to the match data block and a capture group number.
.P
The final arguments of \fBpcre2_substring_copy_bynumber()\fP are a pointer to
the buffer and a pointer to a variable that contains its length in code units.
@@ -3102,9 +3239,9 @@ could not be obtained. When the list is no longer needed, it should be freed by
calling \fBpcre2_substring_list_free()\fP.
.P
If this function encounters a substring that is unset, which can happen when
-capturing subpattern number \fIn+1\fP matches some part of the subject, but
-subpattern \fIn\fP has not been used at all, it returns an empty string. This
-can be distinguished from a genuine zero-length substring by inspecting the
+capture group number \fIn+1\fP matches some part of the subject, but group
+\fIn\fP has not been used at all, it returns an empty string. This can be
+distinguished from a genuine zero-length substring by inspecting the
appropriate offset in the ovector, which contain PCRE2_UNSET for unset
substrings, or by calling \fBpcre2_substring_length_bynumber()\fP.
.
@@ -3134,20 +3271,20 @@ For example, for this pattern:
.sp
(a+)b(?\ed+)...
.sp
-the number of the subpattern called "xxx" is 2. If the name is known to be
+the number of the capture group called "xxx" is 2. If the name is known to be
unique (PCRE2_DUPNAMES was not set), you can find the number from the name by
calling \fBpcre2_substring_number_from_name()\fP. The first argument is the
compiled pattern, and the second is the name. The yield of the function is the
-subpattern number, PCRE2_ERROR_NOSUBSTRING if there is no subpattern of that
-name, or PCRE2_ERROR_NOUNIQUESUBSTRING if there is more than one subpattern of
-that name. Given the number, you can extract the substring directly from the
-ovector, or use one of the "bynumber" functions described above.
+group number, PCRE2_ERROR_NOSUBSTRING if there is no group with that name, or
+PCRE2_ERROR_NOUNIQUESUBSTRING if there is more than one group with that name.
+Given the number, you can extract the substring directly from the ovector, or
+use one of the "bynumber" functions described above.
.P
For convenience, there are also "byname" functions that correspond to the
"bynumber" functions, the only difference being that the second argument is a
name instead of a number. If PCRE2_DUPNAMES is set and there are duplicate
names, these functions scan all the groups with the given name, and return the
-first named string that is set.
+captured substring from the first named group that is set.
.P
If there are no groups with the given name, PCRE2_ERROR_NOSUBSTRING is
returned. If all groups with the name have numbers that are greater than the
@@ -3156,21 +3293,22 @@ is at least one group with a slot in the ovector, but no group is found to be
set, PCRE2_ERROR_UNSET is returned.
.P
\fBWarning:\fP If the pattern uses the (?| feature to set up multiple
-subpatterns with the same number, as described in the
-.\" HTML
+capture groups with the same number, as described in the
+.\" HTML
.\"
-section on duplicate subpattern numbers
+section on duplicate group numbers
.\"
in the
.\" HREF
\fBpcre2pattern\fP
.\"
-page, you cannot use names to distinguish the different subpatterns, because
+page, you cannot use names to distinguish the different capture groups, because
names are not included in the compiled code. The matching process uses only
-numbers. For this reason, the use of different names for subpatterns of the
+numbers. For this reason, the use of different names for groups with the
same number causes an error at compile time.
.
.
+.\" HTML
.SH "CREATING A NEW STRING WITH SUBSTITUTIONS"
.rs
.sp
@@ -3179,19 +3317,22 @@ same number causes an error at compile time.
.B " PCRE2_SIZE \fIlength\fP, PCRE2_SIZE \fIstartoffset\fP,"
.B " uint32_t \fIoptions\fP, pcre2_match_data *\fImatch_data\fP,"
.B " pcre2_match_context *\fImcontext\fP, PCRE2_SPTR \fIreplacement\fP,"
-.B " PCRE2_SIZE \fIrlength\fP, PCRE2_UCHAR *\fIoutputbuffer\zfP,"
+.B " PCRE2_SIZE \fIrlength\fP, PCRE2_UCHAR *\fIoutputbuffer\fP,"
.B " PCRE2_SIZE *\fIoutlengthptr\fP);"
.fi
.P
This function calls \fBpcre2_match()\fP and then makes a copy of the subject
-string in \fIoutputbuffer\fP, replacing the part that was matched with the
-\fIreplacement\fP string, whose length is supplied in \fBrlength\fP. This can
-be given as PCRE2_ZERO_TERMINATED for a zero-terminated string. Matches in
-which a \eK item in a lookahead in the pattern causes the match to end before
-it starts are not supported, and give rise to an error return. For global
-replacements, matches in which \eK in a lookbehind causes the match to start
-earlier than the point that was reached in the previous iteration are also not
-supported.
+string in \fIoutputbuffer\fP, replacing one or more parts that were matched
+with the \fIreplacement\fP string, whose length is supplied in \fBrlength\fP.
+This can be given as PCRE2_ZERO_TERMINATED for a zero-terminated string.
+The default is to perform just one replacement, but there is an option that
+requests multiple replacements (see PCRE2_SUBSTITUTE_GLOBAL below for details).
+.P
+Matches in which a \eK item in a lookahead in the pattern causes the match to
+end before it starts are not supported, and give rise to an error return. For
+global replacements, matches in which \eK in a lookbehind causes the match to
+start earlier than the point that was reached in the previous iteration are
+also not supported.
.P
The first seven arguments of \fBpcre2_substitute()\fP are the same as for
\fBpcre2_match()\fP, except that the partial matching options are not
@@ -3201,9 +3342,9 @@ functions from the match context, if provided, or else those that were used to
allocate memory for the compiled code.
.P
If an external \fImatch_data\fP block is provided, its contents afterwards
-are those set by the final call to \fBpcre2_match()\fP, which will have
-ended in a matching error. The contents of the ovector within the match data
-block may or may not have been changed.
+are those set by the final call to \fBpcre2_match()\fP. For global changes,
+this will have ended in a matching error. The contents of the ovector within
+the match data block may or may not have been changed.
.P
The \fIoutlengthptr\fP argument must point to a variable that contains the
length, in code units, of the output buffer. If the function is successful, the
@@ -3224,12 +3365,12 @@ length is in code units, not bytes.
In the replacement string, which is interpreted as a UTF string in UTF mode,
and is checked for UTF validity unless the PCRE2_NO_UTF_CHECK option is set, a
dollar character is an escape character that can specify the insertion of
-characters from capturing groups or (*MARK), (*PRUNE), or (*THEN) items in the
-pattern. The following forms are always recognized:
+characters from capture groups or names from (*MARK) or other control verbs
+in the pattern. The following forms are always recognized:
.sp
$$ insert a dollar character
$ or ${} insert the contents of group
- $*MARK or ${*MARK} insert a (*MARK), (*PRUNE), or (*THEN) name
+ $*MARK or ${*MARK} insert a control verb name
.sp
Either a group number or a group name can be given for . Curly brackets are
required only if the following character would be interpreted as part of the
@@ -3237,11 +3378,11 @@ number or name. The number may be zero to include the entire matched string.
For example, if the pattern a(b)c is matched with "=abc=" and the replacement
string "+$1$0$1+", the result is "=+babcb+=".
.P
-$*MARK inserts the name from the last encountered (*MARK), (*PRUNE), or (*THEN)
-on the matching path that has a name. (*MARK) must always include a name, but
-(*PRUNE) and (*THEN) need not. For example, in the case of (*MARK:A)(*PRUNE)
-the name inserted is "A", but for (*MARK:A)(*PRUNE:B) the relevant name is "B".
-This facility can be used to perform simple simultaneous substitutions, as this
+$*MARK inserts the name from the last encountered backtracking control verb on
+the matching path that has a name. (*MARK) must always include a name, but the
+other verbs need not. For example, in the case of (*MARK:A)(*PRUNE) the name
+inserted is "A", but for (*MARK:A)(*PRUNE:B) the relevant name is "B". This
+facility can be used to perform simple simultaneous substitutions, as this
\fBpcre2test\fP example shows:
.sp
/(*MARK:pear)apple|(*MARK:orange)lemon/g,replace=${*MARK}
@@ -3287,12 +3428,12 @@ operation is carried out twice. Depending on the application, it may be more
efficient to allocate a large buffer and free the excess afterwards, instead of
using PCRE2_SUBSTITUTE_OVERFLOW_LENGTH.
.P
-PCRE2_SUBSTITUTE_UNKNOWN_UNSET causes references to capturing groups that do
+PCRE2_SUBSTITUTE_UNKNOWN_UNSET causes references to capture groups that do
not appear in the pattern to be treated as unset groups. This option should be
used with care, because it means that a typo in a group name or number no
longer causes the PCRE2_ERROR_NOSUBSTRING error.
.P
-PCRE2_SUBSTITUTE_UNSET_EMPTY causes unset capturing groups (including unknown
+PCRE2_SUBSTITUTE_UNSET_EMPTY causes unset capture groups (including unknown
groups when PCRE2_SUBSTITUTE_UNKNOWN_UNSET is set) to be treated as empty
strings when inserted as described above. If this option is not set, an attempt
to insert an unset group causes the PCRE2_ERROR_UNSET error. This option does
@@ -3317,14 +3458,16 @@ terminating a \eQ quoted sequence) reverts to no case forcing. The sequences
\eu and \el force the next character (if it is a letter) to upper or lower
case, respectively, and then the state automatically reverts to no case
forcing. Case forcing applies to all inserted characters, including those from
-captured groups and letters within \eQ...\eE quoted sequences.
+capture groups and letters within \eQ...\eE quoted sequences.
.P
Note that case forcing sequences such as \eU...\eE do not nest. For example,
the result of processing "\eUaa\eLBB\eEcc\eE" is "AAbbcc"; the final \eE has no
-effect.
+effect. Note also that the PCRE2_ALT_BSUX and PCRE2_EXTRA_ALT_BSUX options do
+not apply to replacement strings.
.P
The second effect of setting PCRE2_SUBSTITUTE_EXTENDED is to add more
-flexibility to group substitution. The syntax is similar to that used by Bash:
+flexibility to capture group substitution. The syntax is similar to that used
+by Bash:
.sp
${:-}
${:+:}
@@ -3351,9 +3494,9 @@ The PCRE2_SUBSTITUTE_UNSET_EMPTY option does not affect these extended
substitutions. However, PCRE2_SUBSTITUTE_UNKNOWN_UNSET does cause unknown
groups in the extended syntax forms to be treated as unset.
.P
-If successful, \fBpcre2_substitute()\fP returns the number of replacements that
-were made. This may be zero if no matches were found, and is never greater than
-1 unless PCRE2_SUBSTITUTE_GLOBAL is set.
+If successful, \fBpcre2_substitute()\fP returns the number of successful
+matches. This may be zero if no matches were found, and is never greater than 1
+unless PCRE2_SUBSTITUTE_GLOBAL is set.
.P
In the event of an error, a negative error code is returned. Except for
PCRE2_ERROR_NOMATCH (which is never returned), errors from \fBpcre2_match()\fP
@@ -3388,7 +3531,65 @@ above).
.\"
.
.
-.SH "DUPLICATE SUBPATTERN NAMES"
+.SS "Substitution callouts"
+.rs
+.sp
+.nf
+.B int pcre2_set_substitute_callout(pcre2_match_context *\fImcontext\fP,
+.B " int (*\fIcallout_function\fP)(pcre2_substitute_callout_block *, void *),"
+.B " void *\fIcallout_data\fP);"
+.fi
+.sp
+The \fBpcre2_set_substitution_callout()\fP function can be used to specify a
+callout function for \fBpcre2_substitute()\fP. This information is passed in
+a match context. The callout function is called after each substitution has
+been processed, but it can cause the replacement not to happen. The callout
+function is not called for simulated substitutions that happen as a result of
+the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option.
+.P
+The first argument of the callout function is a pointer to a substitute callout
+block structure, which contains the following fields, not necessarily in this
+order:
+.sp
+ uint32_t \fIversion\fP;
+ uint32_t \fIsubscount\fP;
+ PCRE2_SPTR \fIinput\fP;
+ PCRE2_SPTR \fIoutput\fP;
+ PCRE2_SIZE \fI*ovector\fP;
+ uint32_t \fIoveccount\fP;
+ PCRE2_SIZE \fIoutput_offsets[2]\fP;
+.sp
+The \fIversion\fP field contains the version number of the block format. The
+current version is 0. The version number will increase in future if more fields
+are added, but the intention is never to remove any of the existing fields.
+.P
+The \fIsubscount\fP field is the number of the current match. It is 1 for the
+first callout, 2 for the second, and so on. The \fIinput\fP and \fIoutput\fP
+pointers are copies of the values passed to \fBpcre2_substitute()\fP.
+.P
+The \fIovector\fP field points to the ovector, which contains the result of the
+most recent match. The \fIoveccount\fP field contains the number of pairs that
+are set in the ovector, and is always greater than zero.
+.P
+The \fIoutput_offsets\fP vector contains the offsets of the replacement in the
+output string. This has already been processed for dollar and (if requested)
+backslash substitutions as described above.
+.P
+The second argument of the callout function is the value passed as
+\fIcallout_data\fP when the function was registered. The value returned by the
+callout function is interpreted as follows:
+.P
+If the value is zero, the replacement is accepted, and, if
+PCRE2_SUBSTITUTE_GLOBAL is set, processing continues with a search for the next
+match. If the value is not zero, the current replacement is not accepted. If
+the value is greater than zero, processing continues when
+PCRE2_SUBSTITUTE_GLOBAL is set. Otherwise (the value is less than zero or
+PCRE2_SUBSTITUTE_GLOBAL is not set), the the rest of the input is copied to the
+output and the call to \fBpcre2_substitute()\fP exits, returning the number of
+matches so far.
+.
+.
+.SH "DUPLICATE CAPTURE GROUP NAMES"
.rs
.sp
.nf
@@ -3396,13 +3597,14 @@ above).
.B " PCRE2_SPTR \fIname\fP, PCRE2_SPTR *\fIfirst\fP, PCRE2_SPTR *\fIlast\fP);"
.fi
.P
-When a pattern is compiled with the PCRE2_DUPNAMES option, names for
-subpatterns are not required to be unique. Duplicate names are always allowed
-for subpatterns with the same number, created by using the (?| feature. Indeed,
-if such subpatterns are named, they are required to use the same names.
+When a pattern is compiled with the PCRE2_DUPNAMES option, names for capture
+groups are not required to be unique. Duplicate names are always allowed for
+groups with the same number, created by using the (?| feature. Indeed, if such
+groups are named, they are required to use the same names.
.P
-Normally, patterns with duplicate names are such that in any one match, only
-one of the named subpatterns participates. An example is shown in the
+Normally, patterns that use duplicate names are such that in any one match,
+only one of each set of identically-named groups participates. An example is
+shown in the
.\" HREF
\fBpcre2pattern\fP
.\"
@@ -3512,11 +3714,12 @@ Here is an example of a simple call to \fBpcre2_dfa_match()\fP:
.rs
.sp
The unused bits of the \fIoptions\fP argument for \fBpcre2_dfa_match()\fP must
-be zero. The only bits that may be set are PCRE2_ANCHORED, PCRE2_ENDANCHORED,
-PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART,
-PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, PCRE2_PARTIAL_SOFT, PCRE2_DFA_SHORTEST,
-and PCRE2_DFA_RESTART. All but the last four of these are exactly the same as
-for \fBpcre2_match()\fP, so their description is not repeated here.
+be zero. The only bits that may be set are PCRE2_ANCHORED,
+PCRE2_COPY_MATCHED_SUBJECT, PCRE2_ENDANCHORED, PCRE2_NOTBOL, PCRE2_NOTEOL,
+PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD,
+PCRE2_PARTIAL_SOFT, PCRE2_DFA_SHORTEST, and PCRE2_DFA_RESTART. All but the last
+four of these are exactly the same as for \fBpcre2_match()\fP, so their
+description is not repeated here.
.sp
PCRE2_PARTIAL_HARD
PCRE2_PARTIAL_SOFT
@@ -3582,9 +3785,8 @@ the three matched strings are
On success, the yield of the function is a number greater than zero, which is
the number of matched substrings. The offsets of the substrings are returned in
the ovector, and can be extracted by number in the same way as for
-\fBpcre2_match()\fP, but the numbers bear no relation to any capturing groups
-that may exist in the pattern, because DFA matching does not support group
-capture.
+\fBpcre2_match()\fP, but the numbers bear no relation to any capture groups
+that may exist in the pattern, because DFA matching does not support capturing.
.P
Calls to the convenience functions that extract substrings by name
return the error PCRE2_ERROR_DFA_UFUNC (unsupported function) if used after a
@@ -3626,7 +3828,13 @@ a backreference.
.sp
This return is given if \fBpcre2_dfa_match()\fP encounters a condition item
that uses a backreference for the condition, or a test for recursion in a
-specific group. These are not supported.
+specific capture group. These are not supported.
+.sp
+ PCRE2_ERROR_DFA_UINVALID_UTF
+.sp
+This return is given if \fBpcre2_dfa_match()\fP is called for a pattern that
+was compiled with PCRE2_MATCH_INVALID_UTF. This is not supported for DFA
+matching.
.sp
PCRE2_ERROR_DFA_WSSIZE
.sp
@@ -3635,9 +3843,9 @@ This return is given if \fBpcre2_dfa_match()\fP runs out of space in the
.sp
PCRE2_ERROR_DFA_RECURSE
.sp
-When a recursive subpattern is processed, the matching function calls itself
-recursively, using private memory for the ovector and \fIworkspace\fP. This
-error is given if the internal ovector is not large enough. This should be
+When a recursion or subroutine call is processed, the matching function calls
+itself recursively, using private memory for the ovector and \fIworkspace\fP.
+This error is given if the internal ovector is not large enough. This should be
extremely rare, as a vector of size 1000 is used.
.sp
PCRE2_ERROR_DFA_BADRESTART
@@ -3670,6 +3878,6 @@ Cambridge, England.
.rs
.sp
.nf
-Last updated: 07 September 2018
-Copyright (c) 1997-2018 University of Cambridge.
+Last updated: 02 September 2019
+Copyright (c) 1997-2019 University of Cambridge.
.fi
diff --git a/doc/pcre2build.3 b/doc/pcre2build.3
index 540df78..f1d28f8 100644
--- a/doc/pcre2build.3
+++ b/doc/pcre2build.3
@@ -1,4 +1,4 @@
-.TH PCRE2BUILD 3 "26 April 2018" "PCRE2 10.32"
+.TH PCRE2BUILD 3 "03 March 2019" "PCRE2 10.33"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.
@@ -373,14 +373,17 @@ environment.
.SH "PCRE2GREP SUPPORT FOR EXTERNAL SCRIPTS"
.rs
.sp
-By default, on non-Windows systems, \fBpcre2grep\fP supports the use of
-callouts with string arguments within the patterns it is matching, in order to
-run external scripts. For details, see the
+By default \fBpcre2grep\fP supports the use of callouts with string arguments
+within the patterns it is matching. There are two kinds: one that generates
+output using local code, and another that calls an external program or script.
+If --disable-pcre2grep-callout-fork is added to the \fBconfigure\fP command,
+only the first kind of callout is supported; if --disable-pcre2grep-callout is
+used, all callouts are completely ignored. For more details of \fBpcre2grep\fP
+callouts, see the
.\" HREF
\fBpcre2grep\fP
.\"
-documentation. This support can be disabled by adding
---disable-pcre2grep-callout to the \fBconfigure\fP command.
+documentation.
.
.
.SH "PCRE2GREP OPTIONS FOR COMPRESSED FILE SUPPORT"
@@ -533,6 +536,22 @@ information about code coverage, see the \fBgcov\fP and \fBlcov\fP
documentation.
.
.
+.SH "DISABLING THE Z AND T FORMATTING MODIFIERS"
+.rs
+.sp
+The C99 standard defines formatting modifiers z and t for size_t and
+ptrdiff_t values, respectively. By default, PCRE2 uses these modifiers in
+environments other than Microsoft Visual Studio when __STDC_VERSION__ is
+defined and has a value greater than or equal to 199901L (indicating C99).
+However, there is at least one environment that claims to be C99 but does not
+support these modifiers. If
+.sp
+ --disable-percent-zt
+.sp
+is specified, no use is made of the z or t modifiers. Instead or %td or %zu,
+%lu is used, with a cast for size_t values.
+.
+.
.SH "SUPPORT FOR FUZZERS"
.rs
.sp
@@ -591,6 +610,6 @@ Cambridge, England.
.rs
.sp
.nf
-Last updated: 26 April 2018
-Copyright (c) 1997-2018 University of Cambridge.
+Last updated: 03 March 2019
+Copyright (c) 1997-2019 University of Cambridge.
.fi
diff --git a/doc/pcre2callout.3 b/doc/pcre2callout.3
index c815c72..adb411b 100644
--- a/doc/pcre2callout.3
+++ b/doc/pcre2callout.3
@@ -1,4 +1,4 @@
-.TH PCRE2CALLOUT 3 "26 April 2018" "PCRE2 10.32"
+.TH PCRE2CALLOUT 3 "03 February 2019" "PCRE2 10.33"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH SYNOPSIS
@@ -27,6 +27,15 @@ a match context (see \fBpcre2_set_callout()\fP in the
.\"
documentation).
.P
+When using the \fBpcre2_substitute()\fP function, an additional callout feature
+is available. This does a callout after each change to the subject string and
+is described in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation; the rest of this document is concerned with callouts during
+pattern matching.
+.P
Within a regular expression, (?C) indicates a point at which the external
function is to be called. Different callout points can be identified by putting
a number less than 256 after the letter C. The default value is zero.
@@ -128,7 +137,7 @@ start only after an internal newline or at the beginning of the subject, and
branch, automatic anchoring occurs if all branches are anchorable.
.P
This optimization is disabled, however, if .* is in an atomic group or if there
-is a backreference to the capturing group in which it appears. It is also
+is a backreference to the capture group in which it appears. It is also
disabled if the pattern contains (*PRUNE) or (*SKIP). However, the presence of
callouts does not affect it.
.P
@@ -322,8 +331,8 @@ callout before an assertion such as (?=ab) the length is 3. For an an
alternation bar or a closing parenthesis, the length is one, unless a closing
parenthesis is followed by a quantifier, in which case its length is included.
(This changed in release 10.23. In earlier releases, before an opening
-parenthesis the length was that of the entire subpattern, and before an
-alternation bar or a closing parenthesis the length was zero.)
+parenthesis the length was that of the entire group, and before an alternation
+bar or a closing parenthesis the length was zero.)
.P
The \fIpattern_position\fP and \fInext_item_length\fP fields are intended to
help in distinguishing between different automatic callouts, which all have the
@@ -443,6 +452,6 @@ Cambridge, England.
.rs
.sp
.nf
-Last updated: 26 April 2018
-Copyright (c) 1997-2018 University of Cambridge.
+Last updated: 03 February 2019
+Copyright (c) 1997-2019 University of Cambridge.
.fi
diff --git a/doc/pcre2compat.3 b/doc/pcre2compat.3
index 6e448f6..b4209db 100644
--- a/doc/pcre2compat.3
+++ b/doc/pcre2compat.3
@@ -1,4 +1,4 @@
-.TH PCRE2COMPAT 3 "28 July 2018" "PCRE2 10.32"
+.TH PCRE2COMPAT 3 "13 July 2019" "PCRE2 10.34"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH "DIFFERENCES BETWEEN PCRE2 AND PERL"
@@ -23,10 +23,9 @@ character is not "a" three times (in principle; PCRE2 optimizes this to run the
assertion just once). Perl allows some repeat quantifiers on other assertions,
for example, \eb* (but not \eb{3}), but these do not seem to have any use.
.P
-3. Capturing subpatterns that occur inside negative lookaround assertions are
-counted, but their entries in the offsets vector are set only when a negative
-assertion is a condition that has a matching branch (that is, the condition is
-false).
+3. Capture groups that occur inside negative lookaround assertions are counted,
+but their entries in the offsets vector are set only when a negative assertion
+is a condition that has a matching branch (that is, the condition is false).
.P
4. The following Perl escape sequences are not supported: \eF, \el, \eL, \eu,
\eU, and \eN when followed by a character name. \eN on its own, matching a
@@ -34,8 +33,9 @@ non-newline character, and \eN{U+dd..}, matching a Unicode code point, are
supported. The escapes that modify the case of following letters are
implemented by Perl's general string-handling and are not part of its pattern
matching engine. If any of these are encountered by PCRE2, an error is
-generated by default. However, if the PCRE2_ALT_BSUX option is set, \eU and \eu
-are interpreted as ECMAScript interprets them.
+generated by default. However, if either of the PCRE2_ALT_BSUX or
+PCRE2_EXTRA_ALT_BSUX options is set, \eU and \eu are interpreted as ECMAScript
+interprets them.
.P
5. The Perl escape sequences \ep, \eP, and \eX are supported only if PCRE2 is
built with Unicode support (the default). The properties that can be tested
@@ -79,13 +79,13 @@ documentation for details.
to PCRE2 release 10.23, but from release 10.30 this changed, and backtracking
into subroutine calls is now supported, as in Perl.
.P
-9. If any of the backtracking control verbs are used in a subpattern that is
-called as a subroutine (whether or not recursively), their effect is confined
-to that subpattern; it does not extend to the surrounding pattern. This is not
-always the case in Perl. In particular, if (*THEN) is present in a group that
-is called as a subroutine, its action is limited to that group, even if the
-group does not contain any | characters. Note that such subpatterns are
-processed as anchored at the point where they are tested.
+9. If any of the backtracking control verbs are used in a group that is called
+as a subroutine (whether or not recursively), their effect is confined to that
+group; it does not extend to the surrounding pattern. This is not always the
+case in Perl. In particular, if (*THEN) is present in a group that is called as
+a subroutine, its action is limited to that group, even if the group does not
+contain any | characters. Note that such groups are processed as anchored
+at the point where they are tested.
.P
10. If a pattern contains more than one backtracking control verb, the first
one that is backtracked onto acts. For example, in the pattern
@@ -101,21 +101,20 @@ strings when part of a pattern is repeated. For example, matching "aba" against
the pattern /^(a(b)?)+$/ in Perl leaves $2 unset, but in PCRE2 it is set to
"b".
.P
-13. PCRE2's handling of duplicate subpattern numbers and duplicate subpattern
-names is not as general as Perl's. This is a consequence of the fact the PCRE2
-works internally just with numbers, using an external table to translate
-between numbers and names. In particular, a pattern such as (?|(?A)|(?B),
-where the two capturing parentheses have the same number but different names,
-is not supported, and causes an error at compile time. If it were allowed, it
-would not be possible to distinguish which parentheses matched, because both
-names map to capturing subpattern number 1. To avoid this confusing situation,
-an error is given at compile time.
+13. PCRE2's handling of duplicate capture group numbers and names is not as
+general as Perl's. This is a consequence of the fact the PCRE2 works internally
+just with numbers, using an external table to translate between numbers and
+names. In particular, a pattern such as (?|(?A)|(?B), where the two
+capture groups have the same number but different names, is not supported, and
+causes an error at compile time. If it were allowed, it would not be possible
+to distinguish which group matched, because both names map to capture group
+number 1. To avoid this confusing situation, an error is given at compile time.
.P
14. Perl used to recognize comments in some places that PCRE2 does not, for
-example, between the ( and ? at the start of a subpattern. If the /x modifier
-is set, Perl allowed white space between ( and ? though the latest Perls give
-an error (for a while it was just deprecated). There may still be some cases
-where Perl behaves differently.
+example, between the ( and ? at the start of a group. If the /x modifier is
+set, Perl allowed white space between ( and ? though the latest Perls give an
+error (for a while it was just deprecated). There may still be some cases where
+Perl behaves differently.
.P
15. Perl, when in warning mode, gives warnings for character classes such as
[A-\ed] or [a-[:digit:]]. It then treats the hyphens as literals. PCRE2 has no
@@ -171,6 +170,10 @@ different way and is not Perl-compatible.
(l) PCRE2 recognizes some special sequences such as (*CR) or (*NO_JIT) at
the start of a pattern that set overall options that cannot be changed within
the pattern.
+.sp
+(m) PCRE2 supports non-atomic positive lookaround assertions. This is an
+extension to the lookaround facilities. The default, Perl-compatible
+lookarounds are atomic.
.P
18. The Perl /a modifier restricts /d numbers to pure ascii, and the /aa
modifier restricts /i case-insensitive matching to pure ascii, ignoring Unicode
@@ -200,6 +203,6 @@ Cambridge, England.
.rs
.sp
.nf
-Last updated: 28 July 2018
-Copyright (c) 1997-2018 University of Cambridge.
+Last updated: 13 July 2019
+Copyright (c) 1997-2019 University of Cambridge.
.fi
diff --git a/doc/pcre2demo.3 b/doc/pcre2demo.3
index a9e58e2..0d30145 100644
--- a/doc/pcre2demo.3
+++ b/doc/pcre2demo.3
@@ -104,12 +104,11 @@ uint32_t newline;
PCRE2_SIZE erroroffset;
PCRE2_SIZE *ovector;
+PCRE2_SIZE subject_length;
-size_t subject_length;
pcre2_match_data *match_data;
-
/**************************************************************************
* First, sort out the command line. There is only one possible option at *
* the moment, "-g" to request repeated matching to find all occurrences, *
@@ -138,12 +137,14 @@ if (argc - i != 2)
return 1;
}
-/* As pattern and subject are char arguments, they can be straightforwardly
-cast to PCRE2_SPTR as we are working in 8-bit code units. */
+/* Pattern and subject are char arguments, so they can be straightforwardly
+cast to PCRE2_SPTR because we are working in 8-bit code units. The subject
+length is cast to PCRE2_SIZE for completeness, though PCRE2_SIZE is in fact
+defined to be size_t. */
pattern = (PCRE2_SPTR)argv[i];
subject = (PCRE2_SPTR)argv[i+1];
-subject_length = strlen((char *)subject);
+subject_length = (PCRE2_SIZE)strlen((char *)subject);
/*************************************************************************
@@ -172,17 +173,22 @@ if (re == NULL)
/*************************************************************************
-* If the compilation succeeded, we call PCRE again, in order to do a *
+* If the compilation succeeded, we call PCRE2 again, in order to do a *
* pattern match against the subject string. This does just ONE match. If *
* further matching is needed, it will be done below. Before running the *
-* match we must set up a match_data block for holding the result. *
+* match we must set up a match_data block for holding the result. Using *
+* pcre2_match_data_create_from_pattern() ensures that the block is *
+* exactly the right size for the number of capturing parentheses in the *
+* pattern. If you need to know the actual size of a match_data block as *
+* a number of bytes, you can find it like this: *
+* *
+* PCRE2_SIZE match_data_size = pcre2_get_match_data_size(match_data); *
*************************************************************************/
-/* Using this function ensures that the block is exactly the right size for
-the number of capturing parentheses in the pattern. */
-
match_data = pcre2_match_data_create_from_pattern(re, NULL);
+/* Now run the match. */
+
rc = pcre2_match(
re, /* the compiled pattern */
subject, /* the subject string */
@@ -205,7 +211,7 @@ if (rc < 0)
default: printf("Matching error %d\en", rc); break;
}
pcre2_match_data_free(match_data); /* Release memory used for the match */
- pcre2_code_free(re); /* data and the compiled pattern. */
+ pcre2_code_free(re); /* data and the compiled pattern. */
return 1;
}
@@ -249,7 +255,7 @@ application you might want to do things other than print them. */
for (i = 0; i < rc; i++)
{
PCRE2_SPTR substring_start = subject + ovector[2*i];
- size_t substring_length = ovector[2*i+1] - ovector[2*i];
+ PCRE2_SIZE substring_length = ovector[2*i+1] - ovector[2*i];
printf("%2d: %.*s\en", i, (int)substring_length, (char *)substring_start);
}
diff --git a/doc/pcre2grep.1 b/doc/pcre2grep.1
index ce112af..22992b1 100644
--- a/doc/pcre2grep.1
+++ b/doc/pcre2grep.1
@@ -1,4 +1,4 @@
-.TH PCRE2GREP 1 "24 February 2018" "PCRE2 10.32"
+.TH PCRE2GREP 1 "15 June 2019" "PCRE2 10.34"
.SH NAME
pcre2grep - a grep with Perl-compatible regular expressions.
.SH SYNOPSIS
@@ -596,19 +596,29 @@ otherwise empty line. This option is mutually exclusive with \fB--output\fP,
.TP
\fB-o\fP\fInumber\fP, \fB--only-matching\fP=\fInumber\fP
Show only the part of the line that matched the capturing parentheses of the
-given number. Up to 32 capturing parentheses are supported, and -o0 is
-equivalent to \fB-o\fP without a number. Because these options can be given
-without an argument (see above), if an argument is present, it must be given in
-the same shell item, for example, -o3 or --only-matching=2. The comments given
-for the non-argument case above also apply to this option. If the specified
-capturing parentheses do not exist in the pattern, or were not set in the
-match, nothing is output unless the file name or line number are being output.
+given number. Up to 50 capturing parentheses are supported by default. This
+limit can be changed via the \fB--om-capture\fP option. A pattern may contain
+any number of capturing parentheses, but only those whose number is within the
+limit can be accessed by \fB-o\fP. An error occurs if the number specified by
+\fB-o\fP is greater than the limit.
+.sp
+-o0 is the same as \fB-o\fP without a number. Because these options can be
+given without an argument (see above), if an argument is present, it must be
+given in the same shell item, for example, -o3 or --only-matching=2. The
+comments given for the non-argument case above also apply to this option. If
+the specified capturing parentheses do not exist in the pattern, or were not
+set in the match, nothing is output unless the file name or line number are
+being output.
.sp
If this option is given multiple times, multiple substrings are output for each
match, in the order the options are given, and all on one line. For example,
-o3 -o1 -o3 causes the substrings matched by capturing parentheses 3 and 1 and
then 3 again to be output. By default, there is no separator (but see the next
-option).
+but one option).
+.TP
+\fB--om-capture\fP=\fInumber\fP
+Set the number of capturing parentheses that can be accessed by \fB-o\fP. The
+default is 50.
.TP
\fB--om-separator\fP=\fItext\fP
Specify a separating string for multiple occurrences of \fB-o\fP. The default
@@ -644,12 +654,22 @@ is listed. If file names are being output, the grand total is preceded by
ignored when used with \fB-L\fP (list files without matches), because the grand
total would always be zero.
.TP
-\fB-u\fP, \fB--utf-8\fP
+\fB-u\fP, \fB--utf\fP
Operate in UTF-8 mode. This option is available only if PCRE2 has been compiled
with UTF-8 support. All patterns (including those for any \fB--exclude\fP and
\fB--include\fP options) and all subject lines that are scanned must be valid
strings of UTF-8 characters.
.TP
+\fB-U\fP, \fB--utf-allow-invalid\fP
+As \fB--utf\fP, but in addition subject lines may contain invalid UTF-8 code
+unit sequences. These can never form part of any pattern match. This facility
+allows valid UTF-8 strings to be sought in executable or other binary files.
+For more details about matching in non-valid UTF-8 strings, see the
+.\" HREF
+\fBpcre2unicode\fP(3)
+.\"
+documentation.
+.TP
\fB-V\fP, \fB--version\fP
Write the version numbers of \fBpcre2grep\fP and the PCRE2 library to the
standard output and then exit. Anything else on the command line is
@@ -711,9 +731,9 @@ as in the GNU \fBgrep\fP program. Any long option of the form
\fB--file-offsets\fP, \fB--heap-limit\fP, \fB--include-dir\fP,
\fB--line-offsets\fP, \fB--locale\fP, \fB--match-limit\fP, \fB-M\fP,
\fB--multiline\fP, \fB-N\fP, \fB--newline\fP, \fB--om-separator\fP,
-\fB--output\fP, \fB-u\fP, and \fB--utf-8\fP options are specific to
-\fBpcre2grep\fP, as is the use of the \fB--only-matching\fP option with a
-capturing parentheses number.
+\fB--output\fP, \fB-u\fP, \fB--utf\fP, \fB-U\fP, and \fB--utf-allow-invalid\fP
+options are specific to \fBpcre2grep\fP, as is the use of the
+\fB--only-matching\fP option with a capturing parentheses number.
.P
Although most of the common options work the same way, a few are different in
\fBpcre2grep\fP. For example, the \fB--include\fP option's argument is a glob
@@ -759,10 +779,12 @@ character. Otherwise \fBpcre2grep\fP will assume that it has no data.
.sp
\fBpcre2grep\fP has, by default, support for calling external programs or
scripts or echoing specific strings during matching by making use of PCRE2's
-callout facility. However, this support can be disabled when \fBpcre2grep\fP is
-built. You can find out whether your binary has support for callouts by running
-it with the \fB--help\fP option. If the support is not enabled, all callouts in
-patterns are ignored by \fBpcre2grep\fP.
+callout facility. However, this support can be completely or partially disabled
+when \fBpcre2grep\fP is built. You can find out whether your binary has support
+for callouts by running it with the \fB--help\fP option. If callout support is
+completely disabled, all callouts in patterns are ignored by \fBpcre2grep\fP.
+If the facility is partially disabled, calling external programs is not
+supported, and callouts that request it are ignored.
.P
A callout in a PCRE2 pattern is of the form (?C) where the argument is
either a number or a quoted string (see the
@@ -776,6 +798,11 @@ only callouts with string arguments are useful.
.SS "Calling external programs or scripts"
.rs
.sp
+This facility can be independently disabled when \fBpcre2grep\fP is built. It
+is supported for Windows, where a call to \fB_spawnvp()\fP is used, for VMS,
+where \fBlib$spawn()\fP is used, and for any other Unix-like environment where
+\fBfork()\fP and \fBexecv()\fP are available.
+.P
If the callout string does not start with a pipe (vertical bar) character, it
is parsed into a list of substrings separated by pipe characters. The first
substring must be an executable name, with the following substrings specifying
@@ -803,7 +830,7 @@ a single dollar and $| is replaced by a pipe character. Here is an example:
Arg1: [1] [234] [4] Arg2: |1| ()
12345
.sp
-The parameters for the \fBexecv()\fP system call that is used to run the
+The parameters for the system call that is used to run the
program or script are zero-terminated strings. This means that binary zero
characters in the callout argument will cause premature termination of their
substrings, and therefore should not be present. Any syntax errors in the
@@ -816,14 +843,15 @@ matcher backtracks in the normal way.
.SS "Echoing a specific string"
.rs
.sp
-If the callout string starts with a pipe (vertical bar) character, the rest of
-the string is written to the output, having been passed through the same escape
-processing as text from the --output option. This provides a simple echoing
-facility that avoids calling an external program or script. No terminator is
-added to the string, so if you want a newline, you must include it explicitly.
-Matching continues normally after the string is output. If you want to see only
-the callout output but not any output from an actual match, you should end the
-relevant pattern with (*FAIL).
+This facility is always available, provided that callouts were not completely
+disabled when \fBpcre2grep\fP was built. If the callout string starts with a
+pipe (vertical bar) character, the rest of the string is written to the output,
+having been passed through the same escape processing as text from the --output
+option. This provides a simple echoing facility that avoids calling an external
+program or script. No terminator is added to the string, so if you want a
+newline, you must include it explicitly. Matching continues normally after the
+string is output. If you want to see only the callout output but not any output
+from an actual match, you should end the relevant pattern with (*FAIL).
.
.
.SH "MATCHING ERRORS"
@@ -876,6 +904,6 @@ Cambridge, England.
.rs
.sp
.nf
-Last updated: 24 February 2018
-Copyright (c) 1997-2018 University of Cambridge.
+Last updated: 15 June 2019
+Copyright (c) 1997-2019 University of Cambridge.
.fi
diff --git a/doc/pcre2grep.txt b/doc/pcre2grep.txt
index 000239c..b11092a 100644
--- a/doc/pcre2grep.txt
+++ b/doc/pcre2grep.txt
@@ -12,11 +12,11 @@ SYNOPSIS
DESCRIPTION
pcre2grep searches files for character patterns, in the same way as
- other grep commands do, but it uses the PCRE2 regular expression
- library to support patterns that are compatible with the regular
- expressions of Perl 5. See pcre2syntax(3) for a quick-reference summary
- of pattern syntax, or pcre2pattern(3) for a full description of the
- syntax and semantics of the regular expressions that PCRE2 supports.
+ other grep commands do, but it uses the PCRE2 regular expression li-
+ brary to support patterns that are compatible with the regular expres-
+ sions of Perl 5. See pcre2syntax(3) for a quick-reference summary of
+ pattern syntax, or pcre2pattern(3) for a full description of the syntax
+ and semantics of the regular expressions that PCRE2 supports.
Patterns, whether supplied on the command line or in a separate file,
are given without delimiters. For example:
@@ -26,8 +26,8 @@ DESCRIPTION
If you attempt to use delimiters (for example, by surrounding a pattern
with slashes, as is common in Perl scripts), they are interpreted as
part of the pattern. Quotes can of course be used to delimit patterns
- on the command line because they are interpreted by the shell, and
- indeed quotes are required if a pattern contains white space or shell
+ on the command line because they are interpreted by the shell, and in-
+ deed quotes are required if a pattern contains white space or shell
metacharacters.
The first argument that follows any option settings is treated as the
@@ -54,8 +54,8 @@ DESCRIPTION
controlled by parameters that can be set by the --buffer-size and
--max-buffer-size options. The first of these sets the size of buffer
that is obtained at the start of processing. If an input file contains
- very long lines, a larger buffer may be needed; this is handled by
- automatically extending the buffer, up to the limit specified by --max-
+ very long lines, a larger buffer may be needed; this is handled by au-
+ tomatically extending the buffer, up to the limit specified by --max-
buffer-size. The default values for these parameters can be set when
pcre2grep is built; if nothing is specified, the defaults are set to
20KiB and 1MiB respectively. An error occurs if a line is too long and
@@ -75,12 +75,12 @@ DESCRIPTION
By default, as soon as one pattern matches a line, no further patterns
are considered. However, if --colour (or --color) is used to colour the
matching substrings, or if --only-matching, --file-offsets, or --line-
- offsets is used to output only the part of the line that matched
- (either shown literally, or as an offset), scanning resumes immediately
+ offsets is used to output only the part of the line that matched (ei-
+ ther shown literally, or as an offset), scanning resumes immediately
following the match, so that further matches on the same line can be
- found. If there are multiple patterns, they are all tried on the
- remainder of the line, but patterns that follow the one that matched
- are not tried on the earlier part of the line.
+ found. If there are multiple patterns, they are all tried on the re-
+ mainder of the line, but patterns that follow the one that matched are
+ not tried on the earlier part of the line.
This behaviour means that the order in which multiple patterns are
specified can affect the output when one of the above options is used.
@@ -89,11 +89,11 @@ DESCRIPTION
overlap).
Patterns that can match an empty string are accepted, but empty string
- matches are never recognized. An example is the pattern
- "(super)?(man)?", in which all components are optional. This pattern
- finds all occurrences of both "super" and "man"; the output differs
- from matching with "super|man" when only the matching substrings are
- being shown.
+ matches are never recognized. An example is the pattern "(su-
+ per)?(man)?", in which all components are optional. This pattern finds
+ all occurrences of both "super" and "man"; the output differs from
+ matching with "super|man" when only the matching substrings are being
+ shown.
If the LC_ALL or LC_CTYPE environment variable is set, pcre2grep uses
the value to set a locale when calling the PCRE2 library. The --locale
@@ -116,153 +116,152 @@ BINARY FILES
By default, a file that contains a binary zero byte within the first
1024 bytes is identified as a binary file, and is processed specially.
(GNU grep identifies binary files in this manner.) However, if the new-
- line type is specified as "nul", that is, the line terminator is a
- binary zero, the test for a binary file is not applied. See the
- --binary-files option for a means of changing the way binary files are
- handled.
+ line type is specified as "nul", that is, the line terminator is a bi-
+ nary zero, the test for a binary file is not applied. See the --binary-
+ files option for a means of changing the way binary files are handled.
BINARY ZEROS IN PATTERNS
- Patterns passed from the command line are strings that are terminated
- by a binary zero, so cannot contain internal zeros. However, patterns
+ Patterns passed from the command line are strings that are terminated
+ by a binary zero, so cannot contain internal zeros. However, patterns
that are read from a file via the -f option may contain binary zeros.
OPTIONS
- The order in which some of the options appear can affect the output.
- For example, both the -H and -l options affect the printing of file
- names. Whichever comes later in the command line will be the one that
- takes effect. Similarly, except where noted below, if an option is
- given twice, the later setting is used. Numerical values for options
- may be followed by K or M, to signify multiplication by 1024 or
+ The order in which some of the options appear can affect the output.
+ For example, both the -H and -l options affect the printing of file
+ names. Whichever comes later in the command line will be the one that
+ takes effect. Similarly, except where noted below, if an option is
+ given twice, the later setting is used. Numerical values for options
+ may be followed by K or M, to signify multiplication by 1024 or
1024*1024 respectively.
-- This terminates the list of options. It is useful if the next
- item on the command line starts with a hyphen but is not an
- option. This allows for the processing of patterns and file
+ item on the command line starts with a hyphen but is not an
+ option. This allows for the processing of patterns and file
names that start with hyphens.
-A number, --after-context=number
- Output up to number lines of context after each matching
- line. Fewer lines are output if the next match or the end of
- the file is reached, or if the processing buffer size has
- been set too small. If file names and/or line numbers are
- being output, a hyphen separator is used instead of a colon
- for the context lines. A line containing "--" is output
- between each group of lines, unless they are in fact contigu-
- ous in the input file. The value of number is expected to be
- relatively small. When -c is used, -A is ignored.
+ Output up to number lines of context after each matching
+ line. Fewer lines are output if the next match or the end of
+ the file is reached, or if the processing buffer size has
+ been set too small. If file names and/or line numbers are be-
+ ing output, a hyphen separator is used instead of a colon for
+ the context lines. A line containing "--" is output between
+ each group of lines, unless they are in fact contiguous in
+ the input file. The value of number is expected to be rela-
+ tively small. When -c is used, -A is ignored.
-a, --text
- Treat binary files as text. This is equivalent to --binary-
+ Treat binary files as text. This is equivalent to --binary-
files=text.
-B number, --before-context=number
- Output up to number lines of context before each matching
- line. Fewer lines are output if the previous match or the
- start of the file is within number lines, or if the process-
- ing buffer size has been set too small. If file names and/or
- line numbers are being output, a hyphen separator is used
- instead of a colon for the context lines. A line containing
- "--" is output between each group of lines, unless they are
- in fact contiguous in the input file. The value of number is
- expected to be relatively small. When -c is used, -B is
- ignored.
+ Output up to number lines of context before each matching
+ line. Fewer lines are output if the previous match or the
+ start of the file is within number lines, or if the process-
+ ing buffer size has been set too small. If file names and/or
+ line numbers are being output, a hyphen separator is used in-
+ stead of a colon for the context lines. A line containing
+ "--" is output between each group of lines, unless they are
+ in fact contiguous in the input file. The value of number is
+ expected to be relatively small. When -c is used, -B is ig-
+ nored.
--binary-files=word
- Specify how binary files are to be processed. If the word is
- "binary" (the default), pattern matching is performed on
- binary files, but the only output is "Binary file
- matches" when a match succeeds. If the word is "text", which
- is equivalent to the -a or --text option, binary files are
- processed in the same way as any other file. In this case,
- when a match succeeds, the output may be binary garbage,
- which can have nasty effects if sent to a terminal. If the
- word is "without-match", which is equivalent to the -I
- option, binary files are not processed at all; they are
- assumed not to be of interest and are skipped without causing
- any output or affecting the return code.
+ Specify how binary files are to be processed. If the word is
+ "binary" (the default), pattern matching is performed on bi-
+ nary files, but the only output is "Binary file
+ matches" when a match succeeds. If the word is "text", which
+ is equivalent to the -a or --text option, binary files are
+ processed in the same way as any other file. In this case,
+ when a match succeeds, the output may be binary garbage,
+ which can have nasty effects if sent to a terminal. If the
+ word is "without-match", which is equivalent to the -I op-
+ tion, binary files are not processed at all; they are assumed
+ not to be of interest and are skipped without causing any
+ output or affecting the return code.
--buffer-size=number
- Set the parameter that controls how much memory is obtained
+ Set the parameter that controls how much memory is obtained
at the start of processing for buffering files that are being
scanned. See also --max-buffer-size below.
-C number, --context=number
- Output number lines of context both before and after each
- matching line. This is equivalent to setting both -A and -B
+ Output number lines of context both before and after each
+ matching line. This is equivalent to setting both -A and -B
to the same value.
-c, --count
- Do not output lines from the files that are being scanned;
- instead output the number of lines that would have been
+ Do not output lines from the files that are being scanned;
+ instead output the number of lines that would have been
shown, either because they matched, or, if -v is set, because
- they failed to match. By default, this count is exactly the
- same as the number of lines that would have been output, but
- if the -M (multiline) option is used (without -v), there may
- be more suppressed lines than the count (that is, the number
+ they failed to match. By default, this count is exactly the
+ same as the number of lines that would have been output, but
+ if the -M (multiline) option is used (without -v), there may
+ be more suppressed lines than the count (that is, the number
of matches).
- If no lines are selected, the number zero is output. If sev-
- eral files are are being scanned, a count is output for each
- of them and the -t option can be used to cause a total to be
- output at the end. However, if the --files-with-matches
- option is also used, only those files whose counts are
- greater than zero are listed. When -c is used, the -A, -B,
- and -C options are ignored.
+ If no lines are selected, the number zero is output. If sev-
+ eral files are are being scanned, a count is output for each
+ of them and the -t option can be used to cause a total to be
+ output at the end. However, if the --files-with-matches op-
+ tion is also used, only those files whose counts are greater
+ than zero are listed. When -c is used, the -A, -B, and -C op-
+ tions are ignored.
--colour, --color
If this option is given without any data, it is equivalent to
- "--colour=auto". If data is required, it must be given in
+ "--colour=auto". If data is required, it must be given in
the same shell item, separated by an equals sign.
--colour=value, --color=value
This option specifies under what circumstances the parts of a
line that matched a pattern should be coloured in the output.
- By default, the output is not coloured. The value (which is
- optional, see above) may be "never", "always", or "auto". In
- the latter case, colouring happens only if the standard out-
- put is connected to a terminal. More resources are used when
+ By default, the output is not coloured. The value (which is
+ optional, see above) may be "never", "always", or "auto". In
+ the latter case, colouring happens only if the standard out-
+ put is connected to a terminal. More resources are used when
colouring is enabled, because pcre2grep has to search for all
- possible matches in a line, not just one, in order to colour
+ possible matches in a line, not just one, in order to colour
them all.
- The colour that is used can be specified by setting one of
- the environment variables PCRE2GREP_COLOUR, PCRE2GREP_COLOR,
+ The colour that is used can be specified by setting one of
+ the environment variables PCRE2GREP_COLOUR, PCRE2GREP_COLOR,
PCREGREP_COLOUR, or PCREGREP_COLOR, which are checked in that
order. If none of these are set, pcre2grep looks for
- GREP_COLORS or GREP_COLOR (in that order). The value of the
- variable should be a string of two numbers, separated by a
- semicolon, except in the case of GREP_COLORS, which must
+ GREP_COLORS or GREP_COLOR (in that order). The value of the
+ variable should be a string of two numbers, separated by a
+ semicolon, except in the case of GREP_COLORS, which must
start with "ms=" or "mt=" followed by two semicolon-separated
- colours, terminated by the end of the string or by a colon.
- If GREP_COLORS does not start with "ms=" or "mt=" it is
- ignored, and GREP_COLOR is checked.
+ colours, terminated by the end of the string or by a colon.
+ If GREP_COLORS does not start with "ms=" or "mt=" it is ig-
+ nored, and GREP_COLOR is checked.
- If the string obtained from one of the above variables con-
+ If the string obtained from one of the above variables con-
tains any characters other than semicolon or digits, the set-
ting is ignored and the default colour is used. The string is
copied directly into the control string for setting colour on
- a terminal, so it is your responsibility to ensure that the
- values make sense. If no relevant environment variable is
+ a terminal, so it is your responsibility to ensure that the
+ values make sense. If no relevant environment variable is
set, the default is "1;31", which gives red.
-D action, --devices=action
- If an input path is not a regular file or a directory,
- "action" specifies how it is to be processed. Valid values
- are "read" (the default) or "skip" (silently skip the path).
+ If an input path is not a regular file or a directory, "ac-
+ tion" specifies how it is to be processed. Valid values are
+ "read" (the default) or "skip" (silently skip the path).
-d action, --directories=action
If an input path is a directory, "action" specifies how it is
- to be processed. Valid values are "read" (the default in
- non-Windows environments, for compatibility with GNU grep),
- "recurse" (equivalent to the -r option), or "skip" (silently
- skip the path, the default in Windows environments). In the
- "read" case, directories are read as if they were ordinary
- files. In some operating systems the effect of reading a
- directory like this is an immediate end-of-file; in others it
+ to be processed. Valid values are "read" (the default in
+ non-Windows environments, for compatibility with GNU grep),
+ "recurse" (equivalent to the -r option), or "skip" (silently
+ skip the path, the default in Windows environments). In the
+ "read" case, directories are read as if they were ordinary
+ files. In some operating systems the effect of reading a di-
+ rectory like this is an immediate end-of-file; in others it
may provoke an error.
--depth-limit=number
@@ -271,198 +270,198 @@ OPTIONS
-e pattern, --regex=pattern, --regexp=pattern
Specify a pattern to be matched. This option can be used mul-
tiple times in order to specify several patterns. It can also
- be used as a way of specifying a single pattern that starts
- with a hyphen. When -e is used, no argument pattern is taken
- from the command line; all arguments are treated as file
- names. There is no limit to the number of patterns. They are
- applied to each line in the order in which they are defined
+ be used as a way of specifying a single pattern that starts
+ with a hyphen. When -e is used, no argument pattern is taken
+ from the command line; all arguments are treated as file
+ names. There is no limit to the number of patterns. They are
+ applied to each line in the order in which they are defined
until one matches.
- If -f is used with -e, the command line patterns are matched
+ If -f is used with -e, the command line patterns are matched
first, followed by the patterns from the file(s), independent
- of the order in which these options are specified. Note that
- multiple use of -e is not the same as a single pattern with
+ of the order in which these options are specified. Note that
+ multiple use of -e is not the same as a single pattern with
alternatives. For example, X|Y finds the first character in a
- line that is X or Y, whereas if the two patterns are given
+ line that is X or Y, whereas if the two patterns are given
separately, with X first, pcre2grep finds X if it is present,
even if it follows Y in the line. It finds Y only if there is
- no X in the line. This matters only if you are using -o or
+ no X in the line. This matters only if you are using -o or
--colo(u)r to show the part(s) of the line that matched.
--exclude=pattern
Files (but not directories) whose names match the pattern are
- skipped without being processed. This applies to all files,
- whether listed on the command line, obtained from --file-
+ skipped without being processed. This applies to all files,
+ whether listed on the command line, obtained from --file-
list, or by scanning a directory. The pattern is a PCRE2 reg-
- ular expression, and is matched against the final component
- of the file name, not the entire path. The -F, -w, and -x
- options do not apply to this pattern. The option may be given
+ ular expression, and is matched against the final component
+ of the file name, not the entire path. The -F, -w, and -x op-
+ tions do not apply to this pattern. The option may be given
any number of times in order to specify multiple patterns. If
- a file name matches both an --include and an --exclude pat-
+ a file name matches both an --include and an --exclude pat-
tern, it is excluded. There is no short form for this option.
--exclude-from=filename
- Treat each non-empty line of the file as the data for an
+ Treat each non-empty line of the file as the data for an
--exclude option. What constitutes a newline when reading the
- file is the operating system's default. The --newline option
- has no effect on this option. This option may be given more
+ file is the operating system's default. The --newline option
+ has no effect on this option. This option may be given more
than once in order to specify a number of files to read.
--exclude-dir=pattern
Directories whose names match the pattern are skipped without
- being processed, whatever the setting of the --recursive
- option. This applies to all directories, whether listed on
- the command line, obtained from --file-list, or by scanning a
- parent directory. The pattern is a PCRE2 regular expression,
- and is matched against the final component of the directory
- name, not the entire path. The -F, -w, and -x options do not
- apply to this pattern. The option may be given any number of
- times in order to specify more than one pattern. If a direc-
- tory matches both --include-dir and --exclude-dir, it is
- excluded. There is no short form for this option.
+ being processed, whatever the setting of the --recursive op-
+ tion. This applies to all directories, whether listed on the
+ command line, obtained from --file-list, or by scanning a
+ parent directory. The pattern is a PCRE2 regular expression,
+ and is matched against the final component of the directory
+ name, not the entire path. The -F, -w, and -x options do not
+ apply to this pattern. The option may be given any number of
+ times in order to specify more than one pattern. If a direc-
+ tory matches both --include-dir and --exclude-dir, it is ex-
+ cluded. There is no short form for this option.
-F, --fixed-strings
- Interpret each data-matching pattern as a list of fixed
- strings, separated by newlines, instead of as a regular
- expression. What constitutes a newline for this purpose is
- controlled by the --newline option. The -w (match as a word)
- and -x (match whole line) options can be used with -F. They
- apply to each of the fixed strings. A line is selected if any
+ Interpret each data-matching pattern as a list of fixed
+ strings, separated by newlines, instead of as a regular ex-
+ pression. What constitutes a newline for this purpose is con-
+ trolled by the --newline option. The -w (match as a word) and
+ -x (match whole line) options can be used with -F. They ap-
+ ply to each of the fixed strings. A line is selected if any
of the fixed strings are found in it (subject to -w or -x, if
- present). This option applies only to the patterns that are
- matched against the contents of files; it does not apply to
- patterns specified by any of the --include or --exclude
- options.
+ present). This option applies only to the patterns that are
+ matched against the contents of files; it does not apply to
+ patterns specified by any of the --include or --exclude op-
+ tions.
-f filename, --file=filename
- Read patterns from the file, one per line, and match them
- against each line of input. As is the case with patterns on
- the command line, no delimiters should be used. What consti-
- tutes a newline when reading the file is the operating sys-
- tem's default interpretation of \n. The --newline option has
- no effect on this option. Trailing white space is removed
- from each line, and blank lines are ignored. An empty file
- contains no patterns and therefore matches nothing. Patterns
- read from a file in this way may contain binary zeros, which
- are treated as ordinary data characters. See also the com-
- ments about multiple patterns versus a single pattern with
+ Read patterns from the file, one per line, and match them
+ against each line of input. As is the case with patterns on
+ the command line, no delimiters should be used. What consti-
+ tutes a newline when reading the file is the operating sys-
+ tem's default interpretation of \n. The --newline option has
+ no effect on this option. Trailing white space is removed
+ from each line, and blank lines are ignored. An empty file
+ contains no patterns and therefore matches nothing. Patterns
+ read from a file in this way may contain binary zeros, which
+ are treated as ordinary data characters. See also the com-
+ ments about multiple patterns versus a single pattern with
alternatives in the description of -e above.
- If this option is given more than once, all the specified
- files are read. A data line is output if any of the patterns
- match it. A file name can be given as "-" to refer to the
- standard input. When -f is used, patterns specified on the
- command line using -e may also be present; they are tested
- before the file's patterns. However, no other pattern is
+ If this option is given more than once, all the specified
+ files are read. A data line is output if any of the patterns
+ match it. A file name can be given as "-" to refer to the
+ standard input. When -f is used, patterns specified on the
+ command line using -e may also be present; they are tested
+ before the file's patterns. However, no other pattern is
taken from the command line; all arguments are treated as the
names of paths to be searched.
--file-list=filename
- Read a list of files and/or directories that are to be
+ Read a list of files and/or directories that are to be
scanned from the given file, one per line. What constitutes a
- newline when reading the file is the operating system's
- default. Trailing white space is removed from each line, and
+ newline when reading the file is the operating system's de-
+ fault. Trailing white space is removed from each line, and
blank lines are ignored. These paths are processed before any
- that are listed on the command line. The file name can be
- given as "-" to refer to the standard input. If --file and
- --file-list are both specified as "-", patterns are read
- first. This is useful only when the standard input is a ter-
- minal, from which further lines (the list of files) can be
+ that are listed on the command line. The file name can be
+ given as "-" to refer to the standard input. If --file and
+ --file-list are both specified as "-", patterns are read
+ first. This is useful only when the standard input is a ter-
+ minal, from which further lines (the list of files) can be
read after an end-of-file indication. If this option is given
more than once, all the specified files are read.
--file-offsets
- Instead of showing lines or parts of lines that match, show
- each match as an offset from the start of the file and a
- length, separated by a comma. In this mode, no context is
- shown. That is, the -A, -B, and -C options are ignored. If
+ Instead of showing lines or parts of lines that match, show
+ each match as an offset from the start of the file and a
+ length, separated by a comma. In this mode, no context is
+ shown. That is, the -A, -B, and -C options are ignored. If
there is more than one match in a line, each of them is shown
- separately. This option is mutually exclusive with --output,
+ separately. This option is mutually exclusive with --output,
--line-offsets, and --only-matching.
-H, --with-filename
- Force the inclusion of the file name at the start of output
+ Force the inclusion of the file name at the start of output
lines when searching a single file. By default, the file name
is not shown in this case. For matching lines, the file name
is followed by a colon; for context lines, a hyphen separator
- is used. If a line number is also being output, it follows
- the file name. When the -M option causes a pattern to match
- more than one line, only the first is preceded by the file
- name. This option overrides any previous -h, -l, or -L
- options.
+ is used. If a line number is also being output, it follows
+ the file name. When the -M option causes a pattern to match
+ more than one line, only the first is preceded by the file
+ name. This option overrides any previous -h, -l, or -L op-
+ tions.
-h, --no-filename
Suppress the output file names when searching multiple files.
- By default, file names are shown when multiple files are
- searched. For matching lines, the file name is followed by a
- colon; for context lines, a hyphen separator is used. If a
- line number is also being output, it follows the file name.
+ By default, file names are shown when multiple files are
+ searched. For matching lines, the file name is followed by a
+ colon; for context lines, a hyphen separator is used. If a
+ line number is also being output, it follows the file name.
This option overrides any previous -H, -L, or -l options.
--heap-limit=number
See --match-limit below.
- --help Output a help message, giving brief details of the command
- options and file type support, and then exit. Anything else
+ --help Output a help message, giving brief details of the command
+ options and file type support, and then exit. Anything else
on the command line is ignored.
- -I Ignore binary files. This is equivalent to --binary-
+ -I Ignore binary files. This is equivalent to --binary-
files=without-match.
-i, --ignore-case
Ignore upper/lower case distinctions during comparisons.
--include=pattern
- If any --include patterns are specified, the only files that
- are processed are those that match one of the patterns (and
- do not match an --exclude pattern). This option does not
- affect directories, but it applies to all files, whether
- listed on the command line, obtained from --file-list, or by
- scanning a directory. The pattern is a PCRE2 regular expres-
- sion, and is matched against the final component of the file
- name, not the entire path. The -F, -w, and -x options do not
- apply to this pattern. The option may be given any number of
- times. If a file name matches both an --include and an
- --exclude pattern, it is excluded. There is no short form
- for this option.
+ If any --include patterns are specified, the only files that
+ are processed are those that match one of the patterns (and
+ do not match an --exclude pattern). This option does not af-
+ fect directories, but it applies to all files, whether listed
+ on the command line, obtained from --file-list, or by scan-
+ ning a directory. The pattern is a PCRE2 regular expression,
+ and is matched against the final component of the file name,
+ not the entire path. The -F, -w, and -x options do not apply
+ to this pattern. The option may be given any number of times.
+ If a file name matches both an --include and an --exclude
+ pattern, it is excluded. There is no short form for this op-
+ tion.
--include-from=filename
- Treat each non-empty line of the file as the data for an
+ Treat each non-empty line of the file as the data for an
--include option. What constitutes a newline for this purpose
- is the operating system's default. The --newline option has
+ is the operating system's default. The --newline option has
no effect on this option. This option may be given any number
of times; all the files are read.
--include-dir=pattern
- If any --include-dir patterns are specified, the only direc-
- tories that are processed are those that match one of the
- patterns (and do not match an --exclude-dir pattern). This
- applies to all directories, whether listed on the command
- line, obtained from --file-list, or by scanning a parent
- directory. The pattern is a PCRE2 regular expression, and is
- matched against the final component of the directory name,
- not the entire path. The -F, -w, and -x options do not apply
+ If any --include-dir patterns are specified, the only direc-
+ tories that are processed are those that match one of the
+ patterns (and do not match an --exclude-dir pattern). This
+ applies to all directories, whether listed on the command
+ line, obtained from --file-list, or by scanning a parent di-
+ rectory. The pattern is a PCRE2 regular expression, and is
+ matched against the final component of the directory name,
+ not the entire path. The -F, -w, and -x options do not apply
to this pattern. The option may be given any number of times.
- If a directory matches both --include-dir and --exclude-dir,
+ If a directory matches both --include-dir and --exclude-dir,
it is excluded. There is no short form for this option.
-L, --files-without-match
- Instead of outputting lines from the files, just output the
- names of the files that do not contain any lines that would
- have been output. Each file name is output once, on a sepa-
- rate line. This option overrides any previous -H, -h, or -l
+ Instead of outputting lines from the files, just output the
+ names of the files that do not contain any lines that would
+ have been output. Each file name is output once, on a sepa-
+ rate line. This option overrides any previous -H, -h, or -l
options.
-l, --files-with-matches
- Instead of outputting lines from the files, just output the
+ Instead of outputting lines from the files, just output the
names of the files containing lines that would have been out-
- put. Each file name is output once, on a separate line.
- Searching normally stops as soon as a matching line is found
- in a file. However, if the -c (count) option is also used,
- matching continues in order to obtain the correct count, and
- those files that have at least one match are listed along
+ put. Each file name is output once, on a separate line.
+ Searching normally stops as soon as a matching line is found
+ in a file. However, if the -c (count) option is also used,
+ matching continues in order to obtain the correct count, and
+ those files that have at least one match are listed along
with their counts. Using this option with -c is a way of sup-
- pressing the listing of files with no matches. This opeion
+ pressing the listing of files with no matches. This opeion
overrides any previous -H, -h, or -L options.
--label=name
@@ -471,261 +470,277 @@ OPTIONS
input)" is used. There is no short form for this option.
--line-buffered
- When this option is given, non-compressed input is read and
- processed line by line, and the output is flushed after each
- write. By default, input is read in large chunks, unless
- pcre2grep can determine that it is reading from a terminal
- (which is currently possible only in Unix-like environments
- or Windows). Output to terminal is normally automatically
- flushed by the operating system. This option can be useful
+ When this option is given, non-compressed input is read and
+ processed line by line, and the output is flushed after each
+ write. By default, input is read in large chunks, unless
+ pcre2grep can determine that it is reading from a terminal
+ (which is currently possible only in Unix-like environments
+ or Windows). Output to terminal is normally automatically
+ flushed by the operating system. This option can be useful
when the input or output is attached to a pipe and you do not
- want pcre2grep to buffer up large amounts of data. However,
- its use will affect performance, and the -M (multiline)
- option ceases to work. When input is from a compressed .gz or
+ want pcre2grep to buffer up large amounts of data. However,
+ its use will affect performance, and the -M (multiline) op-
+ tion ceases to work. When input is from a compressed .gz or
.bz2 file, --line-buffered is ignored.
--line-offsets
- Instead of showing lines or parts of lines that match, show
+ Instead of showing lines or parts of lines that match, show
each match as a line number, the offset from the start of the
- line, and a length. The line number is terminated by a colon
- (as usual; see the -n option), and the offset and length are
- separated by a comma. In this mode, no context is shown.
- That is, the -A, -B, and -C options are ignored. If there is
- more than one match in a line, each of them is shown sepa-
- rately. This option is mutually exclusive with --output,
+ line, and a length. The line number is terminated by a colon
+ (as usual; see the -n option), and the offset and length are
+ separated by a comma. In this mode, no context is shown.
+ That is, the -A, -B, and -C options are ignored. If there is
+ more than one match in a line, each of them is shown sepa-
+ rately. This option is mutually exclusive with --output,
--file-offsets, and --only-matching.
--locale=locale-name
- This option specifies a locale to be used for pattern match-
- ing. It overrides the value in the LC_ALL or LC_CTYPE envi-
- ronment variables. If no locale is specified, the PCRE2
- library's default (usually the "C" locale) is used. There is
- no short form for this option.
+ This option specifies a locale to be used for pattern match-
+ ing. It overrides the value in the LC_ALL or LC_CTYPE envi-
+ ronment variables. If no locale is specified, the PCRE2 li-
+ brary's default (usually the "C" locale) is used. There is no
+ short form for this option.
--match-limit=number
- Processing some regular expression patterns may take a very
+ Processing some regular expression patterns may take a very
long time to search for all possible matching strings. Others
- may require a very large amount of memory. There are three
+ may require a very large amount of memory. There are three
options that set resource limits for matching.
The --match-limit option provides a means of limiting comput-
- ing resource usage when processing patterns that are not
- going to match, but which have a very large number of possi-
- bilities in their search trees. The classic example is a pat-
- tern that uses nested unlimited repeats. Internally, PCRE2
- has a counter that is incremented each time around its main
- processing loop. If the value set by --match-limit is
- reached, an error occurs.
-
- The --heap-limit option specifies, as a number of kibibytes
- (units of 1024 bytes), the amount of heap memory that may be
+ ing resource usage when processing patterns that are not go-
+ ing to match, but which have a very large number of possibil-
+ ities in their search trees. The classic example is a pattern
+ that uses nested unlimited repeats. Internally, PCRE2 has a
+ counter that is incremented each time around its main pro-
+ cessing loop. If the value set by --match-limit is reached,
+ an error occurs.
+
+ The --heap-limit option specifies, as a number of kibibytes
+ (units of 1024 bytes), the amount of heap memory that may be
used for matching. Heap memory is needed only if matching the
- pattern requires a significant number of nested backtracking
+ pattern requires a significant number of nested backtracking
points to be remembered. This parameter can be set to zero to
forbid the use of heap memory altogether.
- The --depth-limit option limits the depth of nested back-
+ The --depth-limit option limits the depth of nested back-
tracking points, which indirectly limits the amount of memory
that is used. The amount of memory needed for each backtrack-
- ing point depends on the number of capturing parentheses in
+ ing point depends on the number of capturing parentheses in
the pattern, so the amount of memory that is used before this
- limit acts varies from pattern to pattern. This limit is of
+ limit acts varies from pattern to pattern. This limit is of
use only if it is set smaller than --match-limit.
- There are no short forms for these options. The default lim-
- its can be set when the PCRE2 library is compiled; if they
- are not specified, the defaults are very large and so effec-
+ There are no short forms for these options. The default lim-
+ its can be set when the PCRE2 library is compiled; if they
+ are not specified, the defaults are very large and so effec-
tively unlimited.
--max-buffer-size=number
- This limits the expansion of the processing buffer, whose
- initial size can be set by --buffer-size. The maximum buffer
- size is silently forced to be no smaller than the starting
+ This limits the expansion of the processing buffer, whose
+ initial size can be set by --buffer-size. The maximum buffer
+ size is silently forced to be no smaller than the starting
buffer size.
-M, --multiline
- Allow patterns to match more than one line. When this option
+ Allow patterns to match more than one line. When this option
is set, the PCRE2 library is called in "multiline" mode. This
- allows a matched string to extend past the end of a line and
- continue on one or more subsequent lines. Patterns used with
+ allows a matched string to extend past the end of a line and
+ continue on one or more subsequent lines. Patterns used with
-M may usefully contain literal newline characters and inter-
- nal occurrences of ^ and $ characters. The output for a suc-
- cessful match may consist of more than one line. The first
- line is the line in which the match started, and the last
- line is the line in which the match ended. If the matched
- string ends with a newline sequence, the output ends at the
- end of that line. If -v is set, none of the lines in a
- multi-line match are output. Once a match has been handled,
- scanning restarts at the beginning of the line after the one
+ nal occurrences of ^ and $ characters. The output for a suc-
+ cessful match may consist of more than one line. The first
+ line is the line in which the match started, and the last
+ line is the line in which the match ended. If the matched
+ string ends with a newline sequence, the output ends at the
+ end of that line. If -v is set, none of the lines in a
+ multi-line match are output. Once a match has been handled,
+ scanning restarts at the beginning of the line after the one
in which the match ended.
- The newline sequence that separates multiple lines must be
- matched as part of the pattern. For example, to find the
- phrase "regular expression" in a file where "regular" might
- be at the end of a line and "expression" at the start of the
+ The newline sequence that separates multiple lines must be
+ matched as part of the pattern. For example, to find the
+ phrase "regular expression" in a file where "regular" might
+ be at the end of a line and "expression" at the start of the
next line, you could use this command:
pcre2grep -M 'regular\s+expression'
- The \s escape sequence matches any white space character,
- including newlines, and is followed by + so as to match
- trailing white space on the first line as well as possibly
- handling a two-character newline sequence.
+ The \s escape sequence matches any white space character, in-
+ cluding newlines, and is followed by + so as to match trail-
+ ing white space on the first line as well as possibly han-
+ dling a two-character newline sequence.
- There is a limit to the number of lines that can be matched,
- imposed by the way that pcre2grep buffers the input file as
- it scans it. With a sufficiently large processing buffer,
+ There is a limit to the number of lines that can be matched,
+ imposed by the way that pcre2grep buffers the input file as
+ it scans it. With a sufficiently large processing buffer,
this should not be a problem, but the -M option does not work
when input is read line by line (see --line-buffered.)
-N newline-type, --newline=newline-type
- The PCRE2 library supports five different conventions for
- indicating the ends of lines. They are the single-character
- sequences CR (carriage return) and LF (linefeed), the two-
- character sequence CRLF, an "anycrlf" convention, which rec-
- ognizes any of the preceding three types, and an "any" con-
- vention, in which any Unicode line ending sequence is assumed
- to end a line. The Unicode sequences are the three just men-
- tioned, plus VT (vertical tab, U+000B), FF (form feed,
- U+000C), NEL (next line, U+0085), LS (line separator,
+ The PCRE2 library supports five different conventions for in-
+ dicating the ends of lines. They are the single-character se-
+ quences CR (carriage return) and LF (linefeed), the two-char-
+ acter sequence CRLF, an "anycrlf" convention, which recog-
+ nizes any of the preceding three types, and an "any" conven-
+ tion, in which any Unicode line ending sequence is assumed to
+ end a line. The Unicode sequences are the three just men-
+ tioned, plus VT (vertical tab, U+000B), FF (form feed,
+ U+000C), NEL (next line, U+0085), LS (line separator,
U+2028), and PS (paragraph separator, U+2029).
- When the PCRE2 library is built, a default line-ending
- sequence is specified. This is normally the standard
- sequence for the operating system. Unless otherwise specified
- by this option, pcre2grep uses the library's default. The
- possible values for this option are CR, LF, CRLF, ANYCRLF, or
- ANY. This makes it possible to use pcre2grep to scan files
- that have come from other environments without having to mod-
- ify their line endings. If the data that is being scanned
- does not agree with the convention set by this option,
- pcre2grep may behave in strange ways. Note that this option
- does not apply to files specified by the -f, --exclude-from,
- or --include-from options, which are expected to use the
- operating system's standard newline sequence.
+ When the PCRE2 library is built, a default line-ending se-
+ quence is specified. This is normally the standard sequence
+ for the operating system. Unless otherwise specified by this
+ option, pcre2grep uses the library's default. The possible
+ values for this option are CR, LF, CRLF, ANYCRLF, or ANY.
+ This makes it possible to use pcre2grep to scan files that
+ have come from other environments without having to modify
+ their line endings. If the data that is being scanned does
+ not agree with the convention set by this option, pcre2grep
+ may behave in strange ways. Note that this option does not
+ apply to files specified by the -f, --exclude-from, or --in-
+ clude-from options, which are expected to use the operating
+ system's standard newline sequence.
-n, --line-number
Precede each output line by its line number in the file, fol-
- lowed by a colon for matching lines or a hyphen for context
+ lowed by a colon for matching lines or a hyphen for context
lines. If the file name is also being output, it precedes the
- line number. When the -M option causes a pattern to match
- more than one line, only the first is preceded by its line
+ line number. When the -M option causes a pattern to match
+ more than one line, only the first is preceded by its line
number. This option is forced if --line-offsets is used.
- --no-jit If the PCRE2 library is built with support for just-in-time
+ --no-jit If the PCRE2 library is built with support for just-in-time
compiling (which speeds up matching), pcre2grep automatically
makes use of this, unless it was explicitly disabled at build
- time. This option can be used to disable the use of JIT at
- run time. It is provided for testing and working round prob-
+ time. This option can be used to disable the use of JIT at
+ run time. It is provided for testing and working round prob-
lems. It should never be needed in normal use.
-O text, --output=text
- When there is a match, instead of outputting the whole line
- that matched, output just the given text. This option is
- mutually exclusive with --only-matching, --file-offsets, and
+ When there is a match, instead of outputting the whole line
+ that matched, output just the given text. This option is mu-
+ tually exclusive with --only-matching, --file-offsets, and
--line-offsets. Escape sequences starting with a dollar char-
- acter may be used to insert the contents of the matched part
+ acter may be used to insert the contents of the matched part
of the line and/or captured substrings into the text.
- $ or ${} is replaced by the captured sub-
- string of the given decimal number; zero substitutes the
+ $ or ${} is replaced by the captured sub-
+ string of the given decimal number; zero substitutes the
whole match. If the number is greater than the number of cap-
- turing substrings, or if the capture is unset, the replace-
+ turing substrings, or if the capture is unset, the replace-
ment is empty.
- $a is replaced by bell; $b by backspace; $e by escape; $f by
- form feed; $n by newline; $r by carriage return; $t by tab;
+ $a is replaced by bell; $b by backspace; $e by escape; $f by
+ form feed; $n by newline; $r by carriage return; $t by tab;
$v by vertical tab.
- $o is replaced by the character represented by the
+ $o is replaced by the character represented by the
given octal number; up to three digits are processed.
- $x is replaced by the character represented by the
+ $x is replaced by the character represented by the
given hexadecimal number; up to two digits are processed.
- Any other character is substituted by itself. In particular,
+ Any other character is substituted by itself. In particular,
$$ is replaced by a single dollar.
-o, --only-matching
Show only the part of the line that matched a pattern instead
- of the whole line. In this mode, no context is shown. That
- is, the -A, -B, and -C options are ignored. If there is more
- than one match in a line, each of them is shown separately,
- on a separate line of output. If -o is combined with -v
- (invert the sense of the match to find non-matching lines),
- no output is generated, but the return code is set appropri-
- ately. If the matched portion of the line is empty, nothing
- is output unless the file name or line number are being
- printed, in which case they are shown on an otherwise empty
+ of the whole line. In this mode, no context is shown. That
+ is, the -A, -B, and -C options are ignored. If there is more
+ than one match in a line, each of them is shown separately,
+ on a separate line of output. If -o is combined with -v (in-
+ vert the sense of the match to find non-matching lines), no
+ output is generated, but the return code is set appropri-
+ ately. If the matched portion of the line is empty, nothing
+ is output unless the file name or line number are being
+ printed, in which case they are shown on an otherwise empty
line. This option is mutually exclusive with --output,
--file-offsets and --line-offsets.
-onumber, --only-matching=number
- Show only the part of the line that matched the capturing
- parentheses of the given number. Up to 32 capturing parenthe-
- ses are supported, and -o0 is equivalent to -o without a num-
- ber. Because these options can be given without an argument
- (see above), if an argument is present, it must be given in
- the same shell item, for example, -o3 or --only-matching=2.
- The comments given for the non-argument case above also apply
- to this option. If the specified capturing parentheses do not
- exist in the pattern, or were not set in the match, nothing
- is output unless the file name or line number are being out-
- put.
+ Show only the part of the line that matched the capturing
+ parentheses of the given number. Up to 50 capturing parenthe-
+ ses are supported by default. This limit can be changed via
+ the --om-capture option. A pattern may contain any number of
+ capturing parentheses, but only those whose number is within
+ the limit can be accessed by -o. An error occurs if the num-
+ ber specified by -o is greater than the limit.
+
+ -o0 is the same as -o without a number. Because these options
+ can be given without an argument (see above), if an argument
+ is present, it must be given in the same shell item, for ex-
+ ample, -o3 or --only-matching=2. The comments given for the
+ non-argument case above also apply to this option. If the
+ specified capturing parentheses do not exist in the pattern,
+ or were not set in the match, nothing is output unless the
+ file name or line number are being output.
If this option is given multiple times, multiple substrings
are output for each match, in the order the options are
given, and all on one line. For example, -o3 -o1 -o3 causes
the substrings matched by capturing parentheses 3 and 1 and
then 3 again to be output. By default, there is no separator
- (but see the next option).
+ (but see the next but one option).
+
+ --om-capture=number
+ Set the number of capturing parentheses that can be accessed
+ by -o. The default is 50.
--om-separator=text
- Specify a separating string for multiple occurrences of -o.
- The default is an empty string. Separating strings are never
+ Specify a separating string for multiple occurrences of -o.
+ The default is an empty string. Separating strings are never
coloured.
-q, --quiet
Work quietly, that is, display nothing except error messages.
- The exit status indicates whether or not any matches were
+ The exit status indicates whether or not any matches were
found.
-r, --recursive
- If any given path is a directory, recursively scan the files
- it contains, taking note of any --include and --exclude set-
- tings. By default, a directory is read as a normal file; in
- some operating systems this gives an immediate end-of-file.
- This option is a shorthand for setting the -d option to
- "recurse".
+ If any given path is a directory, recursively scan the files
+ it contains, taking note of any --include and --exclude set-
+ tings. By default, a directory is read as a normal file; in
+ some operating systems this gives an immediate end-of-file.
+ This option is a shorthand for setting the -d option to "re-
+ curse".
--recursion-limit=number
See --match-limit above.
-s, --no-messages
- Suppress error messages about non-existent or unreadable
- files. Such files are quietly skipped. However, the return
+ Suppress error messages about non-existent or unreadable
+ files. Such files are quietly skipped. However, the return
code is still 2, even if matches were found in other files.
-t, --total-count
- This option is useful when scanning more than one file. If
- used on its own, -t suppresses all output except for a grand
- total number of matching lines (or non-matching lines if -v
- is used) in all the files. If -t is used with -c, a grand
- total is output except when the previous output is just one
- line. In other words, it is not output when just one file's
- count is listed. If file names are being output, the grand
- total is preceded by "TOTAL:". Otherwise, it appears as just
- another number. The -t option is ignored when used with -L
- (list files without matches), because the grand total would
+ This option is useful when scanning more than one file. If
+ used on its own, -t suppresses all output except for a grand
+ total number of matching lines (or non-matching lines if -v
+ is used) in all the files. If -t is used with -c, a grand to-
+ tal is output except when the previous output is just one
+ line. In other words, it is not output when just one file's
+ count is listed. If file names are being output, the grand
+ total is preceded by "TOTAL:". Otherwise, it appears as just
+ another number. The -t option is ignored when used with -L
+ (list files without matches), because the grand total would
always be zero.
- -u, --utf-8
- Operate in UTF-8 mode. This option is available only if PCRE2
+ -u, --utf Operate in UTF-8 mode. This option is available only if PCRE2
has been compiled with UTF-8 support. All patterns (including
- those for any --exclude and --include options) and all sub-
- ject lines that are scanned must be valid strings of UTF-8
+ those for any --exclude and --include options) and all sub-
+ ject lines that are scanned must be valid strings of UTF-8
characters.
+ -U, --utf-allow-invalid
+ As --utf, but in addition subject lines may contain invalid
+ UTF-8 code unit sequences. These can never form part of any
+ pattern match. This facility allows valid UTF-8 strings to be
+ sought in executable or other binary files. For more details
+ about matching in non-valid UTF-8 strings, see the pcre2uni-
+ code(3) documentation.
+
-V, --version
Write the version numbers of pcre2grep and the PCRE2 library
to the standard output and then exit. Anything else on the
@@ -757,10 +772,10 @@ OPTIONS
ENVIRONMENT VARIABLES
- The environment variables LC_ALL and LC_CTYPE are examined, in that
- order, for a locale. The first one that is set is used. This can be
- overridden by the --locale option. If no locale is set, the PCRE2
- library's default (usually the "C" locale) is used.
+ The environment variables LC_ALL and LC_CTYPE are examined, in that or-
+ der, for a locale. The first one that is set is used. This can be over-
+ ridden by the --locale option. If no locale is set, the PCRE2 library's
+ default (usually the "C" locale) is used.
NEWLINES
@@ -785,9 +800,9 @@ OPTIONS COMPATIBILITY
terminology) is also available as --xxx-regex (PCRE2 terminology). How-
ever, the --depth-limit, --file-list, --file-offsets, --heap-limit,
--include-dir, --line-offsets, --locale, --match-limit, -M, --multi-
- line, -N, --newline, --om-separator, --output, -u, and --utf-8 options
- are specific to pcre2grep, as is the use of the --only-matching option
- with a capturing parentheses number.
+ line, -N, --newline, --om-separator, --output, -u, --utf, -U, and
+ --utf-allow-invalid options are specific to pcre2grep, as is the use of
+ the --only-matching option with a capturing parentheses number.
Although most of the common options work the same way, a few are dif-
ferent in pcre2grep. For example, the --include option's argument is a
@@ -818,13 +833,13 @@ OPTIONS WITH DATA
--file /some/file
Note, however, that if you want to supply a file name beginning with ~
- as data in a shell command, and have the shell expand ~ to a home
- directory, you must separate the file name from the option, because the
+ as data in a shell command, and have the shell expand ~ to a home di-
+ rectory, you must separate the file name from the option, because the
shell does not treat ~ specially unless it is at the start of an item.
The exceptions to the above are the --colour (or --color) and --only-
- matching options, for which the data is optional. If one of these
- options does have data, it must be given in the first form, using an
+ matching options, for which the data is optional. If one of these op-
+ tions does have data, it must be given in the first form, using an
equals character. Otherwise pcre2grep will assume that it has no data.
@@ -832,18 +847,26 @@ USING PCRE2'S CALLOUT FACILITY
pcre2grep has, by default, support for calling external programs or
scripts or echoing specific strings during matching by making use of
- PCRE2's callout facility. However, this support can be disabled when
- pcre2grep is built. You can find out whether your binary has support
- for callouts by running it with the --help option. If the support is
- not enabled, all callouts in patterns are ignored by pcre2grep.
-
- A callout in a PCRE2 pattern is of the form (?C) where the argu-
- ment is either a number or a quoted string (see the pcre2callout docu-
- mentation for details). Numbered callouts are ignored by pcre2grep;
+ PCRE2's callout facility. However, this support can be completely or
+ partially disabled when pcre2grep is built. You can find out whether
+ your binary has support for callouts by running it with the --help op-
+ tion. If callout support is completely disabled, all callouts in pat-
+ terns are ignored by pcre2grep. If the facility is partially disabled,
+ calling external programs is not supported, and callouts that request
+ it are ignored.
+
+ A callout in a PCRE2 pattern is of the form (?C) where the argu-
+ ment is either a number or a quoted string (see the pcre2callout docu-
+ mentation for details). Numbered callouts are ignored by pcre2grep;
only callouts with string arguments are useful.
Calling external programs or scripts
+ This facility can be independently disabled when pcre2grep is built. It
+ is supported for Windows, where a call to _spawnvp() is used, for VMS,
+ where lib$spawn() is used, and for any other Unix-like environment
+ where fork() and execv() are available.
+
If the callout string does not start with a pipe (vertical bar) charac-
ter, it is parsed into a list of substrings separated by pipe charac-
ters. The first substring must be an executable name, with the follow-
@@ -851,16 +874,16 @@ USING PCRE2'S CALLOUT FACILITY
executable_name|arg1|arg2|...
- Any substring (including the executable name) may contain escape
- sequences started by a dollar character: $ or ${} is
- replaced by the captured substring of the given decimal number, which
+ Any substring (including the executable name) may contain escape se-
+ quences started by a dollar character: $ or ${} is re-
+ placed by the captured substring of the given decimal number, which
must be greater than zero. If the number is greater than the number of
capturing substrings, or if the capture is unset, the replacement is
empty.
- Any other character is substituted by itself. In particular, $$ is
- replaced by a single dollar and $| is replaced by a pipe character.
- Here is an example:
+ Any other character is substituted by itself. In particular, $$ is re-
+ placed by a single dollar and $| is replaced by a pipe character. Here
+ is an example:
echo -e "abcde\n12345" | pcre2grep \
'(?x)(.)(..(.))
@@ -873,27 +896,27 @@ USING PCRE2'S CALLOUT FACILITY
Arg1: [1] [234] [4] Arg2: |1| ()
12345
- The parameters for the execv() system call that is used to run the pro-
- gram or script are zero-terminated strings. This means that binary zero
- characters in the callout argument will cause premature termination of
- their substrings, and therefore should not be present. Any syntax
- errors in the string (for example, a dollar not followed by another
- character) cause the callout to be ignored. If running the program
- fails for any reason (including the non-existence of the executable), a
- local matching failure occurs and the matcher backtracks in the normal
- way.
+ The parameters for the system call that is used to run the program or
+ script are zero-terminated strings. This means that binary zero charac-
+ ters in the callout argument will cause premature termination of their
+ substrings, and therefore should not be present. Any syntax errors in
+ the string (for example, a dollar not followed by another character)
+ cause the callout to be ignored. If running the program fails for any
+ reason (including the non-existence of the executable), a local match-
+ ing failure occurs and the matcher backtracks in the normal way.
Echoing a specific string
- If the callout string starts with a pipe (vertical bar) character, the
- rest of the string is written to the output, having been passed through
- the same escape processing as text from the --output option. This pro-
- vides a simple echoing facility that avoids calling an external program
- or script. No terminator is added to the string, so if you want a new-
- line, you must include it explicitly. Matching continues normally
- after the string is output. If you want to see only the callout output
- but not any output from an actual match, you should end the relevant
- pattern with (*FAIL).
+ This facility is always available, provided that callouts were not com-
+ pletely disabled when pcre2grep was built. If the callout string starts
+ with a pipe (vertical bar) character, the rest of the string is written
+ to the output, having been passed through the same escape processing as
+ text from the --output option. This provides a simple echoing facility
+ that avoids calling an external program or script. No terminator is
+ added to the string, so if you want a newline, you must include it ex-
+ plicitly. Matching continues normally after the string is output. If
+ you want to see only the callout output but not any output from an ac-
+ tual match, you should end the relevant pattern with (*FAIL).
MATCHING ERRORS
@@ -901,8 +924,8 @@ MATCHING ERRORS
It is possible to supply a regular expression that takes a very long
time to fail to match certain lines. Such patterns normally involve
nested indefinite repeats, for example: (a+)*\d when matched against a
- line of a's with no final digit. The PCRE2 matching function has a
- resource limit that causes it to abort in these circumstances. If this
+ line of a's with no final digit. The PCRE2 matching function has a re-
+ source limit that causes it to abort in these circumstances. If this
happens, pcre2grep outputs an error message and the line that caused
the problem to the standard error stream. If there are more than 20
such errors, pcre2grep gives up.
@@ -940,5 +963,5 @@ AUTHOR
REVISION
- Last updated: 24 February 2018
- Copyright (c) 1997-2018 University of Cambridge.
+ Last updated: 15 June 2019
+ Copyright (c) 1997-2019 University of Cambridge.
diff --git a/doc/pcre2jit.3 b/doc/pcre2jit.3
index c3b916b..f4be3fb 100644
--- a/doc/pcre2jit.3
+++ b/doc/pcre2jit.3
@@ -1,4 +1,4 @@
-.TH PCRE2JIT 3 "28 June 2018" "PCRE2 10.32"
+.TH PCRE2JIT 3 "23 May 2019" "PCRE2 10.34"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH "PCRE2 JUST-IN-TIME COMPILER SUPPORT"
@@ -120,13 +120,42 @@ support is not available, or the pattern was not processed by
pattern.
.
.
+.SH "MATCHING SUBJECTS CONTAINING INVALID UTF"
+.rs
+.sp
+When a pattern is compiled with the PCRE2_UTF option, subject strings are
+normally expected to be a valid sequence of UTF code units. By default, this is
+checked at the start of matching and an error is generated if invalid UTF is
+detected. The PCRE2_NO_UTF_CHECK option can be passed to \fBpcre2_match()\fP to
+skip the check (for improved performance) if you are sure that a subject string
+is valid. If this option is used with an invalid string, the result is
+undefined.
+.P
+However, a way of running matches on strings that may contain invalid UTF
+sequences is available. Calling \fBpcre2_compile()\fP with the
+PCRE2_MATCH_INVALID_UTF option has two effects: it tells the interpreter in
+\fBpcre2_match()\fP to support invalid UTF, and, if \fBpcre2_jit_compile()\fP
+is called, the compiled JIT code also supports invalid UTF. Details of how this
+support works, in both the JIT and the interpretive cases, is given in the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+documentation.
+.P
+There is also an obsolete option for \fBpcre2_jit_compile()\fP called
+PCRE2_JIT_INVALID_UTF, which currently exists only for backward compatibility.
+It is superseded by the \fBpcre2_compile()\fP option PCRE2_MATCH_INVALID_UTF
+and should no longer be used. It may be removed in future.
+.
+.
.SH "UNSUPPORTED OPTIONS AND PATTERN ITEMS"
.rs
.sp
The \fBpcre2_match()\fP options that are supported for JIT matching are
-PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART,
-PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, and PCRE2_PARTIAL_SOFT. The
-PCRE2_ANCHORED option is not supported at match time.
+PCRE2_COPY_MATCHED_SUBJECT, PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY,
+PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, and
+PCRE2_PARTIAL_SOFT. The PCRE2_ANCHORED and PCRE2_ENDANCHORED options are not
+supported at match time.
.P
If the PCRE2_NO_JIT option is passed to \fBpcre2_match()\fP it disables the
use of JIT, forcing matching by the interpreter code.
@@ -376,10 +405,13 @@ available, and which need the best possible performance, can instead use a
processed by \fBpcre2_jit_compile()\fP).
.P
The fast path function is called \fBpcre2_jit_match()\fP, and it takes exactly
-the same arguments as \fBpcre2_match()\fP. The return values are also the same,
-plus PCRE2_ERROR_JIT_BADOPTION if a matching mode (partial or complete) is
-requested that was not compiled. Unsupported option bits (for example,
-PCRE2_ANCHORED) are ignored, as is the PCRE2_NO_JIT option.
+the same arguments as \fBpcre2_match()\fP. However, the subject string must be
+specified with a length; PCRE2_ZERO_TERMINATED is not supported. Unsupported
+option bits (for example, PCRE2_ANCHORED, PCRE2_ENDANCHORED and
+PCRE2_COPY_MATCHED_SUBJECT) are ignored, as is the PCRE2_NO_JIT option. The
+return values are also the same as for \fBpcre2_match()\fP, plus
+PCRE2_ERROR_JIT_BADOPTION if a matching mode (partial or complete) is requested
+that was not compiled.
.P
When you call \fBpcre2_match()\fP, as well as testing for invalid options, a
number of other sanity checks are performed on the arguments. For example, if
@@ -412,6 +444,6 @@ Cambridge, England.
.rs
.sp
.nf
-Last updated: 28 June 2018
-Copyright (c) 1997-2018 University of Cambridge.
+Last updated: 23 May 2019
+Copyright (c) 1997-2019 University of Cambridge.
.fi
diff --git a/doc/pcre2limits.3 b/doc/pcre2limits.3
index 803e97b..9bf3626 100644
--- a/doc/pcre2limits.3
+++ b/doc/pcre2limits.3
@@ -1,4 +1,4 @@
-.TH PCRE2LIMITS 3 "30 March 2017" "PCRE2 10.30"
+.TH PCRE2LIMITS 3 "03 February 2019" "PCRE2 10.33"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH "SIZE AND OTHER LIMITATIONS"
@@ -34,16 +34,16 @@ All values in repeating quantifiers must be less than 65536.
.P
The maximum length of a lookbehind assertion is 65535 characters.
.P
-There is no limit to the number of parenthesized subpatterns, but there can be
-no more than 65535 capturing subpatterns. There is, however, a limit to the
-depth of nesting of parenthesized subpatterns of all kinds. This is imposed in
-order to limit the amount of system stack used at compile time. The default
-limit can be specified when PCRE2 is built; if not, the default is set to 250.
-An application can change this limit by calling pcre2_set_parens_nest_limit()
-to set the limit in a compile context.
+There is no limit to the number of parenthesized groups, but there can be no
+more than 65535 capture groups, and there is a limit to the depth of nesting of
+parenthesized subpatterns of all kinds. This is imposed in order to limit the
+amount of system stack used at compile time. The default limit can be specified
+when PCRE2 is built; if not, the default is set to 250. An application can
+change this limit by calling pcre2_set_parens_nest_limit() to set the limit in
+a compile context.
.P
-The maximum length of name for a named subpattern is 32 code units, and the
-maximum number of named subpatterns is 10000.
+The maximum length of name for a named capture group is 32 code units, and the
+maximum number of such groups is 10000.
.P
The maximum length of a name in a (*MARK), (*PRUNE), (*SKIP), or (*THEN) verb
is 255 code units for the 8-bit library and 65535 code units for the 16-bit and
@@ -67,6 +67,6 @@ Cambridge, England.
.rs
.sp
.nf
-Last updated: 30 March 2017
-Copyright (c) 1997-2017 University of Cambridge.
+Last updated: 02 February 2019
+Copyright (c) 1997-2019 University of Cambridge.
.fi
diff --git a/doc/pcre2matching.3 b/doc/pcre2matching.3
index 81ce968..7f9bbac 100644
--- a/doc/pcre2matching.3
+++ b/doc/pcre2matching.3
@@ -1,4 +1,4 @@
-.TH PCRE2MATCHING 3 "29 September 2014" "PCRE2 10.00"
+.TH PCRE2MATCHING 3 "23 May 2019" "PCRE2 10.34"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH "PCRE2 MATCHING ALGORITHMS"
@@ -113,7 +113,8 @@ do want multiple matches in such cases, either use an ungreedy repeat
("a\ed+?") or set the PCRE2_NO_AUTO_POSSESS option when compiling.
.P
There are a number of features of PCRE2 regular expressions that are not
-supported by the alternative matching algorithm. They are as follows:
+supported or behave differently in the alternative matching function. Those
+that are not supported cause an error if encountered.
.P
1. Because the algorithm finds all possible matches, the greedy or ungreedy
nature of repetition quantifiers is not relevant (though it may affect
@@ -135,25 +136,30 @@ possibilities, and PCRE2's implementation of this algorithm does not attempt to
do this. This means that no captured substrings are available.
.P
3. Because no substrings are captured, backreferences within the pattern are
-not supported, and cause errors if encountered.
+not supported.
.P
4. For the same reason, conditional expressions that use a backreference as the
condition or test for a specific group recursion are not supported.
.P
-5. Because many paths through the tree may be active, the \eK escape sequence,
+5. Again for the same reason, script runs are not supported.
+.P
+6. Because many paths through the tree may be active, the \eK escape sequence,
which resets the start of the match when encountered (but may be on some paths
-and not on others), is not supported. It causes an error if encountered.
+and not on others), is not supported.
.P
-6. Callouts are supported, but the value of the \fIcapture_top\fP field is
+7. Callouts are supported, but the value of the \fIcapture_top\fP field is
always 1, and the value of the \fIcapture_last\fP field is always 0.
.P
-7. The \eC escape sequence, which (in the standard algorithm) always matches a
+8. The \eC escape sequence, which (in the standard algorithm) always matches a
single code unit, even in a UTF mode, is not supported in these modes, because
the alternative algorithm moves through the subject string one character (not
code unit) at a time, for all active paths through the tree.
.P
-8. Except for (*FAIL), the backtracking control verbs such as (*PRUNE) are not
+9. Except for (*FAIL), the backtracking control verbs such as (*PRUNE) are not
supported. (*FAIL) is supported, and behaves like a failing negative assertion.
+.P
+10. The PCRE2_MATCH_INVALID_UTF option for \fBpcre2_compile()\fP is not
+supported by \fBpcre2_dfa_match()\fP.
.
.
.SH "ADVANTAGES OF THE ALTERNATIVE ALGORITHM"
@@ -188,7 +194,8 @@ The alternative algorithm suffers from a number of disadvantages:
because it has to search for all possible matches, but is also because it is
less susceptible to optimization.
.P
-2. Capturing parentheses and backreferences are not supported.
+2. Capturing parentheses, backreferences, script runs, and matching within
+invalid UTF string are not supported.
.P
3. Although atomic groups are supported, their use does not provide the
performance advantage that it does for the standard algorithm.
@@ -208,6 +215,6 @@ Cambridge, England.
.rs
.sp
.nf
-Last updated: 29 September 2014
-Copyright (c) 1997-2014 University of Cambridge.
+Last updated: 23 May 2019
+Copyright (c) 1997-2019 University of Cambridge.
.fi
diff --git a/doc/pcre2partial.3 b/doc/pcre2partial.3
index 72a12ed..3ff939f 100644
--- a/doc/pcre2partial.3
+++ b/doc/pcre2partial.3
@@ -1,67 +1,107 @@
-.TH PCRE2PARTIAL 3 "22 December 2014" "PCRE2 10.00"
+.TH PCRE2PARTIAL 3 "04 September 2019" "PCRE2 10.34"
.SH NAME
PCRE2 - Perl-compatible regular expressions
.SH "PARTIAL MATCHING IN PCRE2"
.rs
.sp
-In normal use of PCRE2, if the subject string that is passed to a matching
-function matches as far as it goes, but is too short to match the entire
-pattern, PCRE2_ERROR_NOMATCH is returned. There are circumstances where it
-might be helpful to distinguish this case from other cases in which there is no
-match.
+In normal use of PCRE2, if there is a match up to the end of a subject string,
+but more characters are needed to match the entire pattern, PCRE2_ERROR_NOMATCH
+is returned, just like any other failing match. There are circumstances where
+it might be helpful to distinguish this "partial match" case.
.P
-Consider, for example, an application where a human is required to type in data
-for a field with specific formatting requirements. An example might be a date
-in the form \fIddmmmyy\fP, defined by this pattern:
-.sp
- ^\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed$
-.sp
-If the application sees the user's keystrokes one by one, and can check that
-what has been typed so far is potentially valid, it is able to raise an error
-as soon as a mistake is made, by beeping and not reflecting the character that
-has been typed, for example. This immediate feedback is likely to be a better
-user interface than a check that is delayed until the entire string has been
-entered. Partial matching can also be useful when the subject string is very
-long and is not all available at once.
+One example is an application where the subject string is very long, and not
+all available at once. The requirement here is to be able to do the matching
+segment by segment, but special action is needed when a matched substring spans
+the boundary between two segments.
.P
-PCRE2 supports partial matching by means of the PCRE2_PARTIAL_SOFT and
-PCRE2_PARTIAL_HARD options, which can be set when calling a matching function.
-The difference between the two options is whether or not a partial match is
-preferred to an alternative complete match, though the details differ between
-the two types of matching function. If both options are set, PCRE2_PARTIAL_HARD
-takes precedence.
+Another example is checking a user input string as it is typed, to ensure that
+it conforms to a required format. Invalid characters can be immediately
+diagnosed and rejected, giving instant feedback.
.P
-If you want to use partial matching with just-in-time optimized code, you must
-call \fBpcre2_jit_compile()\fP with one or both of these options:
+Partial matching is a PCRE2-specific feature; it is not Perl-compatible. It is
+requested by setting one of the PCRE2_PARTIAL_HARD or PCRE2_PARTIAL_SOFT
+options when calling a matching function. The difference between the two
+options is whether or not a partial match is preferred to an alternative
+complete match, though the details differ between the two types of matching
+function. If both options are set, PCRE2_PARTIAL_HARD takes precedence.
+.P
+If you want to use partial matching with just-in-time optimized code, as well
+as setting a partial match option for the matching function, you must also call
+\fBpcre2_jit_compile()\fP with one or both of these options:
.sp
- PCRE2_JIT_PARTIAL_SOFT
PCRE2_JIT_PARTIAL_HARD
+ PCRE2_JIT_PARTIAL_SOFT
.sp
PCRE2_JIT_COMPLETE should also be set if you are going to run non-partial
-matches on the same pattern. If the appropriate JIT mode has not been compiled,
-interpretive matching code is used.
+matches on the same pattern. Separate code is compiled for each mode. If the
+appropriate JIT mode has not been compiled, interpretive matching code is used.
.P
Setting a partial matching option disables two of PCRE2's standard
-optimizations. PCRE2 remembers the last literal code unit in a pattern, and
-abandons matching immediately if it is not present in the subject string. This
-optimization cannot be used for a subject string that might match only
-partially. PCRE2 also knows the minimum length of a matching string, and does
+optimization hints. PCRE2 remembers the last literal code unit in a pattern,
+and abandons matching immediately if it is not present in the subject string.
+This optimization cannot be used for a subject string that might match only
+partially. PCRE2 also remembers a minimum length of a matching string, and does
not bother to run the matching function on shorter strings. This optimization
is also disabled for partial matching.
.
.
+.SH "REQUIREMENTS FOR A PARTIAL MATCH"
+.rs
+.sp
+A possible partial match occurs during matching when the end of the subject
+string is reached successfully, but either more characters are needed to
+complete the match, or the addition of more characters might change what is
+matched.
+.P
+Example 1: if the pattern is /abc/ and the subject is "ab", more characters are
+definitely needed to complete a match. In this case both hard and soft matching
+options yield a partial match.
+.P
+Example 2: if the pattern is /ab+/ and the subject is "ab", a complete match
+can be found, but the addition of more characters might change what is
+matched. In this case, only PCRE2_PARTIAL_HARD returns a partial match;
+PCRE2_PARTIAL_SOFT returns the complete match.
+.P
+On reaching the end of the subject, when PCRE2_PARTIAL_HARD is set, if the next
+pattern item is \ez, \eZ, \eb, \eB, or $ there is always a partial match.
+Otherwise, for both options, the next pattern item must be one that inspects a
+character, and at least one of the following must be true:
+.P
+(1) At least one character has already been inspected. An inspected character
+need not form part of the final matched string; lookbehind assertions and the
+\eK escape sequence provide ways of inspecting characters before the start of a
+matched string.
+.P
+(2) The pattern contains one or more lookbehind assertions. This condition
+exists in case there is a lookbehind that inspects characters before the start
+of the match.
+.P
+(3) There is a special case when the whole pattern can match an empty string.
+When the starting point is at the end of the subject, the empty string match is
+a possibility, and if PCRE2_PARTIAL_SOFT is set and neither of the above
+conditions is true, it is returned. However, because adding more characters
+might result in a non-empty match, PCRE2_PARTIAL_HARD returns a partial match,
+which in this case means "there is going to be a match at this point, but until
+some more characters are added, we do not know if it will be an empty string or
+something longer".
+.
+.
+.
.SH "PARTIAL MATCHING USING pcre2_match()"
.rs
.sp
-A partial match occurs during a call to \fBpcre2_match()\fP when the end of the
-subject string is reached successfully, but matching cannot continue because
-more characters are needed. However, at least one character in the subject must
-have been inspected. This character need not form part of the final matched
-string; lookbehind assertions and the \eK escape sequence provide ways of
-inspecting characters before the start of a matched string. The requirement for
-inspecting at least one character exists because an empty string can always be
-matched; without such a restriction there would always be a partial match of an
-empty string at the end of the subject.
+When a partial matching option is set, the result of calling
+\fBpcre2_match()\fP can be one of the following:
+.TP 2
+\fBA successful match\fP
+A complete match has been found, starting and ending within this subject.
+.TP
+\fBPCRE2_ERROR_NOMATCH\fP
+No match can start anywhere in this subject.
+.TP
+\fBPCRE2_ERROR_PARTIAL\fP
+Adding more characters may result in a complete match that uses one or more
+characters from the end of this subject.
.P
When a partial match is returned, the first two elements in the ovector point
to the portion of the subject that was matched, but the values in the rest of
@@ -77,53 +117,40 @@ is "456abc12", a partial match is found for the string "abc12", because all
these characters are needed for a subsequent re-match with additional
characters.
.P
-What happens when a partial match is identified depends on which of the two
-partial matching options are set.
-.
-.
-.SS "PCRE2_PARTIAL_SOFT WITH pcre2_match()"
-.rs
-.sp
-If PCRE2_PARTIAL_SOFT is set when \fBpcre2_match()\fP identifies a partial
-match, the partial match is remembered, but matching continues as normal, and
-other alternatives in the pattern are tried. If no complete match can be found,
-PCRE2_ERROR_PARTIAL is returned instead of PCRE2_ERROR_NOMATCH.
-.P
-This option is "soft" because it prefers a complete match over a partial match.
-All the various matching items in a pattern behave as if the subject string is
-potentially complete. For example, \ez, \eZ, and $ match at the end of the
-subject, as normal, and for \eb and \eB the end of the subject is treated as a
-non-alphanumeric.
-.P
If there is more than one partial match, the first one that was found provides
the data that is returned. Consider this pattern:
.sp
/123\ew+X|dogY/
.sp
-If this is matched against the subject string "abc123dog", both
-alternatives fail to match, but the end of the subject is reached during
-matching, so PCRE2_ERROR_PARTIAL is returned. The offsets are set to 3 and 9,
-identifying "123dog" as the first partial match that was found. (In this
-example, there are two partial matches, because "dog" on its own partially
-matches the second alternative.)
+If this is matched against the subject string "abc123dog", both alternatives
+fail to match, but the end of the subject is reached during matching, so
+PCRE2_ERROR_PARTIAL is returned. The offsets are set to 3 and 9, identifying
+"123dog" as the first partial match. (In this example, there are two partial
+matches, because "dog" on its own partially matches the second alternative.)
.
.
-.SS "PCRE2_PARTIAL_HARD WITH pcre2_match()"
-.rs
-.sp
-If PCRE2_PARTIAL_HARD is set for \fBpcre2_match()\fP, PCRE2_ERROR_PARTIAL is
-returned as soon as a partial match is found, without continuing to search for
-possible complete matches. This option is "hard" because it prefers an earlier
-partial match over a later complete match. For this reason, the assumption is
-made that the end of the supplied subject string may not be the true end of the
-available data, and so, if \ez, \eZ, \eb, \eB, or $ are encountered at the end
-of the subject, the result is PCRE2_ERROR_PARTIAL, provided that at least one
-character in the subject has been inspected.
-.
-.
-.SS "Comparing hard and soft partial matching"
+.SS "How a partial match is processed by pcre2_match()"
.rs
.sp
+What happens when a partial match is identified depends on which of the two
+partial matching options is set.
+.P
+If PCRE2_PARTIAL_HARD is set, PCRE2_ERROR_PARTIAL is returned as soon as a
+partial match is found, without continuing to search for possible complete
+matches. This option is "hard" because it prefers an earlier partial match over
+a later complete match. For this reason, the assumption is made that the end of
+the supplied subject string is not the true end of the available data, which is
+why \ez, \eZ, \eb, \eB, and $ always give a partial match.
+.P
+If PCRE2_PARTIAL_SOFT is set, the partial match is remembered, but matching
+continues as normal, and other alternatives in the pattern are tried. If no
+complete match can be found, PCRE2_ERROR_PARTIAL is returned instead of
+PCRE2_ERROR_NOMATCH. This option is "soft" because it prefers a complete match
+over a partial match. All the various matching items in a pattern behave as if
+the subject string is potentially complete; \ez, \eZ, and $ match at the end of
+the subject, as normal, and for \eb and \eB the end of the subject is treated
+as a non-alphanumeric.
+.P
The difference between the two partial matching options can be illustrated by a
pattern such as:
.sp
@@ -148,89 +175,151 @@ The second pattern will never match "dogsbody", because it will always find the
shorter match first.
.
.
-.SH "PARTIAL MATCHING USING pcre2_dfa_match()"
+.SS "Example of partial matching using pcre2test"
.rs
.sp
-The DFA functions move along the subject string character by character, without
-backtracking, searching for all possible matches simultaneously. If the end of
-the subject is reached before the end of the pattern, there is the possibility
-of a partial match, again provided that at least one character has been
-inspected.
-.P
-When PCRE2_PARTIAL_SOFT is set, PCRE2_ERROR_PARTIAL is returned only if there
-have been no complete matches. Otherwise, the complete matches are returned.
-However, if PCRE2_PARTIAL_HARD is set, a partial match takes precedence over
-any complete matches. The portion of the string that was matched when the
-longest partial match was found is set as the first matching string.
-.P
-Because the DFA functions always search for all possible matches, and there is
-no difference between greedy and ungreedy repetition, their behaviour is
-different from the standard functions when PCRE2_PARTIAL_HARD is set. Consider
-the string "dog" matched against the ungreedy pattern shown above:
+The \fBpcre2test\fP data modifiers \fBpartial_hard\fP (or \fBph\fP) and
+\fBpartial_soft\fP (or \fBps\fP) set PCRE2_PARTIAL_HARD and PCRE2_PARTIAL_SOFT,
+respectively, when calling \fBpcre2_match()\fP. Here is a run of
+\fBpcre2test\fP using a pattern that matches the whole subject in the form of a
+date:
.sp
- /dog(sbody)??/
+ re> /^\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed$/
+ data> 25dec3\e=ph
+ Partial match: 23dec3
+ data> 3ju\e=ph
+ Partial match: 3ju
+ data> 3juj\e=ph
+ No match
.sp
-Whereas the standard function stops as soon as it finds the complete match for
-"dog", the DFA function also finds the partial match for "dogsbody", and so
-returns that when PCRE2_PARTIAL_HARD is set.
+This example gives the same results for both hard and soft partial matching
+options. Here is an example where there is a difference:
+.sp
+ re> /^\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed$/
+ data> 25jun04\e=ps
+ 0: 25jun04
+ 1: jun
+ data> 25jun04\e=ph
+ Partial match: 25jun04
+.sp
+With PCRE2_PARTIAL_SOFT, the subject is matched completely. For
+PCRE2_PARTIAL_HARD, however, the subject is assumed not to be complete, so
+there is only a partial match.
+.
.
.
-.SH "PARTIAL MATCHING AND WORD BOUNDARIES"
+.SH "MULTI-SEGMENT MATCHING WITH pcre2_match()"
.rs
.sp
-If a pattern ends with one of sequences \eb or \eB, which test for word
-boundaries, partial matching with PCRE2_PARTIAL_SOFT can give counter-intuitive
-results. Consider this pattern:
+PCRE was not originally designed with multi-segment matching in mind. However,
+over time, features (including partial matching) that make multi-segment
+matching possible have been added. A very long string can be searched segment
+by segment by calling \fBpcre2_match()\fP repeatedly, with the aim of achieving
+the same results that would happen if the entire string was available for
+searching all the time. Normally, the strings that are being sought are much
+shorter than each individual segment, and are in the middle of very long
+strings, so the pattern is normally not anchored.
+.P
+Special logic must be implemented to handle a matched substring that spans a
+segment boundary. PCRE2_PARTIAL_HARD should be used, because it returns a
+partial match at the end of a segment whenever there is the possibility of
+changing the match by adding more characters. The PCRE2_NOTBOL option should
+also be set for all but the first segment.
+.P
+When a partial match occurs, the next segment must be added to the current
+subject and the match re-run, using the \fIstartoffset\fP argument of
+\fBpcre2_match()\fP to begin at the point where the partial match started.
+For example:
.sp
- /\ebcat\eb/
+ re> /\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed/
+ data> ...the date is 23ja\e=ph
+ Partial match: 23ja
+ data> ...the date is 23jan19 and on that day...\e=offset=15
+ 0: 23jan19
+ 1: jan
+.sp
+Note the use of the \fBoffset\fP modifier to start the new match where the
+partial match was found. In this example, the next segment was added to the one
+in which the partial match was found. This is the most straightforward
+approach, typically using a memory buffer that is twice the size of each
+segment. After a partial match, the first half of the buffer is discarded, the
+second half is moved to the start of the buffer, and a new segment is added
+before repeating the match as in the example above. After a no match, the
+entire buffer can be discarded.
+.P
+If there are memory constraints, you may want to discard text that precedes a
+partial match before adding the next segment. Unfortunately, this is not at
+present straightforward. In cases such as the above, where the pattern does not
+contain any lookbehinds, it is sufficient to retain only the partially matched
+substring. However, if the pattern contains a lookbehind assertion, characters
+that precede the start of the partial match may have been inspected during the
+matching process. When \fBpcre2test\fP displays a partial match, it indicates
+these characters with '<' if the \fBallusedtext\fP modifier is set:
.sp
-This matches "cat", provided there is a word boundary at either end. If the
-subject string is "the cat", the comparison of the final "t" with a following
-character cannot take place, so a partial match is found. However, normal
-matching carries on, and \eb matches at the end of the subject when the last
-character is a letter, so a complete match is found. The result, therefore, is
-\fInot\fP PCRE2_ERROR_PARTIAL. Using PCRE2_PARTIAL_HARD in this case does yield
-PCRE2_ERROR_PARTIAL, because then the partial match takes precedence.
+ re> "(?<=123)abc"
+ data> xx123ab\e=ph,allusedtext
+ Partial match: 123ab
+ <<<
+.sp
+However, the \fPallusedtext\fP modifier is not available for JIT matching,
+because JIT matching does not record the first (or last) consulted characters.
+For this reason, this information is not available via the API. It is therefore
+not possible in general to obtain the exact number of characters that must be
+retained in order to get the right match result. If you cannot retain the
+entire segment, you must find some heuristic way of choosing.
+.P
+If you know the approximate length of the matching substrings, you can use that
+to decide how much text to retain. The only lookbehind information that is
+currently available via the API is the length of the longest individual
+lookbehind in a pattern, but this can be misleading if there are nested
+lookbehinds. The value returned by calling \fBpcre2_pattern_info()\fP with the
+PCRE2_INFO_MAXLOOKBEHIND option is the maximum number of characters (not code
+units) that any individual lookbehind moves back when it is processed. A
+pattern such as "(?<=(? /^\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed$/
- data> 25jun04\e=ps
- 0: 25jun04
- 1: jun
- data> 25dec3\e=ps
- Partial match: 23dec3
- data> 3ju\e=ps
- Partial match: 3ju
- data> 3juj\e=ps
- No match
- data> j\e=ps
- No match
+ /dog(sbody)??/
.sp
-The first data string is matched completely, so \fBpcre2test\fP shows the
-matched substrings. The remaining four strings do not match the complete
-pattern, but the first two are partial matches. Similar output is obtained
-if DFA matching is used.
-.P
-If the \fBpartial_hard\fP (or \fBph\fP) modifier is present on a
-\fBpcre2test\fP data line, the PCRE2_PARTIAL_HARD option is set for the match.
+Whereas the standard function stops as soon as it finds the complete match for
+"dog", the DFA function also finds the partial match for "dogsbody", and so
+returns that when PCRE2_PARTIAL_HARD is set.
.
.
.SH "MULTI-SEGMENT MATCHING WITH pcre2_dfa_match()"
.rs
.sp
-When a partial match has been found using a DFA matching function, it is
+When a partial match has been found using the DFA matching function, it is
possible to continue the match by providing additional subject data and calling
the function again with the same compiled regular expression, this time setting
the PCRE2_DFA_RESTART option. You must pass the same working space as before,
-because this is where details of the previous partial match are stored. Here is
-an example using \fBpcre2test\fP:
+because this is where details of the previous partial match are stored. You can
+set the PCRE2_PARTIAL_SOFT or PCRE2_PARTIAL_HARD options with PCRE2_DFA_RESTART
+to continue partial matching over multiple segments. Here is an example using
+\fBpcre2test\fP:
.sp
re> /^\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed$/
data> 23ja\e=dfa,ps
@@ -242,147 +331,10 @@ The first call has "23ja" as the subject, and requests partial matching; the
second call has "n05" as the subject for the continued (restarted) match.
Notice that when the match is complete, only the last part is shown; PCRE2 does
not retain the previously partially-matched string. It is up to the calling
-program to do that if it needs to.
-.P
-That means that, for an unanchored pattern, if a continued match fails, it is
-not possible to try again at a new starting point. All this facility is capable
-of doing is continuing with the previous match attempt. In the previous
-example, if the second set of data is "ug23" the result is no match, even
-though there would be a match for "aug23" if the entire string were given at
-once. Depending on the application, this may or may not be what you want.
-The only way to allow for starting again at the next character is to retain the
-matched part of the subject and try a new complete match.
-.P
-You can set the PCRE2_PARTIAL_SOFT or PCRE2_PARTIAL_HARD options with
-PCRE2_DFA_RESTART to continue partial matching over multiple segments. This
-facility can be used to pass very long subject strings to the DFA matching
-functions.
-.
-.
-.SH "MULTI-SEGMENT MATCHING WITH pcre2_match()"
-.rs
-.sp
-Unlike the DFA function, it is not possible to restart the previous match with
-a new segment of data when using \fBpcre2_match()\fP. Instead, new data must be
-added to the previous subject string, and the entire match re-run, starting
-from the point where the partial match occurred. Earlier data can be discarded.
-.P
-It is best to use PCRE2_PARTIAL_HARD in this situation, because it does not
-treat the end of a segment as the end of the subject when matching \ez, \eZ,
-\eb, \eB, and $. Consider an unanchored pattern that matches dates:
-.sp
- re> /\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed/
- data> The date is 23ja\e=ph
- Partial match: 23ja
-.sp
-At this stage, an application could discard the text preceding "23ja", add on
-text from the next segment, and call the matching function again. Unlike the
-DFA matching function, the entire matching string must always be available,
-and the complete matching process occurs for each call, so more memory and more
-processing time is needed.
-.
-.
-.SH "ISSUES WITH MULTI-SEGMENT MATCHING"
-.rs
-.sp
-Certain types of pattern may give problems with multi-segment matching,
-whichever matching function is used.
-.P
-1. If the pattern contains a test for the beginning of a line, you need to pass
-the PCRE2_NOTBOL option when the subject string for any call does start at the
-beginning of a line. There is also a PCRE2_NOTEOL option, but in practice when
-doing multi-segment matching you should be using PCRE2_PARTIAL_HARD, which
-includes the effect of PCRE2_NOTEOL.
-.P
-2. If a pattern contains a lookbehind assertion, characters that precede the
-start of the partial match may have been inspected during the matching process.
-When using \fBpcre2_match()\fP, sufficient characters must be retained for the
-next match attempt. You can ensure that enough characters are retained by doing
-the following:
-.P
-Before doing any matching, find the length of the longest lookbehind in the
-pattern by calling \fBpcre2_pattern_info()\fP with the PCRE2_INFO_MAXLOOKBEHIND
-option. Note that the resulting count is in characters, not code units. After a
-partial match, moving back from the ovector[0] offset in the subject by the
-number of characters given for the maximum lookbehind gets you to the earliest
-character that must be retained. In a non-UTF or a 32-bit situation, moving
-back is just a subtraction, but in UTF-8 or UTF-16 you have to count characters
-while moving back through the code units.
-.P
-Characters before the point you have now reached can be discarded, and after
-the next segment has been added to what is retained, you should run the next
-match with the \fBstartoffset\fP argument set so that the match begins at the
-same point as before.
-.P
-For example, if the pattern "(?<=123)abc" is partially matched against the
-string "xx123ab", the ovector offsets are 5 and 7 ("ab"). The maximum
-lookbehind count is 3, so all characters before offset 2 can be discarded. The
-value of \fBstartoffset\fP for the next match should be 3. When \fBpcre2test\fP
-displays a partial match, it indicates the lookbehind characters with '<'
-characters:
-.sp
- re> "(?<=123)abc"
- data> xx123ab\e=ph
- Partial match: 123ab
- <<<
-.P
-3. Because a partial match must always contain at least one character, what
-might be considered a partial match of an empty string actually gives a "no
-match" result. For example:
-.sp
- re> /c(?<=abc)x/
- data> ab\e=ps
- No match
-.sp
-If the next segment begins "cx", a match should be found, but this will only
-happen if characters from the previous segment are retained. For this reason, a
-"no match" result should be interpreted as "partial match of an empty string"
-when the pattern contains lookbehinds.
-.P
-4. Matching a subject string that is split into multiple segments may not
-always produce exactly the same result as matching over one single long string,
-especially when PCRE2_PARTIAL_SOFT is used. The section "Partial Matching and
-Word Boundaries" above describes an issue that arises if the pattern ends with
-\eb or \eB. Another kind of difference may occur when there are multiple
-matching possibilities, because (for PCRE2_PARTIAL_SOFT) a partial match result
-is given only when there are no completed matches. This means that as soon as
-the shortest match has been found, continuation to a new subject segment is no
-longer possible. Consider this \fBpcre2test\fP example:
-.sp
- re> /dog(sbody)?/
- data> dogsb\e=ps
- 0: dog
- data> do\e=ps,dfa
- Partial match: do
- data> gsb\e=ps,dfa,dfa_restart
- 0: g
- data> dogsbody\e=dfa
- 0: dogsbody
- 1: dog
-.sp
-The first data line passes the string "dogsb" to a standard matching function,
-setting the PCRE2_PARTIAL_SOFT option. Although the string is a partial match
-for "dogsbody", the result is not PCRE2_ERROR_PARTIAL, because the shorter
-string "dog" is a complete match. Similarly, when the subject is presented to
-a DFA matching function in several parts ("do" and "gsb" being the first two)
-the match stops when "dog" has been found, and it is not possible to continue.
-On the other hand, if "dogsbody" is presented as a single string, a DFA
-matching function finds both matches.
-.P
-Because of these problems, it is best to use PCRE2_PARTIAL_HARD when matching
-multi-segment data. The example above then behaves differently:
-.sp
- re> /dog(sbody)?/
- data> dogsb\e=ph
- Partial match: dogsb
- data> do\e=ps,dfa
- Partial match: do
- data> gsb\e=ph,dfa,dfa_restart
- Partial match: gsb
-.sp
-5. Patterns that contain alternatives at the top level which do not all start
-with the same pattern item may not work as expected when PCRE2_DFA_RESTART is
-used. For example, consider this pattern:
+program to do that if it needs to. This means that, for an unanchored pattern,
+if a continued match fails, it is not possible to try again at a new starting
+point. All this facility is capable of doing is continuing with the previous
+match attempt. For example, consider this pattern:
.sp
1234|3789
.sp
@@ -391,28 +343,15 @@ alternative is found at offset 3. There is no partial match for the second
alternative, because such a match does not start at the same point in the
subject string. Attempting to continue with the string "7890" does not yield a
match because only those alternatives that match at one point in the subject
-are remembered. The problem arises because the start of the second alternative
-matches within the first alternative. There is no problem with anchored
-patterns or patterns such as:
-.sp
- 1234|ABCD
-.sp
-where no string can be a partial match for both alternatives. This is not a
-problem if a standard matching function is used, because the entire match has
-to be rerun each time:
-.sp
- re> /1234|3789/
- data> ABC123\e=ph
- Partial match: 123
- data> 1237890
- 0: 3789
-.sp
-Of course, instead of using PCRE2_DFA_RESTART, the same technique of re-running
-the entire match can also be used with the DFA matching function. Another
-possibility is to work with two buffers. If a partial match at offset \fIn\fP
-in the first buffer is followed by "no match" when PCRE2_DFA_RESTART is used on
-the second buffer, you can then try a new match starting at offset \fIn+1\fP in
-the first buffer.
+are remembered. Depending on the application, this may or may not be what you
+want.
+.P
+If you do want to allow for starting again at the next character, one way of
+doing it is to retain some or all of the segment and try a new complete match,
+as described for \fBpcre2_match()\fP above. Another possibility is to work with
+two buffers. If a partial match at offset \fIn\fP in the first buffer is
+followed by "no match" when PCRE2_DFA_RESTART is used on the second buffer, you
+can then try a new match starting at offset \fIn+1\fP in the first buffer.
.
.
.SH AUTHOR
@@ -429,6 +368,6 @@ Cambridge, England.
.rs
.sp
.nf
-Last updated: 22 December 2014
-Copyright (c) 1997-2014 University of Cambridge.
+Last updated: 04 September 2019
+Copyright (c) 1997-2019 University of Cambridge.
.fi
diff --git a/doc/pcre2pattern.3 b/doc/pcre2pattern.3
index 0247c52..d5228f3 100644
--- a/doc/pcre2pattern.3
+++ b/doc/pcre2pattern.3
@@ -1,4 +1,4 @@
-.TH PCRE2PATTERN 3 "04 September 2018" "PCRE2 10.32"
+.TH PCRE2PATTERN 3 "29 July 2019" "PCRE2 10.34"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH "PCRE2 REGULAR EXPRESSION DETAILS"
@@ -20,13 +20,13 @@ copious examples. Jeffrey Friedl's "Mastering Regular Expressions", published
by O'Reilly, covers regular expressions in great detail. This description of
PCRE2's regular expressions is intended as reference material.
.P
-This document discusses the patterns that are supported by PCRE2 when its main
-matching function, \fBpcre2_match()\fP, is used. PCRE2 also has an alternative
-matching function, \fBpcre2_dfa_match()\fP, which matches using a different
-algorithm that is not Perl-compatible. Some of the features discussed below are
-not available when DFA matching is used. The advantages and disadvantages of
-the alternative function, and how it differs from the normal function, are
-discussed in the
+This document discusses the regular expression patterns that are supported by
+PCRE2 when its main matching function, \fBpcre2_match()\fP, is used. PCRE2 also
+has an alternative matching function, \fBpcre2_dfa_match()\fP, which matches
+using a different algorithm that is not Perl-compatible. Some of the features
+discussed below are not available when DFA matching is used. The advantages and
+disadvantages of the alternative function, and how it differs from the normal
+function, are discussed in the
.\" HREF
\fBpcre2matching\fP
.\"
@@ -52,10 +52,11 @@ single code units, or as multiple UTF-8 or UTF-16 code units. UTF-32 can be
specified for the 32-bit library, in which case it constrains the character
values to valid Unicode code points. To process UTF strings, PCRE2 must be
built to include Unicode support (which is the default). When using UTF strings
-you must either call the compiling function with the PCRE2_UTF option, or the
-pattern must start with the special sequence (*UTF), which is equivalent to
-setting the relevant option. How setting a UTF mode affects pattern matching is
-mentioned in several places below. There is also a summary of features in the
+you must either call the compiling function with one or both of the PCRE2_UTF
+or PCRE2_MATCH_INVALID_UTF options, or the pattern must start with the special
+sequence (*UTF), which is equivalent to setting the relevant PCRE2_UTF. How
+setting a UTF mode affects pattern matching is mentioned in several places
+below. There is also a summary of features in the
.\" HREF
\fBpcre2unicode\fP
.\"
@@ -149,8 +150,8 @@ this indirectly restricts the amount of heap memory that is used, but there is
also an explicit memory limit that can be set.
.P
These facilities are provided to catch runaway matches that are provoked by
-patterns with huge matching trees (a typical example is a pattern with nested
-unlimited repeats applied to a long string that does not match). When one of
+patterns with huge matching trees. A common example is a pattern with nested
+unlimited repeats applied to a long string that does not match. When one of
these limits is reached, \fBpcre2_match()\fP gives an error return. The limits
can also be set by items at the start of the pattern of the form
.sp
@@ -264,10 +265,10 @@ matches a portion of a subject string that is identical to itself. When
caseless matching is specified (the PCRE2_CASELESS option), letters are matched
independently of case.
.P
-The power of regular expressions comes from the ability to include alternatives
-and repetitions in the pattern. These are encoded in the pattern by the use of
-\fImetacharacters\fP, which do not stand for themselves but instead are
-interpreted in some special way.
+The power of regular expressions comes from the ability to include wild cards,
+character classes, alternatives, and repetitions in the pattern. These are
+encoded in the pattern by the use of \fImetacharacters\fP, which do not stand
+for themselves but instead are interpreted in some special way.
.P
There are two different sets of metacharacters: those that are recognized
anywhere in the pattern except within square brackets, and those that are
@@ -280,14 +281,11 @@ are as follows:
. match any character except newline (by default)
[ start character class definition
| start of alternative branch
- ( start subpattern
- ) end subpattern
- ? extends the meaning of (
- also 0 or 1 quantifier
- also quantifier minimizer
+ ( start group or control verb
+ ) end group or control verb
* 0 or more quantifier
- + 1 or more quantifier
- also "possessive quantifier"
+ + 1 or more quantifier; also "possessive quantifier"
+ ? 0 or 1 quantifier; also quantifier minimizer
{ start min/max quantifier
.sp
Part of a pattern that is in square brackets is called a "character class". In
@@ -296,9 +294,7 @@ a character class the only metacharacters are:
\e general escape character
^ negate the class, but only if the first character
- indicates character range
-.\" JOIN
- [ POSIX character class (only if followed by POSIX
- syntax)
+ [ POSIX character class (if followed by POSIX syntax)
] terminates the character class
.sp
The following sections describe the use of each of the metacharacters.
@@ -308,7 +304,7 @@ The following sections describe the use of each of the metacharacters.
.rs
.sp
The backslash character has several uses. Firstly, if it is followed by a
-character that is not a number or a letter, it takes away any special meaning
+character that is not a digit or a letter, it takes away any special meaning
that character may have. This use of backslash as an escape character applies
both inside and outside character classes.
.P
@@ -318,7 +314,7 @@ would otherwise be interpreted as a metacharacter, so it is always safe to
precede a non-alphanumeric with backslash to specify that it stands for itself.
In particular, if you want to match a backslash, you write \e\e.
.P
-In a UTF mode, only ASCII numbers and letters have any special meaning after a
+In a UTF mode, only ASCII digits and letters have any special meaning after a
backslash. All other characters (in particular, those whose code points are
greater than 127) are treated as literals.
.P
@@ -328,13 +324,13 @@ outside a character class and the next newline, inclusive, are ignored. An
escaping backslash can be used to include a white space or # character as part
of the pattern.
.P
-If you want to remove the special meaning from a sequence of characters, you
-can do so by putting them between \eQ and \eE. This is different from Perl in
-that $ and @ are handled as literals in \eQ...\eE sequences in PCRE2, whereas
-in Perl, $ and @ cause variable interpolation. Also, Perl does "double-quotish
-backslash interpolation" on any backslashes between \eQ and \eE which, its
-documentation says, "may lead to confusing results". PCRE2 treats a backslash
-between \eQ and \eE just like any other character. Note the following examples:
+If you want to treat all characters in a sequence as literals, you can do so by
+putting them between \eQ and \eE. This is different from Perl in that $ and @
+are handled as literals in \eQ...\eE sequences in PCRE2, whereas in Perl, $ and
+@ cause variable interpolation. Also, Perl does "double-quotish backslash
+interpolation" on any backslashes between \eQ and \eE which, its documentation
+says, "may lead to confusing results". PCRE2 treats a backslash between \eQ and
+\eE just like any other character. Note the following examples:
.sp
Pattern PCRE2 matches Perl matches
.sp
@@ -362,15 +358,15 @@ A second use of backslash provides a way of encoding non-printing characters
in patterns in a visible manner. There is no restriction on the appearance of
non-printing characters in a pattern, but when a pattern is being prepared by
text editing, it is often easier to use one of the following escape sequences
-than the binary character it represents. In an ASCII or Unicode environment,
-these escapes are as follows:
+instead of the binary character it represents. In an ASCII or Unicode
+environment, these escapes are as follows:
.sp
\ea alarm, that is, the BEL character (hex 07)
\ecx "control-x", where x is any printable ASCII character
\ee escape (hex 1B)
\ef form feed (hex 0C)
\en linefeed (hex 0A)
- \er carriage return (hex 0D)
+ \er carriage return (hex 0D) (but see below)
\et tab (hex 09)
\e0dd character with octal code 0dd
\eddd character with octal code ddd, or backreference
@@ -378,13 +374,41 @@ these escapes are as follows:
\exhh character with hex code hh
\ex{hhh..} character with hex code hhh..
\eN{U+hhh..} character with Unicode hex code point hhh..
- \euhhhh character with hex code hhhh (when PCRE2_ALT_BSUX is set)
.sp
-The \eN{U+hhh..} escape sequence is recognized only when the PCRE2_UTF option
-is set, that is, when PCRE2 is operating in a Unicode mode. Perl also uses
-\eN{name} to specify characters by Unicode name; PCRE2 does not support this.
-Note that when \eN is not followed by an opening brace (curly bracket) it has
-an entirely different meaning, matching any character that is not a newline.
+By default, after \ex that is not followed by {, from zero to two hexadecimal
+digits are read (letters can be in upper or lower case). Any number of
+hexadecimal digits may appear between \ex{ and }. If a character other than a
+hexadecimal digit appears between \ex{ and }, or if there is no terminating },
+an error occurs.
+.P
+Characters whose code points are less than 256 can be defined by either of the
+two syntaxes for \ex or by an octal sequence. There is no difference in the way
+they are handled. For example, \exdc is exactly the same as \ex{dc} or \e334.
+However, using the braced versions does make such sequences easier to read.
+.P
+Support is available for some ECMAScript (aka JavaScript) escape sequences via
+two compile-time options. If PCRE2_ALT_BSUX is set, the sequence \ex followed
+by { is not recognized. Only if \ex is followed by two hexadecimal digits is it
+recognized as a character escape. Otherwise it is interpreted as a literal "x"
+character. In this mode, support for code points greater than 256 is provided
+by \eu, which must be followed by four hexadecimal digits; otherwise it is
+interpreted as a literal "u" character.
+.P
+PCRE2_EXTRA_ALT_BSUX has the same effect as PCRE2_ALT_BSUX and, in addition,
+\eu{hhh..} is recognized as the character specified by hexadecimal code point.
+There may be any number of hexadecimal digits. This syntax is from ECMAScript
+6.
+.P
+The \eN{U+hhh..} escape sequence is recognized only when PCRE2 is operating in
+UTF mode. Perl also uses \eN{name} to specify characters by Unicode name; PCRE2
+does not support this. Note that when \eN is not followed by an opening brace
+(curly bracket) it has an entirely different meaning, matching any character
+that is not a newline.
+.P
+There are some legacy applications where the escape sequence \er is expected to
+match a newline. If the PCRE2_EXTRA_ESCAPED_CR_IS_LF option is set, \er in a
+pattern is converted to \en so that it matches a LF (linefeed) instead of a CR
+(carriage return) character.
.P
The precise effect of \ecx on ASCII characters is as follows: if x is a lower
case letter, it is converted to upper case. Then bit 6 of the character (hex
@@ -436,17 +460,17 @@ and Perl has changed over time, causing PCRE2 also to change.
.P
Outside a character class, PCRE2 reads the digit and any following digits as a
decimal number. If the number is less than 10, begins with the digit 8 or 9, or
-if there are at least that many previous capturing left parentheses in the
-expression, the entire sequence is taken as a \fIbackreference\fP. A
-description of how this works is given
+if there are at least that many previous capture groups in the expression, the
+entire sequence is taken as a \fIbackreference\fP. A description of how this
+works is given
.\" HTML
.\"
later,
.\"
following the discussion of
-.\" HTML
+.\" HTML
.\"
-parenthesized subpatterns.
+parenthesized groups.
.\"
Otherwise, up to three octal digits are read to form a character code.
.P
@@ -458,7 +482,7 @@ for themselves. For example, outside a character class:
\e040 is another way of writing an ASCII space
.\" JOIN
\e40 is the same, provided there are fewer than 40
- previous capturing subpatterns
+ previous capture groups
\e7 is always a backreference
.\" JOIN
\e11 might be a backreference, or another way of
@@ -477,23 +501,6 @@ for themselves. For example, outside a character class:
Note that octal values of 100 or greater that are specified using this syntax
must not be introduced by a leading zero, because no more than three octal
digits are ever read.
-.P
-By default, after \ex that is not followed by {, from zero to two hexadecimal
-digits are read (letters can be in upper or lower case). Any number of
-hexadecimal digits may appear between \ex{ and }. If a character other than
-a hexadecimal digit appears between \ex{ and }, or if there is no terminating
-}, an error occurs.
-.P
-If the PCRE2_ALT_BSUX option is set, the interpretation of \ex is as just
-described only when it is followed by two hexadecimal digits. Otherwise, it
-matches a literal "x" character. In this mode, support for code points greater
-than 256 is provided by \eu, which must be followed by four hexadecimal digits;
-otherwise it matches a literal "u" character.
-.P
-Characters whose value is less than 256 can be defined by either of the two
-syntaxes for \ex (or by \eu in PCRE2_ALT_BSUX mode). There is no difference in
-the way they are handled. For example, \exdc is exactly the same as \ex{dc} (or
-\eu00dc in PCRE2_ALT_BSUX mode).
.
.
.SS "Constraints on character values"
@@ -532,9 +539,10 @@ character class, these sequences have different meanings.
.sp
In Perl, the sequences \eF, \el, \eL, \eu, and \eU are recognized by its string
handler and used to modify the case of following characters. By default, PCRE2
-does not support these escape sequences. However, if the PCRE2_ALT_BSUX option
-is set, \eU matches a "U" character, and \eu can be used to define a character
-by code point, as described above.
+does not support these escape sequences in patterns. However, if either of the
+PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX options is set, \eU matches a "U"
+character, and \eu can be used to define a character by code point, as
+described above.
.
.
.SS "Absolute and relative backreferences"
@@ -548,9 +556,9 @@ can be coded as \eg{name}. Backreferences are discussed
later,
.\"
following the discussion of
-.\" HTML
+.\" HTML
.\"
-parenthesized subpatterns.
+parenthesized groups.
.\"
.
.
@@ -559,14 +567,14 @@ parenthesized subpatterns.
.sp
For compatibility with Oniguruma, the non-Perl syntax \eg followed by a name or
a number enclosed either in angle brackets or single quotes, is an alternative
-syntax for referencing a subpattern as a "subroutine". Details are discussed
+syntax for referencing a capture group as a subroutine. Details are discussed
.\" HTML
.\"
later.
.\"
Note that \eg{...} (Perl syntax) and \eg<...> (Oniguruma syntax) are \fInot\fP
synonymous. The former is a backreference; the latter is a
-.\" HTML
+.\" HTML
.\"
subroutine
.\"
@@ -746,21 +754,22 @@ an error.
.rs
.sp
When PCRE2 is built with Unicode support (the default), three additional escape
-sequences that match characters with specific properties are available. In
-8-bit non-UTF-8 mode, these sequences are of course limited to testing
-characters whose code points are less than 256, but they do work in this mode.
-In 32-bit non-UTF mode, code points greater than 0x10ffff (the Unicode limit)
-may be encountered. These are all treated as being in the Common script and
-with an unassigned type. The extra escape sequences are:
+sequences that match characters with specific properties are available. They
+can be used in any mode, though in 8-bit and 16-bit non-UTF modes these
+sequences are of course limited to testing characters whose code points are
+less than U+0100 and U+10000, respectively. In 32-bit non-UTF mode, code points
+greater than 0x10ffff (the Unicode limit) may be encountered. These are all
+treated as being in the Unknown script and with an unassigned type. The extra
+escape sequences are:
.sp
\ep{\fIxx\fP} a character with the \fIxx\fP property
\eP{\fIxx\fP} a character without the \fIxx\fP property
\eX a Unicode extended grapheme cluster
.sp
-The property names represented by \fIxx\fP above are limited to the Unicode
-script names, the general category properties, "Any", which matches any
-character (including newline), and some special PCRE2 properties (described
-in the
+The property names represented by \fIxx\fP above are case-sensitive. There is
+support for Unicode script names, Unicode general category properties, "Any",
+which matches any character (including newline), and some special PCRE2
+properties (described in the
.\" HTML
.\"
next section).
@@ -776,8 +785,10 @@ example:
\ep{Greek}
\eP{Han}
.sp
-Those that are not part of an identified script are lumped together as
-"Common". The current list of scripts is:
+Unassigned characters (and in non-UTF 32-bit mode, characters with code points
+greater than 0x10FFFF) are assigned the "Unknown" script. Others that are not
+part of an identified script are lumped together as "Common". The current list
+of scripts is:
.P
Adlam,
Ahom,
@@ -813,6 +824,7 @@ Dogra,
Duployan,
Egyptian_Hieroglyphs,
Elbasan,
+Elymaic,
Ethiopic,
Georgian,
Glagolitic,
@@ -870,10 +882,12 @@ Mro,
Multani,
Myanmar,
Nabataean,
+Nandinagari,
New_Tai_Lue,
Newa,
Nko,
Nushu,
+Nyakeng_Puachue_Hmong,
Ogham,
Ol_Chiki,
Old_Hungarian,
@@ -923,7 +937,9 @@ Tibetan,
Tifinagh,
Tirhuta,
Ugaritic,
+Unknown,
Vai,
+Wancho,
Warang_Citi,
Yi,
Zanabazar_Square.
@@ -991,14 +1007,16 @@ The special property L& is also supported: it matches a character that has
the Lu, Ll, or Lt property, in other words, a letter that is not classified as
a modifier or "other".
.P
-The Cs (Surrogate) property applies only to characters in the range U+D800 to
-U+DFFF. Such characters are not valid in Unicode strings and so
-cannot be tested by PCRE2, unless UTF validity checking has been turned off
-(see the discussion of PCRE2_NO_UTF_CHECK in the
+The Cs (Surrogate) property applies only to characters whose code points are in
+the range U+D800 to U+DFFF. These characters are no different to any other
+character when PCRE2 is not in UTF mode (using the 16-bit or 32-bit library).
+However, they are not valid in Unicode strings and so cannot be tested by PCRE2
+in UTF mode, unless UTF validity checking has been turned off (see the
+discussion of PCRE2_NO_UTF_CHECK in the
.\" HREF
\fBpcre2api\fP
.\"
-page). Perl does not support the Cs property.
+page).
.P
The long synonyms for property names that Perl supports (such as \ep{Letter})
are not supported by PCRE2, nor is it permitted to prefix any of these
@@ -1122,7 +1140,7 @@ a lookbehind assertion
However, in this case, the part of the subject before the real match does not
have to be of fixed length, as lookbehind assertions do. The use of \eK does
not interfere with the setting of
-.\" HTML
+.\" HTML
.\"
captured substrings.
.\"
@@ -1153,7 +1171,7 @@ start of the reported match is earlier than where the match started.
The final use of backslash is for certain simple assertions. An assertion
specifies a condition that has to be met at a particular point in a match,
without consuming any characters from the subject string. The use of
-subpatterns for more complicated assertions is described
+groups for more complicated assertions is described
.\" HTML
.\"
below.
@@ -1175,12 +1193,12 @@ character. If any other of these assertions appears in a character class, an
A word boundary is a position in the subject string where the current character
and the previous character do not both match \ew or \eW (i.e. one matches
\ew and the other matches \eW), or the start or end of the string if the
-first or last character matches \ew, respectively. In a UTF mode, the meanings
-of \ew and \eW can be changed by setting the PCRE2_UCP option. When this is
-done, it also affects \eb and \eB. Neither PCRE2 nor Perl has a separate "start
-of word" or "end of word" metasequence. However, whatever follows \eb normally
-determines which it is. For example, the fragment \eba matches "a" at the start
-of a word.
+first or last character matches \ew, respectively. When PCRE2 is built with
+Unicode support, the meanings of \ew and \eW can be changed by setting the
+PCRE2_UCP option. When this is done, it also affects \eb and \eB. Neither PCRE2
+nor Perl has a separate "start of word" or "end of word" metasequence. However,
+whatever follows \eb normally determines which it is. For example, the fragment
+\eba matches "a" at the start of a word.
.P
The \eA, \eZ, and \ez assertions differ from the traditional circumflex and
dollar (described in the next section) in that they only ever match at the very
@@ -1339,7 +1357,7 @@ with \eC in UTF-8 or UTF-16 mode means that the rest of the string may start
with a malformed UTF character. This has undefined results, because PCRE2
assumes that it is matching character by character in a valid UTF string (by
default it checks the subject string's validity at the start of processing
-unless the PCRE2_NO_UTF_CHECK option is used).
+unless the PCRE2_NO_UTF_CHECK or PCRE2_MATCH_INVALID_UTF option is used).
.P
An application can lock out the use of \eC by setting the
PCRE2_NEVER_BACKSLASH_C option when compiling a pattern. It is also possible to
@@ -1372,9 +1390,9 @@ could be used with a UTF-8 string (ignore white space and line breaks):
.sp
In this example, a group that starts with (?| resets the capturing parentheses
numbers in each alternative (see
-.\" HTML
+.\" HTML
.\"
-"Duplicate Subpattern Numbers"
+"Duplicate Group Numbers"
.\"
below). The assertions at the start of each branch check the next UTF-8
character for values whose encoding uses 1, 2, 3, or 4 bytes, respectively. The
@@ -1616,13 +1634,13 @@ the pattern
matches either "gilbert" or "sullivan". Any number of alternatives may appear,
and an empty alternative is permitted (matching the empty string). The matching
process tries each alternative in turn, from left to right, and the first one
-that succeeds is used. If the alternatives are within a subpattern
-.\" HTML
+that succeeds is used. If the alternatives are within a group
+.\" HTML
.\"
(defined below),
.\"
"succeeds" means matching the rest of the main pattern as well as the
-alternative in the subpattern.
+alternative in the group.
.
.
.SH "INTERNAL OPTION SETTING"
@@ -1665,16 +1683,16 @@ the same way as the Perl-compatible options by using the characters J and U
respectively. However, these are not unset by (?^).
.P
When one of these option changes occurs at top level (that is, not inside
-subpattern parentheses), the change applies to the remainder of the pattern
-that follows. An option change within a subpattern (see below for a description
-of subpatterns) affects only that part of the subpattern that follows it, so
+group parentheses), the change applies to the remainder of the pattern
+that follows. An option change within a group (see below for a description
+of groups) affects only that part of the group that follows it, so
.sp
(a(?i)b)c
.sp
matches abc and aBc and no other strings (assuming PCRE2_CASELESS is not used).
By this means, options can be made to have different settings in different
parts of the pattern. Any changes made in one alternative do carry on
-into subsequent branches within the same subpattern. For example,
+into subsequent branches within the same group. For example,
.sp
(a(?i)b|c)
.sp
@@ -1684,7 +1702,7 @@ option settings happen at compile time. There would be some very weird
behaviour otherwise.
.P
As a convenient shorthand, if any option settings are required at the start of
-a non-capturing subpattern (see the next section), the option letters may
+a non-capturing group (see the next section), the option letters may
appear between the "?" and the ":". Thus the two patterns
.sp
(?i:saturday|sunday)
@@ -1692,10 +1710,11 @@ appear between the "?" and the ":". Thus the two patterns
.sp
match exactly the same set of strings.
.P
-\fBNote:\fP There are other PCRE2-specific options that can be set by the
-application when the compiling function is called. The pattern can contain
-special leading sequences such as (*CRLF) to override what the application has
-set or what has been defaulted. Details are given in the section entitled
+\fBNote:\fP There are other PCRE2-specific options, applying to the whole
+pattern, which can be set by the application when the compiling function is
+called. In addition, the pattern can contain special leading sequences such as
+(*CRLF) to override what the application has set or what has been defaulted.
+Details are given in the section entitled
.\" HTML
.\"
"Newline sequences"
@@ -1707,12 +1726,12 @@ the PCRE2_NEVER_UTF and PCRE2_NEVER_UCP options, which lock out the use of the
(*UTF) and (*UCP) sequences.
.
.
-.\" HTML
-.SH SUBPATTERNS
+.\" HTML
+.SH GROUPS
.rs
.sp
-Subpatterns are delimited by parentheses (round brackets), which can be nested.
-Turning part of a pattern into a subpattern does two things:
+Groups are delimited by parentheses (round brackets), which can be nested.
+Turning part of a pattern into a group does two things:
.sp
1. It localizes a set of alternatives. For example, the pattern
.sp
@@ -1721,15 +1740,15 @@ Turning part of a pattern into a subpattern does two things:
matches "cataract", "caterpillar", or "cat". Without the parentheses, it would
match "cataract", "erpillar" or an empty string.
.sp
-2. It sets up the subpattern as a capturing subpattern. This means that, when
-the whole pattern matches, the portion of the subject string that matched the
-subpattern is passed back to the caller, separately from the portion that
-matched the whole pattern. (This applies only to the traditional matching
-function; the DFA matching function does not support capturing.)
+2. It creates a "capture group". This means that, when the whole pattern
+matches, the portion of the subject string that matched the group is passed
+back to the caller, separately from the portion that matched the whole pattern.
+(This applies only to the traditional matching function; the DFA matching
+function does not support capturing.)
.P
Opening parentheses are counted from left to right (starting from 1) to obtain
-numbers for the capturing subpatterns. For example, if the string "the red
-king" is matched against the pattern
+numbers for capture groups. For example, if the string "the red king" is
+matched against the pattern
.sp
the ((red|white) (king|queen))
.sp
@@ -1737,38 +1756,37 @@ the captured substrings are "red king", "red", and "king", and are numbered 1,
2, and 3, respectively.
.P
The fact that plain parentheses fulfil two functions is not always helpful.
-There are often times when a grouping subpattern is required without a
-capturing requirement. If an opening parenthesis is followed by a question mark
-and a colon, the subpattern does not do any capturing, and is not counted when
-computing the number of any subsequent capturing subpatterns. For example, if
-the string "the white queen" is matched against the pattern
+There are often times when grouping is required without capturing. If an
+opening parenthesis is followed by a question mark and a colon, the group
+does not do any capturing, and is not counted when computing the number of any
+subsequent capture groups. For example, if the string "the white queen"
+is matched against the pattern
.sp
the ((?:red|white) (king|queen))
.sp
the captured substrings are "white queen" and "queen", and are numbered 1 and
-2. The maximum number of capturing subpatterns is 65535.
+2. The maximum number of capture groups is 65535.
.P
As a convenient shorthand, if any option settings are required at the start of
-a non-capturing subpattern, the option letters may appear between the "?" and
-the ":". Thus the two patterns
+a non-capturing group, the option letters may appear between the "?" and the
+":". Thus the two patterns
.sp
(?i:saturday|sunday)
(?:(?i)saturday|sunday)
.sp
match exactly the same set of strings. Because alternative branches are tried
-from left to right, and options are not reset until the end of the subpattern
-is reached, an option setting in one branch does affect subsequent branches, so
+from left to right, and options are not reset until the end of the group is
+reached, an option setting in one branch does affect subsequent branches, so
the above patterns match "SUNDAY" as well as "Saturday".
.
.
-.\" HTML
-.SH "DUPLICATE SUBPATTERN NUMBERS"
+.\" HTML
+.SH "DUPLICATE GROUP NUMBERS"
.rs
.sp
-Perl 5.10 introduced a feature whereby each alternative in a subpattern uses
-the same numbers for its capturing parentheses. Such a subpattern starts with
-(?| and is itself a non-capturing subpattern. For example, consider this
-pattern:
+Perl 5.10 introduced a feature whereby each alternative in a group uses the
+same numbers for its capturing parentheses. Such a group starts with (?| and is
+itself a non-capturing group. For example, consider this pattern:
.sp
(?|(Sat)ur|(Sun))day
.sp
@@ -1778,7 +1796,7 @@ at captured substring number one, whichever alternative matched. This construct
is useful when you want to capture part, but not all, of one of a number of
alternatives. Inside a (?| group, parentheses are numbered as usual, but the
number is reset at the start of each branch. The numbers of any capturing
-parentheses that follow the subpattern start after the highest number used in
+parentheses that follow the whole group start after the highest number used in
any branch. The following example is taken from the Perl documentation. The
numbers underneath show in which buffer the captured content will be stored.
.sp
@@ -1786,13 +1804,12 @@ numbers underneath show in which buffer the captured content will be stored.
/ ( a ) (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x
# 1 2 2 3 2 3 4
.sp
-A backreference to a numbered subpattern uses the most recent value that is
-set for that number by any subpattern. The following pattern matches "abcabc"
-or "defdef":
+A backreference to a capture group uses the most recent value that is set for
+the group. The following pattern matches "abcabc" or "defdef":
.sp
/(?|(abc)|(def))\e1/
.sp
-In contrast, a subroutine call to a numbered subpattern always refers to the
+In contrast, a subroutine call to a capture group always refers to the
first one in the pattern with the given number. The following pattern matches
"abcabc" or "defabc":
.sp
@@ -1806,29 +1823,35 @@ If a
.\"
condition test
.\"
-for a subpattern's having matched refers to a non-unique number, the test is
-true if any of the subpatterns of that number have matched.
+for a group's having matched refers to a non-unique number, the test is
+true if any group with that number has matched.
.P
An alternative approach to using this "branch reset" feature is to use
-duplicate named subpatterns, as described in the next section.
+duplicate named groups, as described in the next section.
.
.
-.SH "NAMED SUBPATTERNS"
+.SH "NAMED CAPTURE GROUPS"
.rs
.sp
-Identifying capturing parentheses by number is simple, but it can be very hard
-to keep track of the numbers in complicated patterns. Furthermore, if an
-expression is modified, the numbers may change. To help with this difficulty,
-PCRE2 supports the naming of capturing subpatterns. This feature was not added
-to Perl until release 5.10. Python had the feature earlier, and PCRE1
-introduced it at release 4.0, using the Python syntax. PCRE2 supports both the
-Perl and the Python syntax.
+Identifying capture groups by number is simple, but it can be very hard to keep
+track of the numbers in complicated patterns. Furthermore, if an expression is
+modified, the numbers may change. To help with this difficulty, PCRE2 supports
+the naming of capture groups. This feature was not added to Perl until release
+5.10. Python had the feature earlier, and PCRE1 introduced it at release 4.0,
+using the Python syntax. PCRE2 supports both the Perl and the Python syntax.
.P
-In PCRE2, a capturing subpattern can be named in one of three ways:
-(?...) or (?'name'...) as in Perl, or (?P...) as in Python. Names
-consist of up to 32 alphanumeric characters and underscores, but must start
-with a non-digit. References to capturing parentheses from other parts of the
-pattern, such as
+In PCRE2, a capture group can be named in one of three ways: (?...) or
+(?'name'...) as in Perl, or (?P...) as in Python. Names may be up to 32
+code units long. When PCRE2_UTF is not set, they may contain only ASCII
+alphanumeric characters and underscores, but must start with a non-digit. When
+PCRE2_UTF is set, the syntax of group names is extended to allow any Unicode
+letter or Unicode decimal digit. In other words, group names must match one of
+these patterns:
+.sp
+ ^[_A-Za-z][_A-Za-z0-9]*\ez when PCRE2_UTF is not set
+ ^[_\ep{L}][_\ep{L}\ep{Nd}]*\ez when PCRE2_UTF is set
+.sp
+References to capture groups from other parts of the pattern, such as
.\" HTML
.\"
backreferences,
@@ -1844,17 +1867,17 @@ conditions,
.\"
can all be made by name as well as by number.
.P
-Named capturing parentheses are allocated numbers as well as names, exactly as
-if the names were not present. In both PCRE2 and Perl, capturing subpatterns
+Named capture groups are allocated numbers as well as names, exactly as
+if the names were not present. In both PCRE2 and Perl, capture groups
are primarily identified by numbers; any names are just aliases for these
numbers. The PCRE2 API provides function calls for extracting the complete
name-to-number translation table from a compiled pattern, as well as
convenience functions for extracting captured substrings by name.
.P
-\fBWarning:\fP When more than one subpattern has the same number, as described
-in the previous section, a name given to one of them applies to all of them.
-Perl allows identically numbered subpatterns to have different names. Consider
-this pattern, where there are two capturing subpatterns, both numbered 1:
+\fBWarning:\fP When more than one capture group has the same number, as
+described in the previous section, a name given to one of them applies to all
+of them. Perl allows identically numbered groups to have different names.
+Consider this pattern, where there are two capture groups, both numbered 1:
.sp
(?|(?aa)|(?bb))
.sp
@@ -1868,20 +1891,20 @@ pattern:
.sp
(?|(?aa)|(bb))
.sp
-Although the second subpattern number 1 is not explicitly named, the name AA is
-still an alias for subpattern 1. Whether the pattern matches "aa" or "bb", a
+Although the second group number 1 is not explicitly named, the name AA is
+still an alias for any group 1. Whether the pattern matches "aa" or "bb", a
reference by name to group AA yields the matched string.
.P
By default, a name must be unique within a pattern, except that duplicate names
-are permitted for subpatterns with the same number, for example:
+are permitted for groups with the same number, for example:
.sp
(?|(?aa)|(?bb))
.sp
The duplicate name constraint can be disabled by setting the PCRE2_DUPNAMES
option at compile time, or by the use of (?J) within the pattern. Duplicate
-names can be useful for patterns where only one instance of the named
-parentheses can match. Suppose you want to match the name of a weekday, either
-as a 3-letter abbreviation or as the full name, and in both cases you want to
+names can be useful for patterns where only one instance of the named capture
+group can match. Suppose you want to match the name of a weekday, either as a
+3-letter abbreviation or as the full name, and in both cases you want to
extract the abbreviation. This pattern (ignoring the line breaks) does the job:
.sp
(?Mon|Fri|Sun)(?:day)?|
@@ -1890,23 +1913,23 @@ extract the abbreviation. This pattern (ignoring the line breaks) does the job:
(?Thu)(?:rsday)?|
(?Sat)(?:urday)?
.sp
-There are five capturing substrings, but only one is ever set after a match.
-The convenience functions for extracting the data by name returns the substring
-for the first (and in this example, the only) subpattern of that name that
-matched. This saves searching to find which numbered subpattern it was. (An
-alternative way of solving this problem is to use a "branch reset" subpattern,
-as described in the previous section.)
+There are five capture groups, but only one is ever set after a match. The
+convenience functions for extracting the data by name returns the substring for
+the first (and in this example, the only) group of that name that matched. This
+saves searching to find which numbered group it was. (An alternative way of
+solving this problem is to use a "branch reset" group, as described in the
+previous section.)
.P
-If you make a backreference to a non-unique named subpattern from elsewhere in
-the pattern, the subpatterns to which the name refers are checked in the order
-in which they appear in the overall pattern. The first one that is set is used
-for the reference. For example, this pattern matches both "foofoo" and
-"barbar" but not "foobar" or "barfoo":
+If you make a backreference to a non-unique named group from elsewhere in the
+pattern, the groups to which the name refers are checked in the order in which
+they appear in the overall pattern. The first one that is set is used for the
+reference. For example, this pattern matches both "foofoo" and "barbar" but not
+"foobar" or "barfoo":
.sp
(?:(?foo)|(?bar))\ek
.sp
.P
-If you make a subroutine call to a non-unique named subpattern, the one that
+If you make a subroutine call to a non-unique named group, the one that
corresponds to the first occurrence of the name is used. In the absence of
duplicate numbers this is the one with the lowest number.
.P
@@ -1917,11 +1940,11 @@ test (see the
.\"
section about conditions
.\"
-below), either to check whether a subpattern has matched, or to check for
-recursion, all subpatterns with the same name are tested. If the condition is
-true for any one of them, the overall condition is true. This is the same
-behaviour as testing by number. For further details of the interfaces for
-handling named subpatterns, see the
+below), either to check whether a capture group has matched, or to check for
+recursion, all groups with the same name are tested. If the condition is true
+for any one of them, the overall condition is true. This is the same behaviour
+as testing by number. For further details of the interfaces for handling named
+capture groups, see the
.\" HREF
\fBpcre2api\fP
.\"
@@ -1937,18 +1960,18 @@ items:
a literal data character
the dot metacharacter
the \eC escape sequence
- the \eX escape sequence
the \eR escape sequence
+ the \eX escape sequence
an escape such as \ed or \epL that matches a single character
a character class
a backreference
- a parenthesized subpattern (including most assertions)
- a subroutine call to a subpattern (recursive or otherwise)
+ a parenthesized group (including most assertions)
+ a subroutine call (recursive or otherwise)
.sp
The general repetition quantifier specifies a minimum and maximum number of
permitted matches, by giving the two numbers in curly brackets (braces),
separated by a comma. The numbers must be less than 65536, and the first must
-be less than or equal to the second. For example:
+be less than or equal to the second. For example,
.sp
z{2,4}
.sp
@@ -1976,18 +1999,18 @@ several code units long (and they may be of different lengths).
.P
The quantifier {0} is permitted, causing the expression to behave as if the
previous item and the quantifier were not present. This may be useful for
-subpatterns that are referenced as
-.\" HTML
+capture groups that are referenced as
+.\" HTML
.\"
subroutines
.\"
from elsewhere in the pattern (but see also the section entitled
.\" HTML
.\"
-"Defining subpatterns for use by reference only"
+"Defining capture groups for use by reference only"
.\"
-below). Items other than subpatterns that have a {0} quantifier are omitted
-from the compiled pattern.
+below). Except for parenthesized groups, items that have a {0} quantifier are
+omitted from the compiled pattern.
.P
For convenience, the three most common quantifiers have single-character
abbreviations:
@@ -1996,22 +2019,24 @@ abbreviations:
+ is equivalent to {1,}
? is equivalent to {0,1}
.sp
-It is possible to construct infinite loops by following a subpattern that can
-match no characters with a quantifier that has no upper limit, for example:
+It is possible to construct infinite loops by following a group that can match
+no characters with a quantifier that has no upper limit, for example:
.sp
(a?)*
.sp
Earlier versions of Perl and PCRE1 used to give an error at compile time for
such patterns. However, because there are cases where this can be useful, such
-patterns are now accepted, but if any repetition of the subpattern does in fact
-match no characters, the loop is forcibly broken.
-.P
-By default, the quantifiers are "greedy", that is, they match as much as
-possible (up to the maximum number of permitted times), without causing the
-rest of the pattern to fail. The classic example of where this gives problems
-is in trying to match comments in C programs. These appear between /* and */
-and within the comment, individual * and / characters may appear. An attempt to
-match C comments by applying the pattern
+patterns are now accepted, but whenever an iteration of such a group matches no
+characters, matching moves on to the next item in the pattern instead of
+repeatedly matching an empty string. This does not prevent backtracking into
+any of the iterations if a subsequent item fails to match.
+.P
+By default, quantifiers are "greedy", that is, they match as much as possible
+(up to the maximum number of permitted times), without causing the rest of the
+pattern to fail. The classic example of where this gives problems is in trying
+to match comments in C programs. These appear between /* and */ and within the
+comment, individual * and / characters may appear. An attempt to match C
+comments by applying the pattern
.sp
/\e*.*\e*/
.sp
@@ -2020,10 +2045,9 @@ to the string
/* first comment */ not comment /* second comment */
.sp
fails, because it matches the entire string owing to the greediness of the .*
-item.
-.P
-If a quantifier is followed by a question mark, it ceases to be greedy, and
-instead matches the minimum number of times possible, so the pattern
+item. However, if a quantifier is followed by a question mark, it ceases to be
+greedy, and instead matches the minimum number of times possible, so the
+pattern
.sp
/\e*.*?\e*/
.sp
@@ -2042,7 +2066,7 @@ the quantifiers are not greedy by default, but individual ones can be made
greedy by following them with a question mark. In other words, it inverts the
default behaviour.
.P
-When a parenthesized subpattern is quantified with a minimum repeat count that
+When a parenthesized group is quantified with a minimum repeat count that
is greater than 1 or with a limited maximum, more memory is required for the
compiled pattern, in proportion to the size of the minimum or maximum.
.P
@@ -2077,15 +2101,14 @@ It matches "ab" in the subject "aab". The use of the backtracking control verbs
(*PRUNE) and (*SKIP) also disable this optimization, and there is an option,
PCRE2_NO_DOTSTAR_ANCHOR, to do so explicitly.
.P
-When a capturing subpattern is repeated, the value captured is the substring
-that matched the final iteration. For example, after
+When a capture group is repeated, the value captured is the substring that
+matched the final iteration. For example, after
.sp
(tweedle[dume]{3}\es*)+
.sp
has matched "tweedledum tweedledee" the value of the captured substring is
-"tweedledee". However, if there are nested capturing subpatterns, the
-corresponding captured values may have been set in previous iterations. For
-example, after
+"tweedledee". However, if there are nested capture groups, the corresponding
+captured values may have been set in previous iterations. For example, after
.sp
(a|(b))+
.sp
@@ -2111,7 +2134,7 @@ After matching all 6 digits and then failing to match "foo", the normal
action of the matcher is to try again with only 5 digits matching the \ed+
item, and then with 4, and so on, before ultimately failing. "Atomic grouping"
(a term taken from Jeffrey Friedl's book) provides the means for specifying
-that once a subpattern has matched, it is not to be re-evaluated in this way.
+that once a group has matched, it is not to be re-evaluated in this way.
.P
If we use atomic grouping for the previous example, the matcher gives up
immediately on failing to match "foo" the first time. The notation is a kind of
@@ -2119,23 +2142,28 @@ special parenthesis, starting with (?> as in this example:
.sp
(?>\ed+)foo
.sp
-This kind of parenthesis "locks up" the part of the pattern it contains once
-it has matched, and a failure further into the pattern is prevented from
-backtracking into it. Backtracking past it to previous items, however, works as
-normal.
+Perl 5.28 introduced an experimental alphabetic form starting with (* which may
+be easier to remember:
+.sp
+ (*atomic:\ed+)foo
+.sp
+This kind of parenthesized group "locks up" the part of the pattern it
+contains once it has matched, and a failure further into the pattern is
+prevented from backtracking into it. Backtracking past it to previous items,
+however, works as normal.
.P
-An alternative description is that a subpattern of this type matches exactly
-the string of characters that an identical standalone pattern would match, if
+An alternative description is that a group of this type matches exactly the
+string of characters that an identical standalone pattern would match, if
anchored at the current point in the subject string.
.P
-Atomic grouping subpatterns are not capturing subpatterns. Simple cases such as
-the above example can be thought of as a maximizing repeat that must swallow
-everything it can. So, while both \ed+ and \ed+? are prepared to adjust the
-number of digits they match in order to make the rest of the pattern match,
-(?>\ed+) can only match an entire sequence of digits.
+Atomic groups are not capture groups. Simple cases such as the above example
+can be thought of as a maximizing repeat that must swallow everything it can.
+So, while both \ed+ and \ed+? are prepared to adjust the number of digits they
+match in order to make the rest of the pattern match, (?>\ed+) can only match
+an entire sequence of digits.
.P
Atomic groups in general can of course contain arbitrarily complicated
-subpatterns, and can be nested. However, when the subpattern for an atomic
+expressions, and can be nested. However, when the contents of an atomic
group is just a single repeated item, as in the example above, a simpler
notation, called a "possessive quantifier" can be used. This consists of an
additional + character following a quantifier. Using this notation, the
@@ -2157,8 +2185,8 @@ difference; possessive quantifiers should be slightly faster.
The possessive quantifier syntax is an extension to the Perl 5.8 syntax.
Jeffrey Friedl originated the idea (and the name) in the first edition of his
book. Mike McCloskey liked it, so implemented it when he built Sun's Java
-package, and PCRE1 copied it from there. It ultimately found its way into Perl
-at release 5.10.
+package, and PCRE1 copied it from there. It found its way into Perl at release
+5.10.
.P
PCRE2 has an optimization that automatically "possessifies" certain simple
pattern constructs. For example, the sequence A+B is treated as A++B because
@@ -2166,10 +2194,9 @@ there is no point in backtracking into a sequence of A's when B must follow.
This feature can be disabled by the PCRE2_NO_AUTOPOSSESS option, or starting
the pattern with (*NO_AUTO_POSSESS).
.P
-When a pattern contains an unlimited repeat inside a subpattern that can itself
-be repeated an unlimited number of times, the use of an atomic group is the
-only way to avoid some failing matches taking a very long time indeed. The
-pattern
+When a pattern contains an unlimited repeat inside a group that can itself be
+repeated an unlimited number of times, the use of an atomic group is the only
+way to avoid some failing matches taking a very long time indeed. The pattern
.sp
(\eD+|<\ed+>)*[!?]
.sp
@@ -2198,29 +2225,28 @@ sequences of non-digits cannot be broken, and failure happens quickly.
.rs
.sp
Outside a character class, a backslash followed by a digit greater than 0 (and
-possibly further digits) is a backreference to a capturing subpattern earlier
-(that is, to its left) in the pattern, provided there have been that many
-previous capturing left parentheses.
+possibly further digits) is a backreference to a capture group earlier (that
+is, to its left) in the pattern, provided there have been that many previous
+capture groups.
.P
However, if the decimal number following the backslash is less than 8, it is
-always taken as a backreference, and causes an error only if there are not
-that many capturing left parentheses in the entire pattern. In other words, the
-parentheses that are referenced need not be to the left of the reference for
-numbers less than 8. A "forward backreference" of this type can make sense
-when a repetition is involved and the subpattern to the right has participated
-in an earlier iteration.
-.P
-It is not possible to have a numerical "forward backreference" to a subpattern
-whose number is 8 or more using this syntax because a sequence such as \e50 is
+always taken as a backreference, and causes an error only if there are not that
+many capture groups in the entire pattern. In other words, the group that is
+referenced need not be to the left of the reference for numbers less than 8. A
+"forward backreference" of this type can make sense when a repetition is
+involved and the group to the right has participated in an earlier iteration.
+.P
+It is not possible to have a numerical "forward backreference" to a group whose
+number is 8 or more using this syntax because a sequence such as \e50 is
interpreted as a character defined in octal. See the subsection entitled
"Non-printing characters"
.\" HTML
.\"
above
.\"
-for further details of the handling of digits following a backslash. There is
-no such problem when named parentheses are used. A backreference to any
-subpattern is possible using named parentheses (see below).
+for further details of the handling of digits following a backslash. Other
+forms of backreferencing do not suffer from this restriction. In particular,
+there is no problem when named capture groups are used (see below).
.P
Another way of avoiding the ambiguity inherent in the use of digits following a
backslash is to use the \eg escape sequence. This escape must be followed by a
@@ -2237,22 +2263,22 @@ the reference. A signed number is a relative reference. Consider this example:
.sp
(abc(def)ghi)\eg{-1}
.sp
-The sequence \eg{-1} is a reference to the most recently started capturing
-subpattern before \eg, that is, is it equivalent to \e2 in this example.
-Similarly, \eg{-2} would be equivalent to \e1. The use of relative references
-can be helpful in long patterns, and also in patterns that are created by
-joining together fragments that contain references within themselves.
+The sequence \eg{-1} is a reference to the most recently started capture group
+before \eg, that is, is it equivalent to \e2 in this example. Similarly,
+\eg{-2} would be equivalent to \e1. The use of relative references can be
+helpful in long patterns, and also in patterns that are created by joining
+together fragments that contain references within themselves.
.P
-The sequence \eg{+1} is a reference to the next capturing subpattern. This kind
-of forward reference can be useful it patterns that repeat. Perl does not
-support the use of + in this way.
+The sequence \eg{+1} is a reference to the next capture group. This kind of
+forward reference can be useful in patterns that repeat. Perl does not support
+the use of + in this way.
.P
-A backreference matches whatever actually matched the capturing subpattern in
-the current subject string, rather than anything matching the subpattern
-itself (see
-.\" HTML
+A backreference matches whatever actually most recently matched the capture
+group in the current subject string, rather than anything at all that matches
+the group (see
+.\" HTML
.\"
-"Subpatterns as subroutines"
+"Groups as subroutines"
.\"
below for a way of doing that). So the pattern
.sp
@@ -2265,26 +2291,26 @@ backreference, the case of letters is relevant. For example,
((?i)rah)\es+\e1
.sp
matches "rah rah" and "RAH RAH", but not "RAH rah", even though the original
-capturing subpattern is matched caselessly.
+capture group is matched caselessly.
.P
-There are several different ways of writing backreferences to named
-subpatterns. The .NET syntax \ek{name} and the Perl syntax \ek or
-\ek'name' are supported, as is the Python syntax (?P=name). Perl 5.10's unified
+There are several different ways of writing backreferences to named capture
+groups. The .NET syntax \ek{name} and the Perl syntax \ek or \ek'name'
+are supported, as is the Python syntax (?P=name). Perl 5.10's unified
backreference syntax, in which \eg can be used for both numeric and named
-references, is also supported. We could rewrite the above example in any of
-the following ways:
+references, is also supported. We could rewrite the above example in any of the
+following ways:
.sp
(?(?i)rah)\es+\ek
(?'p1'(?i)rah)\es+\ek{p1}
(?P(?i)rah)\es+(?P=p1)
(?(?i)rah)\es+\eg{p1}
.sp
-A subpattern that is referenced by name may appear in the pattern before or
+A capture group that is referenced by name may appear in the pattern before or
after the reference.
.P
-There may be more than one backreference to the same subpattern. If a
-subpattern has not actually been used in a particular match, any backreferences
-to it always fail by default. For example, the pattern
+There may be more than one backreference to the same group. If a group has not
+actually been used in a particular match, backreferences to it always fail by
+default. For example, the pattern
.sp
(a|(bc))\e2
.sp
@@ -2292,12 +2318,11 @@ always fails if it starts to match "a" rather than "bc". However, if the
PCRE2_MATCH_UNSET_BACKREF option is set at compile time, a backreference to an
unset value matches an empty string.
.P
-Because there may be many capturing parentheses in a pattern, all digits
-following a backslash are taken as part of a potential backreference number.
-If the pattern continues with a digit character, some delimiter must be used to
-terminate the backreference. If the PCRE2_EXTENDED or PCRE2_EXTENDED_MORE
-option is set, this can be white space. Otherwise, the \eg{ syntax or an empty
-comment (see
+Because there may be many capture groups in a pattern, all digits following a
+backslash are taken as part of a potential backreference number. If the pattern
+continues with a digit character, some delimiter must be used to terminate the
+backreference. If the PCRE2_EXTENDED or PCRE2_EXTENDED_MORE option is set, this
+can be white space. Otherwise, the \eg{} syntax or an empty comment (see
.\" HTML
.\"
"Comments"
@@ -2308,19 +2333,18 @@ below) can be used.
.SS "Recursive backreferences"
.rs
.sp
-A backreference that occurs inside the parentheses to which it refers fails
-when the subpattern is first used, so, for example, (a\e1) never matches.
-However, such references can be useful inside repeated subpatterns. For
-example, the pattern
+A backreference that occurs inside the group to which it refers fails when the
+group is first used, so, for example, (a\e1) never matches. However, such
+references can be useful inside repeated groups. For example, the pattern
.sp
(a|b\e1)+
.sp
matches any number of "a"s and also "aba", "ababbaa" etc. At each iteration of
-the subpattern, the backreference matches the character string corresponding
-to the previous iteration. In order for this to work, the pattern must be such
-that the first iteration does not need to match the backreference. This can be
-done using alternation, as in the example above, or by a quantifier with a
-minimum of zero.
+the group, the backreference matches the character string corresponding to the
+previous iteration. In order for this to work, the pattern must be such that
+the first iteration does not need to match the backreference. This can be done
+using alternation, as in the example above, or by a quantifier with a minimum
+of zero.
.P
Backreferences of this type cause the group that they reference to be treated
as an
@@ -2344,24 +2368,42 @@ coded as \eb, \eB, \eA, \eG, \eZ, \ez, ^ and $ are described
above.
.\"
.P
-More complicated assertions are coded as subpatterns. There are two kinds:
-those that look ahead of the current position in the subject string, and those
-that look behind it, and in each case an assertion may be positive (must
-succeed for matching to continue) or negative (must not succeed for matching to
-continue). An assertion subpattern is matched in the normal way, except that,
-when matching continues after a successful assertion, the matching position in
-the subject string is as it was before the assertion was processed.
+More complicated assertions are coded as parenthesized groups. There are two
+kinds: those that look ahead of the current position in the subject string, and
+those that look behind it, and in each case an assertion may be positive (must
+match for the assertion to be true) or negative (must not match for the
+assertion to be true). An assertion group is matched in the normal way,
+and if it is true, matching continues after it, but with the matching position
+in the subject string reset to what it was before the assertion was processed.
.P
-Assertion subpatterns are not capturing subpatterns. If an assertion contains
-capturing subpatterns within it, these are counted for the purposes of
-numbering the capturing subpatterns in the whole pattern. Within each branch of
-an assertion, locally captured substrings may be referenced in the usual way.
-For example, a sequence such as (.)\eg{-1} can be used to check that two
-adjacent characters are the same.
+The Perl-compatible lookaround assertions are atomic. If an assertion is true,
+but there is a subsequent matching failure, there is no backtracking into the
+assertion. However, there are some cases where non-atomic assertions can be
+useful. PCRE2 has some support for these, described in the section entitled
+.\" HTML
+.\"
+"Non-atomic assertions"
+.\"
+below, but they are not Perl-compatible.
+.P
+A lookaround assertion may appear as the condition in a
+.\" HTML
+.\"
+conditional group
+.\"
+(see below). In this case, the result of matching the assertion determines
+which branch of the condition is followed.
+.P
+Assertion groups are not capture groups. If an assertion contains capture
+groups within it, these are counted for the purposes of numbering the capture
+groups in the whole pattern. Within each branch of an assertion, locally
+captured substrings may be referenced in the usual way. For example, a sequence
+such as (.)\eg{-1} can be used to check that two adjacent characters are the
+same.
.P
When a branch within an assertion fails to match, any substrings that were
captured are discarded (as happens with any pattern branch that fails to
-match). A negative assertion succeeds only when all its branches fail to match;
+match). A negative assertion is true only when all its branches fail to match;
this means that no captured substrings are ever retained after a successful
negative assertion. When an assertion contains a matching branch, what happens
depends on the type of assertion.
@@ -2369,26 +2411,26 @@ depends on the type of assertion.
For a positive assertion, internally captured substrings in the successful
branch are retained, and matching continues with the next pattern item after
the assertion. For a negative assertion, a matching branch means that the
-assertion has failed. If the assertion is being used as a condition in a
+assertion is not true. If such an assertion is being used as a condition in a
.\" HTML
.\"
-conditional subpattern
+conditional group
.\"
(see below), captured substrings are retained, because matching continues with
the "no" branch of the condition. For other failing negative assertions,
control passes to the previous backtracking point, thus discarding any captured
strings within the assertion.
.P
-For compatibility with Perl, most assertion subpatterns may be repeated; though
-it makes no sense to assert the same thing several times, the side effect of
-capturing parentheses may occasionally be useful. However, an assertion that
-forms the condition for a conditional subpattern may not be quantified. In
-practice, for other assertions, there only three cases:
+For compatibility with Perl, most assertion groups may be repeated; though it
+makes no sense to assert the same thing several times, the side effect of
+capturing may occasionally be useful. However, an assertion that forms the
+condition for a conditional group may not be quantified. In practice, for
+other assertions, there only three cases:
.sp
(1) If the quantifier is {0}, the assertion is never obeyed during matching.
-However, it may contain internal capturing parenthesized groups that are called
-from elsewhere via the
-.\" HTML
+However, it may contain internal capture groups that are called from elsewhere
+via the
+.\" HTML
.\"
subroutine mechanism.
.\"
@@ -2401,6 +2443,25 @@ without the assertion, the order depending on the greediness of the quantifier.
The assertion is obeyed just once when encountered during matching.
.
.
+.SS "Alphabetic assertion names"
+.rs
+.sp
+Traditionally, symbolic sequences such as (?= and (?<= have been used to
+specify lookaround assertions. Perl 5.28 introduced some experimental
+alphabetic alternatives which might be easier to remember. They all start with
+(* instead of (? and must be written using lower case letters. PCRE2 supports
+the following synonyms:
+.sp
+ (*positive_lookahead: or (*pla: is the same as (?=
+ (*negative_lookahead: or (*nla: is the same as (?!
+ (*positive_lookbehind: or (*plb: is the same as (?<=
+ (*negative_lookbehind: or (*nlb: is the same as (?
+.\" HTML
.\"
"Subroutine"
.\"
calls (see below) such as (?2) or (?&X) are permitted in lookbehinds, as long
-as the subpattern matches a fixed-length string. However,
+as the called capture group matches a fixed-length string. However,
.\" HTML
.\"
recursion,
@@ -2498,10 +2559,10 @@ is not supported.
Perl does not support backreferences in lookbehinds. PCRE2 does support them,
but only if certain conditions are met. The PCRE2_MATCH_UNSET_BACKREF option
must not be set, there must be no use of (?| in the pattern (it creates
-duplicate subpattern numbers), and if the backreference is by name, the name
-must be unique. Of course, the referenced subpattern must itself be of fixed
-length. The following pattern matches words containing at least two characters
-that begin and end with the same character:
+duplicate group numbers), and if the backreference is by name, the name
+must be unique. Of course, the referenced group must itself match a fixed
+length substring. The following pattern matches words containing at least two
+characters that begin and end with the same character:
.sp
\eb(\ew)\ew++(?<=\e1)
.P
@@ -2566,14 +2627,138 @@ is another pattern that matches "foo" preceded by three digits and any three
characters that are not "999".
.
.
+.\" HTML
+.SH "NON-ATOMIC ASSERTIONS"
+.rs
+.sp
+The traditional Perl-compatible lookaround assertions are atomic. That is, if
+an assertion is true, but there is a subsequent matching failure, there is no
+backtracking into the assertion. However, there are some cases where non-atomic
+positive assertions can be useful. PCRE2 provides these using the following
+syntax:
+.sp
+ (*non_atomic_positive_lookahead: or (*napla:
+ (*non_atomic_positive_lookbehind: or (*naplb:
+.sp
+Consider the problem of finding the right-most word in a string that also
+appears earlier in the string, that is, it must appear at least twice in total.
+This pattern returns the required result as captured substring 1:
+.sp
+ ^(?x)(*napla: .* \eb(\ew++)) (?> .*? \eb\e1\eb ){2}
+.sp
+For a subject such as "word1 word2 word3 word2 word3 word4" the result is
+"word3". How does it work? At the start, ^(?x) anchors the pattern and sets the
+"x" option, which causes white space (introduced for readability) to be
+ignored. Inside the assertion, the greedy .* at first consumes the entire
+string, but then has to backtrack until the rest of the assertion can match a
+word, which is captured by group 1. In other words, when the assertion first
+succeeds, it captures the right-most word in the string.
+.P
+The current matching point is then reset to the start of the subject, and the
+rest of the pattern match checks for two occurrences of the captured word,
+using an ungreedy .*? to scan from the left. If this succeeds, we are done, but
+if the last word in the string does not occur twice, this part of the pattern
+fails. If a traditional atomic lookhead (?= or (*pla: had been used, the
+assertion could not be re-entered, and the whole match would fail. The pattern
+would succeed only if the very last word in the subject was found twice.
+.P
+Using a non-atomic lookahead, however, means that when the last word does not
+occur twice in the string, the lookahead can backtrack and find the second-last
+word, and so on, until either the match succeeds, or all words have been
+tested.
+.P
+Two conditions must be met for a non-atomic assertion to be useful: the
+contents of one or more capturing groups must change after a backtrack into the
+assertion, and there must be a backreference to a changed group later in the
+pattern. If this is not the case, the rest of the pattern match fails exactly
+as before because nothing has changed, so using a non-atomic assertion just
+wastes resources.
+.P
+Non-atomic assertions are not supported by the alternative matching function
+\fBpcre2_dfa_match()\fP. They are also not supported by JIT (but may be in
+future). Note that assertions that appear as conditions for
+.\" HTML
+.\"
+conditional groups
+.\"
+(see below) must be atomic.
+.
+.
+.SH "SCRIPT RUNS"
+.rs
+.sp
+In concept, a script run is a sequence of characters that are all from the same
+Unicode script such as Latin or Greek. However, because some scripts are
+commonly used together, and because some diacritical and other marks are used
+with multiple scripts, it is not that simple. There is a full description of
+the rules that PCRE2 uses in the section entitled
+.\" HTML
+.\"
+"Script Runs"
+.\"
+in the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+documentation.
+.P
+If part of a pattern is enclosed between (*script_run: or (*sr: and a closing
+parenthesis, it fails if the sequence of characters that it matches are not a
+script run. After a failure, normal backtracking occurs. Script runs can be
+used to detect spoofing attacks using characters that look the same, but are
+from different scripts. The string "paypal.com" is an infamous example, where
+the letters could be a mixture of Latin and Cyrillic. This pattern ensures that
+the matched characters in a sequence of non-spaces that follow white space are
+a script run:
+.sp
+ \es+(*sr:\eS+)
+.sp
+To be sure that they are all from the Latin script (for example), a lookahead
+can be used:
+.sp
+ \es+(?=\ep{Latin})(*sr:\eS+)
+.sp
+This works as long as the first character is expected to be a character in that
+script, and not (for example) punctuation, which is allowed with any script. If
+this is not the case, a more creative lookahead is needed. For example, if
+digits, underscore, and dots are permitted at the start:
+.sp
+ \es+(?=[0-9_.]*\ep{Latin})(*sr:\eS+)
+.sp
+.P
+In many cases, backtracking into a script run pattern fragment is not
+desirable. The script run can employ an atomic group to prevent this. Because
+this is a common requirement, a shorthand notation is provided by
+(*atomic_script_run: or (*asr:
+.sp
+ (*asr:...) is the same as (*sr:(?>...))
+.sp
+Note that the atomic group is inside the script run. Putting it outside would
+not prevent backtracking into the script run pattern.
+.P
+Support for script runs is not available if PCRE2 is compiled without Unicode
+support. A compile-time error is given if any of the above constructs is
+encountered. Script runs are not supported by the alternate matching function,
+\fBpcre2_dfa_match()\fP because they use the same mechanism as capturing
+parentheses.
+.P
+\fBWarning:\fP The (*ACCEPT) control verb
+.\" HTML
+.\"
+(see below)
+.\"
+should not be used within a script run group, because it causes an immediate
+exit from the group, bypassing the script run checking.
+.
+.
.\" HTML
-.SH "CONDITIONAL SUBPATTERNS"
+.SH "CONDITIONAL GROUPS"
.rs
.sp
-It is possible to cause the matching process to obey a subpattern
-conditionally or to choose between two alternative subpatterns, depending on
-the result of an assertion, or whether a specific capturing subpattern has
-already been matched. The two possible forms of conditional subpattern are:
+It is possible to cause the matching process to obey a pattern fragment
+conditionally or to choose between two alternative fragments, depending on
+the result of an assertion, or whether a specific capture group has
+already been matched. The two possible forms of conditional group are:
.sp
(?(condition)yes-pattern)
(?(condition)yes-pattern|no-pattern)
@@ -2581,38 +2766,36 @@ already been matched. The two possible forms of conditional subpattern are:
If the condition is satisfied, the yes-pattern is used; otherwise the
no-pattern (if present) is used. An absent no-pattern is equivalent to an empty
string (it always matches). If there are more than two alternatives in the
-subpattern, a compile-time error occurs. Each of the two alternatives may
-itself contain nested subpatterns of any form, including conditional
-subpatterns; the restriction to two alternatives applies only at the level of
-the condition. This pattern fragment is an example where the alternatives are
-complex:
+group, a compile-time error occurs. Each of the two alternatives may itself
+contain nested groups of any form, including conditional groups; the
+restriction to two alternatives applies only at the level of the condition
+itself. This pattern fragment is an example where the alternatives are complex:
.sp
(?(1) (A|B|C) | (D | (?(2)E|F) | E) )
.sp
.P
-There are five kinds of condition: references to subpatterns, references to
+There are five kinds of condition: references to capture groups, references to
recursion, two pseudo-conditions called DEFINE and VERSION, and assertions.
.
.
-.SS "Checking for a used subpattern by number"
+.SS "Checking for a used capture group by number"
.rs
.sp
If the text between the parentheses consists of a sequence of digits, the
-condition is true if a capturing subpattern of that number has previously
-matched. If there is more than one capturing subpattern with the same number
-(see the earlier
+condition is true if a capture group of that number has previously matched. If
+there is more than one capture group with the same number (see the earlier
.\"
.\" HTML
.\"
-section about duplicate subpattern numbers),
+section about duplicate group numbers),
.\"
the condition is true if any of them have matched. An alternative notation is
-to precede the digits with a plus or minus sign. In this case, the subpattern
-number is relative rather than absolute. The most recently opened parentheses
-can be referenced by (?(-1), the next most recent by (?(-2), and so on. Inside
-loops it can also make sense to refer to subsequent groups. The next
-parentheses to be opened can be referenced as (?(+1), and so on. (The value
-zero in any of these forms is not used; it provokes a compile-time error.)
+to precede the digits with a plus or minus sign. In this case, the group number
+is relative rather than absolute. The most recently opened capture group can be
+referenced by (?(-1), the next most recent by (?(-2), and so on. Inside loops
+it can also make sense to refer to subsequent groups. The next capture group
+can be referenced as (?(+1), and so on. (The value zero in any of these forms
+is not used; it provokes a compile-time error.)
.P
Consider the following pattern, which contains non-significant white space to
make it more readable (assume the PCRE2_EXTENDED option) and to divide it into
@@ -2623,12 +2806,12 @@ three parts for ease of discussion:
The first part matches an optional opening parenthesis, and if that
character is present, sets it as the first captured substring. The second part
matches one or more characters that are not parentheses. The third part is a
-conditional subpattern that tests whether or not the first set of parentheses
-matched. If they did, that is, if subject started with an opening parenthesis,
+conditional group that tests whether or not the first capture group
+matched. If it did, that is, if subject started with an opening parenthesis,
the condition is true, and so the yes-pattern is executed and a closing
parenthesis is required. Otherwise, since no-pattern is not present, the
-subpattern matches nothing. In other words, this pattern matches a sequence of
-non-parentheses, optionally enclosed in parentheses.
+conditional group matches nothing. In other words, this pattern matches a
+sequence of non-parentheses, optionally enclosed in parentheses.
.P
If you were embedding this pattern in a larger one, you could use a relative
reference:
@@ -2638,21 +2821,20 @@ reference:
This makes the fragment independent of the parentheses in the larger pattern.
.
.
-.SS "Checking for a used subpattern by name"
+.SS "Checking for a used capture group by name"
.rs
.sp
Perl uses the syntax (?()...) or (?('name')...) to test for a used
-subpattern by name. For compatibility with earlier versions of PCRE1, which had
-this facility before Perl, the syntax (?(name)...) is also recognized. Note,
-however, that undelimited names consisting of the letter R followed by digits
-are ambiguous (see the following section).
-.P
-Rewriting the above example to use a named subpattern gives this:
+capture group by name. For compatibility with earlier versions of PCRE1, which
+had this facility before Perl, the syntax (?(name)...) is also recognized.
+Note, however, that undelimited names consisting of the letter R followed by
+digits are ambiguous (see the following section). Rewriting the above example
+to use a named group gives this:
.sp
(? \e( )? [^()]+ (?() \e) )
.sp
If the name used in a condition of this kind is a duplicate, the test is
-applied to all subpatterns of the same name, and is true if any one of them has
+applied to all groups of the same name, and is true if any one of them has
matched.
.
.
@@ -2667,22 +2849,22 @@ sections entitled
"Recursive patterns"
.\"
and
-.\" HTML
+.\" HTML
.\"
-"Subpatterns as subroutines"
+"Groups as subroutines"
.\"
-below for details of recursion and subpattern calls.
+below for details of recursion and subroutine calls.
.P
-If a condition is the string (R), and there is no subpattern with the name R,
-the condition is true if matching is currently in a recursion or subroutine
-call to the whole pattern or any subpattern. If digits follow the letter R, and
-there is no subpattern with that name, the condition is true if the most recent
-call is into a subpattern with the given number, which must exist somewhere in
-the overall pattern. This is a contrived example that is equivalent to a+b:
+If a condition is the string (R), and there is no capture group with the name
+R, the condition is true if matching is currently in a recursion or subroutine
+call to the whole pattern or any capture group. If digits follow the letter R,
+and there is no group with that name, the condition is true if the most recent
+call is into a group with the given number, which must exist somewhere in the
+overall pattern. This is a contrived example that is equivalent to a+b:
.sp
((?(R1)a+|(?1)b))
.sp
-However, in both cases, if there is a subpattern with a matching name, the
+However, in both cases, if there is a capture group with a matching name, the
condition tests for its being set, as described in the section above, instead
of testing for recursion. For example, creating a group with the name R1 by
adding (?) to the above pattern completely changes its meaning.
@@ -2691,27 +2873,27 @@ If a name preceded by ampersand follows the letter R, for example:
.sp
(?(R&name)...)
.sp
-the condition is true if the most recent recursion is into a subpattern of that
-name (which must exist within the pattern).
+the condition is true if the most recent recursion is into a group of that name
+(which must exist within the pattern).
.P
This condition does not check the entire recursion stack. It tests only the
current level. If the name used in a condition of this kind is a duplicate, the
-test is applied to all subpatterns of the same name, and is true if any one of
+test is applied to all groups of the same name, and is true if any one of
them is the most recent recursion.
.P
At "top level", all these recursion test conditions are false.
.
.
.\" HTML
-.SS "Defining subpatterns for use by reference only"
+.SS "Defining capture groups for use by reference only"
.rs
.sp
If the condition is the string (DEFINE), the condition is always false, even if
there is a group with the name DEFINE. In this case, there may be only one
-alternative in the subpattern. It is always skipped if control reaches this
-point in the pattern; the idea of DEFINE is that it can be used to define
-subroutines that can be referenced from elsewhere. (The use of
-.\" HTML
+alternative in the rest of the conditional group. It is always skipped if
+control reaches this point in the pattern; the idea of DEFINE is that it can be
+used to define subroutines that can be referenced from elsewhere. (The use of
+.\" HTML
.\"
subroutines
.\"
@@ -2751,10 +2933,17 @@ than two digits.
.SS "Assertion conditions"
.rs
.sp
-If the condition is not in any of the above formats, it must be an assertion.
-This may be a positive or negative lookahead or lookbehind assertion. Consider
-this pattern, again containing non-significant white space, and with the two
-alternatives on the second line:
+If the condition is not in any of the above formats, it must be a parenthesized
+assertion. This may be a positive or negative lookahead or lookbehind
+assertion. However, it must be a traditional atomic assertion, not one of the
+PCRE2-specific
+.\" HTML
+.\"
+non-atomic assertions.
+.\"
+.P
+Consider this pattern, again containing non-significant white space, and with
+the two alternatives on the second line:
.sp
(?(?=[^a-z]*[a-z])
\ed{2}-[a-z]{3}-\ed{2} | \ed{2}-\ed{2}-\ed{2} )
@@ -2766,11 +2955,11 @@ subject is matched against the first alternative; otherwise it is matched
against the second. This pattern matches strings in one of the two forms
dd-aaa-dd or dd-dd-dd, where aaa are letters and dd are digits.
.P
-When an assertion that is a condition contains capturing subpatterns, any
+When an assertion that is a condition contains capture groups, any
capturing that occurs in a matching branch is retained afterwards, for both
positive and negative assertions, because matching always continues after the
assertion, whether it succeeds or fails. (Compare non-conditional assertions,
-when captures are retained only for positive assertions that succeed.)
+for which captures are retained only for positive assertions that succeed.)
.
.
.\" HTML
@@ -2780,7 +2969,7 @@ when captures are retained only for positive assertions that succeed.)
There are two ways of including comments in patterns that are processed by
PCRE2. In both cases, the start of the comment must not be in a character
class, nor in the middle of any other sequence of related characters such as
-(?: or a subpattern name or number. The characters that make up a comment play
+(?: or a group name or number. The characters that make up a comment play
no part in the pattern matching.
.P
The sequence (?# marks the start of a comment that continues up to the next
@@ -2830,13 +3019,13 @@ recursively to the pattern in which it appears.
.P
Obviously, PCRE2 cannot support the interpolation of Perl code. Instead, it
supports special syntax for recursion of the entire pattern, and also for
-individual subpattern recursion. After its introduction in PCRE1 and Python,
+individual capture group recursion. After its introduction in PCRE1 and Python,
this kind of recursion was subsequently introduced into Perl at release 5.10.
.P
A special item that consists of (? followed by a number greater than zero and a
-closing parenthesis is a recursive subroutine call of the subpattern of the
-given number, provided that it occurs inside that subpattern. (If not, it is a
-.\" HTML
+closing parenthesis is a recursive subroutine call of the capture group of the
+given number, provided that it occurs inside that group. (If not, it is a
+.\" HTML
.\"
non-recursive subroutine
.\"
@@ -2869,26 +3058,26 @@ parentheses preceding the recursion. In other words, a negative number counts
capturing parentheses leftwards from the point at which it is encountered.
.P
Be aware however, that if
-.\" HTML
+.\" HTML
.\"
-duplicate subpattern numbers
+duplicate capture group numbers
.\"
-are in use, relative references refer to the earliest subpattern with the
+are in use, relative references refer to the earliest group with the
appropriate number. Consider, for example:
.sp
(?|(a)|(b)) (c) (?-2)
.sp
-The first two capturing groups (a) and (b) are both numbered 1, and group (c)
+The first two capture groups (a) and (b) are both numbered 1, and group (c)
is number 2. When the reference (?-2) is encountered, the second most recently
opened parentheses has the number 1, but it is the first such group (the (a)
group) to which the recursion refers. This would be the same if an absolute
reference (?1) was used. In other words, relative references are just a
shorthand for computing a group number.
.P
-It is also possible to refer to subsequently opened parentheses, by writing
+It is also possible to refer to subsequent capture groups, by writing
references such as (?+2). However, these cannot be recursive because the
reference is not inside the parentheses that are referenced. They are always
-.\" HTML
+.\" HTML
.\"
non-recursive subroutine
.\"
@@ -2900,7 +3089,7 @@ rewrite the above example as follows:
.sp
(? \e( ( [^()]++ | (?&pn) )* \e) )
.sp
-If there is more than one subpattern with the same name, the earliest one is
+If there is more than one group with the same name, the earliest one is
used.
.P
The example pattern that we have been looking at contains nested unlimited
@@ -2926,9 +3115,9 @@ documentation). If the pattern above is matched against
(ab(cd)ef)
.sp
the value for the inner capturing parentheses (numbered 2) is "ef", which is
-the last value taken on at the top level. If a capturing subpattern is not
-matched at the top level, its final captured value is unset, even if it was
-(temporarily) set at a deeper level during the matching process.
+the last value taken on at the top level. If a capture group is not matched at
+the top level, its final captured value is unset, even if it was (temporarily)
+set at a deeper level during the matching process.
.P
Do not confuse the (?R) item with the condition (R), which tests for recursion.
Consider this pattern, which matches text in angle brackets, allowing for
@@ -2937,9 +3126,9 @@ recursing), whereas any characters are permitted at the outer level.
.sp
< (?: (?(R) \ed++ | [^<>]*+) | (?R)) * >
.sp
-In this pattern, (?(R) is the start of a conditional subpattern, with two
-different alternatives for the recursive and non-recursive cases. The (?R) item
-is the actual recursive call.
+In this pattern, (?(R) is the start of a conditional group, with two different
+alternatives for the recursive and non-recursive cases. The (?R) item is the
+actual recursive call.
.
.
.\" HTML
@@ -2949,7 +3138,7 @@ is the actual recursive call.
Some former differences between PCRE2 and Perl no longer exist.
.P
Before release 10.30, recursion processing in PCRE2 differed from Perl in that
-a recursive subpattern call was always treated as an atomic group. That is,
+a recursive subroutine call was always treated as an atomic group. That is,
once it had matched some of the subject string, it was never re-entered, even
if it contained untried alternatives and there was a subsequent matching
failure. (Historical note: PCRE implemented recursion before Perl did.)
@@ -2982,7 +3171,7 @@ Perl takes so long that you think it has gone into a loop.
.P
Another way in which PCRE2 and Perl used to differ in their recursion
processing is in the handling of captured values. Formerly in Perl, when a
-subpattern was called recursively or as a subpattern (see the next section), it
+group was called recursively or as a subroutine (see the next section), it
had no access to any values that were captured outside the recursion, whereas
in PCRE2 these values can be referenced. Consider this pattern:
.sp
@@ -2995,17 +3184,16 @@ alternative matches "a" and then recurses. In the recursion, \e1 does now match
later versions (I tried 5.024) it now works.
.
.
-.\" HTML
-.SH "SUBPATTERNS AS SUBROUTINES"
+.\" HTML
+.SH "GROUPS AS SUBROUTINES"
.rs
.sp
-If the syntax for a recursive subpattern call (either by number or by
-name) is used outside the parentheses to which it refers, it operates a bit
-like a subroutine in a programming language. More accurately, PCRE2 treats the
-referenced subpattern as an independent subpattern which it tries to match at
-the current matching position. The called subpattern may be defined before or
-after the reference. A numbered reference can be absolute or relative, as in
-these examples:
+If the syntax for a recursive group call (either by number or by name) is used
+outside the parentheses to which it refers, it operates a bit like a subroutine
+in a programming language. More accurately, PCRE2 treats the referenced group
+as an independent subpattern which it tries to match at the current matching
+position. The called group may be defined before or after the reference. A
+numbered reference can be absolute or relative, as in these examples:
.sp
(...(absolute)...)...(?2)...
(...(relative)...)...(?-1)...
@@ -3028,21 +3216,21 @@ changed at PCRE2 release 10.30, so backtracking into subroutine calls can now
occur. However, any capturing parentheses that are set during the subroutine
call revert to their previous values afterwards.
.P
-Processing options such as case-independence are fixed when a subpattern is
+Processing options such as case-independence are fixed when a group is
defined, so if it is used as a subroutine, such options cannot be changed for
different calls. For example, consider this pattern:
.sp
(abc)(?i:(?-1))
.sp
It matches "abcabc". It does not match "abcABC" because the change of
-processing option does not affect the called subpattern.
+processing option does not affect the called group.
.P
The behaviour of
.\" HTML
.\"
backtracking control verbs
.\"
-in subpatterns when called as subroutines is described in the section entitled
+in groups when called as subroutines is described in the section entitled
.\" HTML
.\"
"Backtracking verbs in subroutines"
@@ -3056,8 +3244,8 @@ below.
.sp
For compatibility with Oniguruma, the non-Perl syntax \eg followed by a name or
a number enclosed either in angle brackets or single quotes, is an alternative
-syntax for referencing a subpattern as a subroutine, possibly recursively. Here
-are two of the examples used above, rewritten using this syntax:
+syntax for calling a group as a subroutine, possibly recursively. Here are two
+of the examples used above, rewritten using this syntax:
.sp
(? \e( ( (?>[^()]+) | \eg )* \e) )
(sens|respons)e and \eg'1'ibility
@@ -3154,7 +3342,8 @@ The doubling is removed before the string is passed to the callout function.
There are a number of special "Backtracking Control Verbs" (to use Perl's
terminology) that modify the behaviour of backtracking during matching. They
are generally of the form (*VERB) or (*VERB:NAME). Some verbs take either form,
-possibly behaving differently depending on whether or not a name is present.
+and may behave differently depending on whether or not a name argument is
+present. The names are not required to be unique within the pattern.
.P
By default, for compatibility with Perl, a name is any sequence of characters
that does not include a closing parenthesis. The name is not processed in
@@ -3178,7 +3367,8 @@ PCRE2_ALT_VERBNAMES is also set.
The maximum length of a name is 255 in the 8-bit library and 65535 in the
16-bit and 32-bit libraries. If the name is empty, that is, if the closing
parenthesis immediately follows the colon, the effect is as if the colon were
-not there. Any number of these verbs may occur in a pattern.
+not there. Any number of these verbs may occur in a pattern. Except for
+(*ACCEPT), they may not be quantified.
.P
Since these verbs are specifically related to backtracking, most of them can be
used only when the pattern is to be matched using the traditional matching
@@ -3198,7 +3388,7 @@ assertions,
and in
.\" HTML
.\"
-subpatterns called as subroutines
+capture groups called as subroutines
.\"
(whether or not recursively) is documented below.
.
@@ -3230,6 +3420,7 @@ Experiments with Perl suggest that it too has similar optimizations, and like
PCRE2, turning them off can change the result of a match.
.
.
+.\" HTML
.SS "Verbs that act immediately"
.rs
.sp
@@ -3238,8 +3429,8 @@ The following verbs act as soon as they are encountered.
(*ACCEPT) or (*ACCEPT:NAME)
.sp
This verb causes the match to end successfully, skipping the remainder of the
-pattern. However, when it is inside a subpattern that is called as a
-subroutine, only that subpattern is ended successfully. Matching then continues
+pattern. However, when it is inside a capture group that is called as a
+subroutine, only that group is ended successfully. Matching then continues
at the outer level. If (*ACCEPT) in triggered in a positive assertion, the
assertion succeeds; in a negative assertion, the assertion fails.
.P
@@ -3250,6 +3441,21 @@ example:
.sp
This matches "AB", "AAD", or "ACD"; when it matches "AB", "B" is captured by
the outer parentheses.
+.P
+(*ACCEPT) is the only backtracking verb that is allowed to be quantified
+because an ungreedy quantification with a minimum of zero acts only when a
+backtrack happens. Consider, for example,
+.sp
+ (A(*ACCEPT)??B)C
+.sp
+where A, B, and C may be complex expressions. After matching "A", the matcher
+processes "BC"; if that fails, causing a backtrack, (*ACCEPT) is triggered and
+the match succeeds. In both cases, all but C is captured. Whereas (*COMMIT)
+(see below) means "fail on backtrack", a repeated (*ACCEPT) of this type means
+"succeed on backtrack".
+.P
+\fBWarning:\fP (*ACCEPT) should not be used within a script run group, because
+it causes an immediate exit from the group, bypassing the script run checking.
.sp
(*FAIL) or (*FAIL:NAME)
.sp
@@ -3264,8 +3470,9 @@ nearest equivalent is the callout feature, as for example in this pattern:
A match with the string "aaaa" always fails, but the callout is taken before
each backtrack happens (in this example, 10 times).
.P
-(*ACCEPT:NAME) and (*FAIL:NAME) behave exactly the same as
-(*MARK:NAME)(*ACCEPT) and (*MARK:NAME)(*FAIL), respectively.
+(*ACCEPT:NAME) and (*FAIL:NAME) behave the same as (*MARK:NAME)(*ACCEPT) and
+(*MARK:NAME)(*FAIL), respectively, that is, a (*MARK) is recorded just before
+the verb acts.
.
.
.SS "Recording which path was taken"
@@ -3277,10 +3484,10 @@ starting point (see (*SKIP) below).
.sp
(*MARK:NAME) or (*:NAME)
.sp
-A name is always required with this verb. There may be as many instances of
-(*MARK) as you like in a pattern, and their names do not have to be unique.
+A name is always required with this verb. For all the other backtracking
+control verbs, a NAME argument is optional.
.P
-When a match succeeds, the name of the last-encountered (*MARK:NAME) on the
+When a match succeeds, the name of the last-encountered mark name on the
matching path is passed back to the caller as described in the section entitled
.\" HTML
.\"
@@ -3290,16 +3497,15 @@ in the
.\" HREF
\fBpcre2api\fP
.\"
-documentation. This applies to all instances of (*MARK), including those inside
-assertions and atomic groups. (There are differences in those cases when
-(*MARK) is used in conjunction with (*SKIP) as described below.)
-.P
-As well as (*MARK), the (*COMMIT), (*PRUNE) and (*THEN) verbs may have
-associated NAME arguments. Whichever is last on the matching path is passed
-back. See below for more details of these other verbs.
+documentation. This applies to all instances of (*MARK) and other verbs,
+including those inside assertions and atomic groups. However, there are
+differences in those cases when (*MARK) is used in conjunction with (*SKIP) as
+described below.
.P
-Here is an example of \fBpcre2test\fP output, where the "mark" modifier
-requests the retrieval and outputting of (*MARK) data:
+The mark name that was last encountered on the matching path is passed back. A
+verb without a NAME argument is ignored for this purpose. Here is an example of
+\fBpcre2test\fP output, where the "mark" modifier requests the retrieval and
+outputting of (*MARK) data:
.sp
re> /X(*MARK:A)Y|X(*MARK:B)Z/mark
data> XY
@@ -3349,7 +3555,7 @@ to the left of the verb. However, when one of these verbs appears inside an
atomic group or in a lookaround assertion that is true, its effect is confined
to that group, because once the group has been matched, there is never any
backtracking into it. Backtracking from beyond an assertion or an atomic group
-ignores the entire group, and seeks a preceeding backtracking point.
+ignores the entire group, and seeks a preceding backtracking point.
.P
These verbs differ in exactly what kind of failure occurs when backtracking
reaches them. The behaviour described below is what happens when the verb is
@@ -3372,8 +3578,8 @@ dynamic anchor, or "I've started, so I must finish."
.P
The behaviour of (*COMMIT:NAME) is not the same as (*MARK:NAME)(*COMMIT). It is
like (*MARK:NAME) in that the name is remembered for passing back to the
-caller. However, (*SKIP:NAME) searches only for names set with (*MARK),
-ignoring those set by (*COMMIT), (*PRUNE) and (*THEN).
+caller. However, (*SKIP:NAME) searches only for names that are set with
+(*MARK), ignoring those set by any of the other backtracking verbs.
.P
If there is more than one backtracking verb in a pattern, a different one that
follows (*COMMIT) may be triggered first, so merely passing (*COMMIT) during a
@@ -3414,7 +3620,7 @@ as (*COMMIT).
The behaviour of (*PRUNE:NAME) is not the same as (*MARK:NAME)(*PRUNE). It is
like (*MARK:NAME) in that the name is remembered for passing back to the
caller. However, (*SKIP:NAME) searches only for names set with (*MARK),
-ignoring those set by (*COMMIT), (*PRUNE) or (*THEN).
+ignoring those set by other backtracking verbs.
.sp
(*SKIP)
.sp
@@ -3432,6 +3638,11 @@ next attempt at "c". Note that a possessive quantifer does not have the same
effect as this example; although it would suppress backtracking during the
first match attempt, the second attempt would start at the second character
instead of skipping on to "c".
+.P
+If (*SKIP) is used to specify a new starting position that is the same as the
+starting position of the current match, or (by being inside a lookbehind)
+earlier, the position specified by (*SKIP) is ignored, and instead the normal
+"bumpalong" occurs.
.sp
(*SKIP:NAME)
.sp
@@ -3467,7 +3678,7 @@ never seen because "a" does not match "b", so the matcher immediately jumps to
the second branch of the pattern.
.P
Note that (*SKIP:NAME) searches only for names set by (*MARK:NAME). It ignores
-names that are set by (*COMMIT:NAME), (*PRUNE:NAME) or (*THEN:NAME).
+names that are set by other backtracking verbs.
.sp
(*THEN) or (*THEN:NAME)
.sp
@@ -3488,32 +3699,30 @@ group. If (*THEN) is not inside an alternation, it acts like (*PRUNE).
The behaviour of (*THEN:NAME) is not the same as (*MARK:NAME)(*THEN). It is
like (*MARK:NAME) in that the name is remembered for passing back to the
caller. However, (*SKIP:NAME) searches only for names set with (*MARK),
-ignoring those set by (*COMMIT), (*PRUNE) and (*THEN).
+ignoring those set by other backtracking verbs.
.P
-A subpattern that does not contain a | character is just a part of the
-enclosing alternative; it is not a nested alternation with only one
-alternative. The effect of (*THEN) extends beyond such a subpattern to the
-enclosing alternative. Consider this pattern, where A, B, etc. are complex
-pattern fragments that do not contain any | characters at this level:
+A group that does not contain a | character is just a part of the enclosing
+alternative; it is not a nested alternation with only one alternative. The
+effect of (*THEN) extends beyond such a group to the enclosing alternative.
+Consider this pattern, where A, B, etc. are complex pattern fragments that do
+not contain any | characters at this level:
.sp
A (B(*THEN)C) | D
.sp
If A and B are matched, but there is a failure in C, matching does not
backtrack into A; instead it moves to the next alternative, that is, D.
-However, if the subpattern containing (*THEN) is given an alternative, it
+However, if the group containing (*THEN) is given an alternative, it
behaves differently:
.sp
A (B(*THEN)C | (*FAIL)) | D
.sp
-The effect of (*THEN) is now confined to the inner subpattern. After a failure
-in C, matching moves to (*FAIL), which causes the whole subpattern to fail
-because there are no more alternatives to try. In this case, matching does now
-backtrack into A.
+The effect of (*THEN) is now confined to the inner group. After a failure in C,
+matching moves to (*FAIL), which causes the whole group to fail because there
+are no more alternatives to try. In this case, matching does backtrack into A.
.P
-Note that a conditional subpattern is not considered as having two
-alternatives, because only one is ever used. In other words, the | character in
-a conditional subpattern has a different meaning. Ignoring white space,
-consider:
+Note that a conditional group is not considered as having two alternatives,
+because only one is ever used. In other words, the | character in a conditional
+group has a different meaning. Ignoring white space, consider:
.sp
^.*? (?(?=a) a | b(*THEN)c )
.sp
@@ -3521,7 +3730,7 @@ If the subject is "ba", this pattern does not match. Because .*? is ungreedy,
it initially matches zero characters. The condition (?=a) then fails, the
character "b" is matched, but "c" is not. At this point, matching does not
backtrack to .*? as might perhaps be expected from the presence of the |
-character. The conditional subpattern is part of the single alternative that
+character. The conditional group is part of the single alternative that
comprises the whole pattern, and so the match fails. (If there was a backtrack
into .*?, allowing it to match "b", the match would succeed.)
.P
@@ -3578,24 +3787,35 @@ acts.
(*FAIL) in any assertion has its normal effect: it forces an immediate
backtrack. The behaviour of the other backtracking verbs depends on whether or
not the assertion is standalone or acting as the condition in a conditional
-subpattern.
+group.
.P
(*ACCEPT) in a standalone positive assertion causes the assertion to succeed
-without any further processing; captured strings and a (*MARK) name (if set)
-are retained. In a standalone negative assertion, (*ACCEPT) causes the
-assertion to fail without any further processing; captured substrings and any
-(*MARK) name are discarded.
+without any further processing; captured strings and a mark name (if set) are
+retained. In a standalone negative assertion, (*ACCEPT) causes the assertion to
+fail without any further processing; captured substrings and any mark name are
+discarded.
.P
If the assertion is a condition, (*ACCEPT) causes the condition to be true for
a positive assertion and false for a negative one; captured substrings are
retained in both cases.
.P
The remaining verbs act only when a later failure causes a backtrack to
-reach them. This means that their effect is confined to the assertion,
-because lookaround assertions are atomic. A backtrack that occurs after an
-assertion is complete does not jump back into the assertion. Note in particular
-that a (*MARK) name that is set in an assertion is not "seen" by an instance of
-(*SKIP:NAME) latter in the pattern.
+reach them. This means that, for the Perl-compatible assertions, their effect
+is confined to the assertion, because Perl lookaround assertions are atomic. A
+backtrack that occurs after such an assertion is complete does not jump back
+into the assertion. Note in particular that a (*MARK) name that is set in an
+assertion is not "seen" by an instance of (*SKIP:NAME) later in the pattern.
+.P
+PCRE2 now supports non-atomic positive assertions, as described in the section
+entitled
+.\" HTML
+.\"
+"Non-atomic assertions"
+.\"
+above. These assertions must be standalone (not used as conditions). They are
+not Perl-compatible. For these assertions, a later backtrack does jump back
+into the assertion, and therefore verbs such as (*COMMIT) can be triggered by
+backtracks from later in the pattern.
.P
The effect of (*THEN) is not allowed to escape beyond an assertion. If there
are no more branches to try, (*THEN) causes a positive assertion to be false,
@@ -3613,25 +3833,24 @@ the assertion to be true, without considering any further alternative branches.
.SS "Backtracking verbs in subroutines"
.rs
.sp
-These behaviours occur whether or not the subpattern is called recursively.
+These behaviours occur whether or not the group is called recursively.
.P
-(*ACCEPT) in a subpattern called as a subroutine causes the subroutine match to
+(*ACCEPT) in a group called as a subroutine causes the subroutine match to
succeed without any further processing. Matching then continues after the
subroutine call. Perl documents this behaviour. Perl's treatment of the other
verbs in subroutines is different in some cases.
.P
-(*FAIL) in a subpattern called as a subroutine has its normal effect: it forces
+(*FAIL) in a group called as a subroutine has its normal effect: it forces
an immediate backtrack.
.P
(*COMMIT), (*SKIP), and (*PRUNE) cause the subroutine match to fail when
-triggered by being backtracked to in a subpattern called as a subroutine. There
-is then a backtrack at the outer level.
+triggered by being backtracked to in a group called as a subroutine. There is
+then a backtrack at the outer level.
.P
(*THEN), when triggered, skips to the next alternative in the innermost
-enclosing group within the subpattern that has alternatives (its normal
-behaviour). However, if there is no such group within the subroutine
-subpattern, the subroutine match fails and there is a backtrack at the outer
-level.
+enclosing group that has alternatives (its normal behaviour). However, if there
+is no such group within the subroutine's group, the subroutine match fails and
+there is a backtrack at the outer level.
.
.
.SH "SEE ALSO"
@@ -3655,6 +3874,6 @@ Cambridge, England.
.rs
.sp
.nf
-Last updated: 04 September 2018
-Copyright (c) 1997-2018 University of Cambridge.
+Last updated: 29 July 2019
+Copyright (c) 1997-2019 University of Cambridge.
.fi
diff --git a/doc/pcre2perform.3 b/doc/pcre2perform.3
index 91ca22a..040369a 100644
--- a/doc/pcre2perform.3
+++ b/doc/pcre2perform.3
@@ -1,4 +1,4 @@
-.TH PCRE2PERFORM 3 "25 April 2018" "PCRE2 10.32"
+.TH PCRE2PERFORM 3 "03 February 2019" "PCRE2 10.33"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH "PCRE2 PERFORMANCE"
@@ -14,9 +14,9 @@ of them.
Patterns are compiled by PCRE2 into a reasonably efficient interpretive code,
so that most simple patterns do not use much memory for storing the compiled
version. However, there is one case where the memory usage of a compiled
-pattern can be unexpectedly large. If a parenthesized subpattern has a
-quantifier with a minimum greater than 1 and/or a limited maximum, the whole
-subpattern is repeated in the compiled code. For example, the pattern
+pattern can be unexpectedly large. If a parenthesized group has a quantifier
+with a minimum greater than 1 and/or a limited maximum, the whole group is
+repeated in the compiled code. For example, the pattern
.sp
(abc|def){2,4}
.sp
@@ -239,6 +239,6 @@ Cambridge, England.
.rs
.sp
.nf
-Last updated: 25 April 2018
-Copyright (c) 1997-2018 University of Cambridge.
+Last updated: 03 February 2019
+Copyright (c) 1997-2019 University of Cambridge.
.fi
diff --git a/doc/pcre2posix.3 b/doc/pcre2posix.3
index 0d8b2c2..35e68e2 100644
--- a/doc/pcre2posix.3
+++ b/doc/pcre2posix.3
@@ -1,4 +1,4 @@
-.TH PCRE2POSIX 3 "15 June 2017" "PCRE2 10.30"
+.TH PCRE2POSIX 3 "30 January 2019" "PCRE2 10.33"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH "SYNOPSIS"
@@ -7,37 +7,60 @@ PCRE2 - Perl-compatible regular expressions (revised API)
.B #include
.PP
.nf
-.B int regcomp(regex_t *\fIpreg\fP, const char *\fIpattern\fP,
+.B int pcre2_regcomp(regex_t *\fIpreg\fP, const char *\fIpattern\fP,
.B " int \fIcflags\fP);"
.sp
-.B int regexec(const regex_t *\fIpreg\fP, const char *\fIstring\fP,
+.B int pcre2_regexec(const regex_t *\fIpreg\fP, const char *\fIstring\fP,
.B " size_t \fInmatch\fP, regmatch_t \fIpmatch\fP[], int \fIeflags\fP);"
.sp
-.B "size_t regerror(int \fIerrcode\fP, const regex_t *\fIpreg\fP,"
+.B "size_t pcre2_regerror(int \fIerrcode\fP, const regex_t *\fIpreg\fP,"
.B " char *\fIerrbuf\fP, size_t \fIerrbuf_size\fP);"
.sp
-.B void regfree(regex_t *\fIpreg\fP);
+.B void pcre2_regfree(regex_t *\fIpreg\fP);
.fi
.
.SH DESCRIPTION
.rs
.sp
This set of functions provides a POSIX-style API for the PCRE2 regular
-expression 8-bit library. See the
+expression 8-bit library. There are no POSIX-style wrappers for PCRE2's 16-bit
+and 32-bit libraries. See the
.\" HREF
\fBpcre2api\fP
.\"
documentation for a description of PCRE2's native API, which contains much
-additional functionality. There are no POSIX-style wrappers for PCRE2's 16-bit
-and 32-bit libraries.
+additional functionality.
.P
-The functions described here are just wrapper functions that ultimately call
-the PCRE2 native API. Their prototypes are defined in the \fBpcre2posix.h\fP
-header file, and on Unix systems the library itself is called
-\fBlibpcre2-posix.a\fP, so can be accessed by adding \fB-lpcre2-posix\fP to the
-command for linking an application that uses them. Because the POSIX functions
-call the native ones, it is also necessary to add \fB-lpcre2-8\fP.
+The functions described here are wrapper functions that ultimately call the
+PCRE2 native API. Their prototypes are defined in the \fBpcre2posix.h\fP header
+file, and they all have unique names starting with \fBpcre2_\fP. However, the
+\fBpcre2posix.h\fP header also contains macro definitions that convert the
+standard POSIX names such \fBregcomp()\fP into \fBpcre2_regcomp()\fP etc. This
+means that a program can use the usual POSIX names without running the risk of
+accidentally linking with POSIX functions from a different library.
.P
+On Unix-like systems the PCRE2 POSIX library is called \fBlibpcre2-posix\fP, so
+can be accessed by adding \fB-lpcre2-posix\fP to the command for linking an
+application. Because the POSIX functions call the native ones, it is also
+necessary to add \fB-lpcre2-8\fP.
+.P
+Although they are not defined as protypes in \fBpcre2posix.h\fP, the library
+does contain functions with the POSIX names \fBregcomp()\fP etc. These simply
+pass their arguments to the PCRE2 functions. These functions are provided for
+backwards compatibility with earlier versions of PCRE2, so that existing
+programs do not have to be recompiled.
+.P
+Calling the header file \fBpcre2posix.h\fP avoids any conflict with other POSIX
+libraries. It can, of course, be renamed or aliased as \fBregex.h\fP, which is
+the "correct" name, if there is no clash. It provides two structure types,
+\fIregex_t\fP for compiled internal forms, and \fIregmatch_t\fP for returning
+captured substrings. It also defines some constants whose names start with
+"REG_"; these are used for setting options and identifying error codes.
+.
+.
+.SH "USING THE POSIX FUNCTIONS"
+.rs
+.sp
Those POSIX option bits that can reasonably be mapped to PCRE2 native options
have been implemented. In addition, the option REG_EXTENDED is defined with the
value zero. This has no effect, but since programs that are written to the
@@ -55,19 +78,15 @@ described below. "POSIX-like in style" means that the API approximates to the
POSIX definition; it is not fully POSIX-compatible, and in multi-unit encoding
domains it is probably even less compatible.
.P
-The header for these functions is supplied as \fBpcre2posix.h\fP to avoid any
-potential clash with other POSIX libraries. It can, of course, be renamed or
-aliased as \fBregex.h\fP, which is the "correct" name. It provides two
-structure types, \fIregex_t\fP for compiled internal forms, and
-\fIregmatch_t\fP for returning captured substrings. It also defines some
-constants whose names start with "REG_"; these are used for setting options and
-identifying error codes.
+The descriptions below use the actual names of the functions, but, as described
+above, the standard POSIX names (without the \fBpcre2_\fP prefix) may also be
+used.
.
.
.SH "COMPILING A PATTERN"
.rs
.sp
-The function \fBregcomp()\fP is called to compile a pattern into an
+The function \fBpcre2_regcomp()\fP is called to compile a pattern into an
internal form. By default, the pattern is a C string terminated by a binary
zero (but see REG_PEND below). The \fIpreg\fP argument is a pointer to a
\fBregex_t\fP structure that is used as a base for storing information about
@@ -104,18 +123,18 @@ REG_UTF. Note that REG_NOSPEC is not part of the POSIX standard.
.sp
REG_NOSUB
.sp
-When a pattern that is compiled with this flag is passed to \fBregexec()\fP for
-matching, the \fInmatch\fP and \fIpmatch\fP arguments are ignored, and no
-captured strings are returned. Versions of the PCRE library prior to 10.22 used
-to set the PCRE2_NO_AUTO_CAPTURE compile option, but this no longer happens
-because it disables the use of backreferences.
+When a pattern that is compiled with this flag is passed to
+\fBpcre2_regexec()\fP for matching, the \fInmatch\fP and \fIpmatch\fP arguments
+are ignored, and no captured strings are returned. Versions of the PCRE library
+prior to 10.22 used to set the PCRE2_NO_AUTO_CAPTURE compile option, but this
+no longer happens because it disables the use of backreferences.
.sp
REG_PEND
.sp
If this option is set, the \fBreg_endp\fP field in the \fIpreg\fP structure
(which has the type const char *) must be set to point to the character beyond
-the end of the pattern before calling \fBregcomp()\fP. The pattern itself may
-now contain binary zeros, which are treated as data characters. Without
+the end of the pattern before calling \fBpcre2_regcomp()\fP. The pattern itself
+may now contain binary zeros, which are treated as data characters. Without
REG_PEND, a binary zero terminates the pattern and the \fBre_endp\fP field is
ignored. This is a GNU extension to the POSIX standard and should be used with
caution in software intended to be portable to other systems.
@@ -148,15 +167,16 @@ Perl way, not the POSIX way. Note that setting PCRE2_MULTILINE has only
newlines are matched by the dot metacharacter (they are not) or by a negative
class such as [^a] (they are).
.P
-The yield of \fBregcomp()\fP is zero on success, and non-zero otherwise. The
-\fIpreg\fP structure is filled in on success, and one other member of the
+The yield of \fBpcre2_regcomp()\fP is zero on success, and non-zero otherwise.
+The \fIpreg\fP structure is filled in on success, and one other member of the
structure (as well as \fIre_endp\fP) is public: \fIre_nsub\fP contains the
number of capturing subpatterns in the regular expression. Various error codes
are defined in the header file.
.P
-NOTE: If the yield of \fBregcomp()\fP is non-zero, you must not attempt to
-use the contents of the \fIpreg\fP structure. If, for example, you pass it to
-\fBregexec()\fP, the result is undefined and your program is likely to crash.
+NOTE: If the yield of \fBpcre2_regcomp()\fP is non-zero, you must not attempt
+to use the contents of the \fIpreg\fP structure. If, for example, you pass it
+to \fBpcre2_regexec()\fP, the result is undefined and your program is likely to
+crash.
.
.
.SH "MATCHING NEWLINE CHARACTERS"
@@ -193,7 +213,7 @@ is no way to stop newline from matching [^a].
Default POSIX newline handling can be obtained by setting PCRE2_DOTALL and
PCRE2_DOLLAR_ENDONLY when calling \fBpcre2_compile()\fP directly, but there is
no way to make PCRE2 behave exactly as for the REG_NEWLINE action. When using
-the POSIX API, passing REG_NEWLINE to PCRE2's \fBregcomp()\fP function
+the POSIX API, passing REG_NEWLINE to PCRE2's \fBpcre2_regcomp()\fP function
causes PCRE2_MULTILINE to be passed to \fBpcre2_compile()\fP, and REG_DOTALL
passes PCRE2_DOTALL. There is no way to pass PCRE2_DOLLAR_ENDONLY.
.
@@ -201,10 +221,10 @@ passes PCRE2_DOTALL. There is no way to pass PCRE2_DOLLAR_ENDONLY.
.SH "MATCHING A PATTERN"
.rs
.sp
-The function \fBregexec()\fP is called to match a compiled pattern \fIpreg\fP
-against a given \fIstring\fP, which is by default terminated by a zero byte
-(but see REG_STARTEND below), subject to the options in \fIeflags\fP. These can
-be:
+The function \fBpcre2_regexec()\fP is called to match a compiled pattern
+\fIpreg\fP against a given \fIstring\fP, which is by default terminated by a
+zero byte (but see REG_STARTEND below), subject to the options in \fIeflags\fP.
+These can be:
.sp
REG_NOTBOL
.sp
@@ -245,7 +265,7 @@ are mutually exclusive; the error REG_INVARG is returned.
.P
If the pattern was compiled with the REG_NOSUB flag, no data about any matched
strings is returned. The \fInmatch\fP and \fIpmatch\fP arguments of
-\fBregexec()\fP are ignored (except possibly as input for REG_STARTEND).
+\fBpcre2_regexec()\fP are ignored (except possibly as input for REG_STARTEND).
.P
The value of \fInmatch\fP may be zero, and the value \fIpmatch\fP may be NULL
(unless REG_STARTEND is set); in both these cases no data about any matched
@@ -268,22 +288,23 @@ header file, of which REG_NOMATCH is the "expected" failure code.
.SH "ERROR MESSAGES"
.rs
.sp
-The \fBregerror()\fP function maps a non-zero errorcode from either
-\fBregcomp()\fP or \fBregexec()\fP to a printable message. If \fIpreg\fP is not
-NULL, the error should have arisen from the use of that structure. A message
-terminated by a binary zero is placed in \fIerrbuf\fP. If the buffer is too
-short, only the first \fIerrbuf_size\fP - 1 characters of the error message are
-used. The yield of the function is the size of buffer needed to hold the whole
-message, including the terminating zero. This value is greater than
-\fIerrbuf_size\fP if the message was truncated.
+The \fBpcre2_regerror()\fP function maps a non-zero errorcode from either
+\fBpcre2_regcomp()\fP or \fBpcre2_regexec()\fP to a printable message. If
+\fIpreg\fP is not NULL, the error should have arisen from the use of that
+structure. A message terminated by a binary zero is placed in \fIerrbuf\fP. If
+the buffer is too short, only the first \fIerrbuf_size\fP - 1 characters of the
+error message are used. The yield of the function is the size of buffer needed
+to hold the whole message, including the terminating zero. This value is
+greater than \fIerrbuf_size\fP if the message was truncated.
.
.
.SH MEMORY USAGE
.rs
.sp
Compiling a regular expression causes memory to be allocated and associated
-with the \fIpreg\fP structure. The function \fBregfree()\fP frees all such
-memory, after which \fIpreg\fP may no longer be used as a compiled expression.
+with the \fIpreg\fP structure. The function \fBpcre2_regfree()\fP frees all
+such memory, after which \fIpreg\fP may no longer be used as a compiled
+expression.
.
.
.SH AUTHOR
@@ -300,6 +321,6 @@ Cambridge, England.
.rs
.sp
.nf
-Last updated: 15 June 2017
-Copyright (c) 1997-2017 University of Cambridge.
+Last updated: 30 January 2019
+Copyright (c) 1997-2019 University of Cambridge.
.fi
diff --git a/doc/pcre2syntax.3 b/doc/pcre2syntax.3
index c392bfb..bbe418a 100644
--- a/doc/pcre2syntax.3
+++ b/doc/pcre2syntax.3
@@ -1,4 +1,4 @@
-.TH PCRE2SYNTAX 3 "02 September 2018" "PCRE2 10.32"
+.TH PCRE2SYNTAX 3 "29 July 2019" "PCRE2 10.34"
.SH NAME
PCRE2 - Perl-compatible regular expressions (revised API)
.SH "PCRE2 REGULAR EXPRESSION SYNTAX SUMMARY"
@@ -22,7 +22,8 @@ documentation. This document contains a quick-reference summary of the syntax.
.SH "ESCAPED CHARACTERS"
.rs
.sp
-This table applies to ASCII and Unicode environments.
+This table applies to ASCII and Unicode environments. An unrecognized escape
+sequence causes an error.
.sp
\ea alarm, that is, the BEL character (hex 07)
\ecx "control-x", where x is any ASCII printing character
@@ -34,12 +35,24 @@ This table applies to ASCII and Unicode environments.
\e0dd character with octal code 0dd
\eddd character with octal code ddd, or backreference
\eo{ddd..} character with octal code ddd..
- \eU "U" if PCRE2_ALT_BSUX is set (otherwise is an error)
\eN{U+hh..} character with Unicode code point hh.. (Unicode mode only)
- \euhhhh character with hex code hhhh (if PCRE2_ALT_BSUX is set)
\exhh character with hex code hh
\ex{hh..} character with hex code hh..
.sp
+If PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX is set ("ALT_BSUX mode"), the
+following are also recognized:
+.sp
+ \eU the character "U"
+ \euhhhh character with hex code hhhh
+ \eu{hh..} character with hex code hh.. but only for EXTRA_ALT_BSUX
+.sp
+When \ex is not followed by {, from zero to two hexadecimal digits are read,
+but in ALT_BSUX mode \ex must be followed by two hexadecimal digits to be
+recognized as a hexadecimal escape; otherwise it matches a literal "x".
+Likewise, if \eu (in ALT_BSUX mode) is not followed by four hexadecimal digits
+or (in EXTRA_ALT_BSUX mode) a sequence of hex digits in curly brackets, it
+matches a literal "u".
+.P
Note that \e0dd is always an octal code. The treatment of backslash followed by
a non-zero digit is complicated; for details see the section
.\" HTML
@@ -54,12 +67,6 @@ documentation, where details of escape processing in EBCDIC environments are
also given. \eN{U+hh..} is synonymous with \ex{hh..} in PCRE2 but is not
supported in EBCDIC environments. Note that \eN not followed by an opening
curly bracket has a different meaning (see below).
-.P
-When \ex is not followed by {, from zero to two hexadecimal digits are read,
-but if PCRE2_ALT_BSUX is set, \ex must be followed by two hexadecimal digits to
-be recognized as a hexadecimal escape; otherwise it matches a literal "x".
-Likewise, if \eu (in ALT_BSUX mode) is not followed by four hexadecimal digits,
-it matches a literal "u".
.
.
.SH "CHARACTER TYPES"
@@ -197,6 +204,7 @@ Dogra,
Duployan,
Egyptian_Hieroglyphs,
Elbasan,
+Elymaic,
Ethiopic,
Georgian,
Glagolitic,
@@ -254,10 +262,12 @@ Mro,
Multani,
Myanmar,
Nabataean,
+Nandinagari,
New_Tai_Lue,
Newa,
Nko,
Nushu,
+Nyakeng_Puachue_Hmong,
Ogham,
Ol_Chiki,
Old_Hungarian,
@@ -308,6 +318,7 @@ Tifinagh,
Tirhuta,
Ugaritic,
Vai,
+Wancho,
Warang_Citi,
Yi,
Zanabazar_Square.
@@ -398,19 +409,24 @@ but some of them use Unicode properties if PCRE2_UCP is set. You can use
.SH "CAPTURING"
.rs
.sp
- (...) capturing group
- (?...) named capturing group (Perl)
- (?'name'...) named capturing group (Perl)
- (?P...) named capturing group (Python)
- (?:...) non-capturing group
- (?|...) non-capturing group; reset group numbers for
- capturing groups in each alternative
+ (...) capture group
+ (?...) named capture group (Perl)
+ (?'name'...) named capture group (Perl)
+ (?P...) named capture group (Python)
+ (?:...) non-capture group
+ (?|...) non-capture group; reset group numbers for
+ capture groups in each alternative
+.sp
+In non-UTF modes, names may contain underscores and ASCII letters and digits;
+in UTF modes, any Unicode letters and Unicode decimal digits are permitted. In
+both cases, a name must not start with a digit.
.
.
.SH "ATOMIC GROUPS"
.rs
.sp
- (?>...) atomic, non-capturing group
+ (?>...) atomic non-capture group
+ (*atomic:...) atomic non-capture group
.
.
.SH "COMMENT"
@@ -438,7 +454,7 @@ of the group.
Unsetting x or xx unsets both. Several options may be set at once, and a
mixture of setting and unsetting such as (?i-x) is allowed, but there may be
only one hyphen. Setting (but no unsetting) is allowed after (?^ for example
-(?^in). An option setting may appear at the start of a non-capturing group, for
+(?^in). An option setting may appear at the start of a non-capture group, for
example (?i:...).
.P
The following are recognized only at the very start of a pattern or after one
@@ -491,12 +507,45 @@ setting with a similar syntax.
.SH "LOOKAHEAD AND LOOKBEHIND ASSERTIONS"
.rs
.sp
- (?=...) positive look ahead
- (?!...) negative look ahead
- (?<=...) positive look behind
- (?name) call subpattern by name (Python)
- \eg call subpattern by name (Oniguruma)
- \eg'name' call subpattern by name (Oniguruma)
- \eg call subpattern by absolute number (Oniguruma)
- \eg'n' call subpattern by absolute number (Oniguruma)
- \eg<+n> call subpattern by relative number (PCRE2 extension)
- \eg'+n' call subpattern by relative number (PCRE2 extension)
- \eg<-n> call subpattern by relative number (PCRE2 extension)
- \eg'-n' call subpattern by relative number (PCRE2 extension)
+ (?n) call subroutine by absolute number
+ (?+n) call subroutine by relative number
+ (?-n) call subroutine by relative number
+ (?&name) call subroutine by name (Perl)
+ (?P>name) call subroutine by name (Python)
+ \eg call subroutine by name (Oniguruma)
+ \eg'name' call subroutine by name (Oniguruma)
+ \eg call subroutine by absolute number (Oniguruma)
+ \eg'n' call subroutine by absolute number (Oniguruma)
+ \eg<+n> call subroutine by relative number (PCRE2 extension)
+ \eg'+n' call subroutine by relative number (PCRE2 extension)
+ \eg<-n> call subroutine by relative number (PCRE2 extension)
+ \eg'-n' call subroutine by relative number (PCRE2 extension)
.
.
.SH "CONDITIONAL PATTERNS"
@@ -550,7 +599,7 @@ Each top-level branch of a look behind must be of a fixed length.
(?(R) overall recursion condition
(?(Rn) specific numbered group recursion condition
(?(R&name) specific named group recursion condition
- (?(DEFINE) define subpattern for reference
+ (?(DEFINE) define groups for reference
(?(VERSION[>]=n.m) test PCRE2 version
(?(assert) assertion condition
.sp
@@ -621,6 +670,6 @@ Cambridge, England.
.rs
.sp
.nf
-Last updated: 02 September 2018
-Copyright (c) 1997-2018 University of Cambridge.
+Last updated: 29 July 2019
+Copyright (c) 1997-2019 University of Cambridge.
.fi
diff --git a/doc/pcre2test.1 b/doc/pcre2test.1
index f590fe1..355dc75 100644
--- a/doc/pcre2test.1
+++ b/doc/pcre2test.1
@@ -1,4 +1,4 @@
-.TH PCRE2TEST 1 "21 July 2018" "PCRE 10.32"
+.TH PCRE2TEST 1 "30 July 2019" "PCRE 10.34"
.SH NAME
pcre2test - a program for testing Perl-compatible regular expressions.
.SH SYNOPSIS
@@ -202,10 +202,16 @@ compiled pattern is given after compilation.
Behave as if each pattern line has the \fBjit\fP modifier; after successful
compilation, each pattern is passed to the just-in-time compiler, if available.
.TP 10
+\fB-jitfast\fP
+Behave as if each pattern line has the \fBjitfast\fP modifier; after
+successful compilation, each pattern is passed to the just-in-time compiler, if
+available, and each subject line is passed directly to the JIT matcher via its
+"fast path".
+.TP 10
\fB-jitverify\fP
Behave as if each pattern line has the \fBjitverify\fP modifier; after
successful compilation, each pattern is passed to the just-in-time compiler, if
-available, and the use of JIT is verified.
+available, and the use of JIT for matching is verified.
.TP 10
\fB-LM\fP
List modifiers: write a list of available pattern and subject modifiers to the
@@ -565,11 +571,14 @@ for a description of the effects of these options.
/s dotall set PCRE2_DOTALL
dupnames set PCRE2_DUPNAMES
endanchored set PCRE2_ENDANCHORED
+ escaped_cr_is_lf set PCRE2_EXTRA_ESCAPED_CR_IS_LF
/x extended set PCRE2_EXTENDED
/xx extended_more set PCRE2_EXTENDED_MORE
+ extra_alt_bsux set PCRE2_EXTRA_ALT_BSUX
firstline set PCRE2_FIRSTLINE
literal set PCRE2_LITERAL
match_line set PCRE2_EXTRA_MATCH_LINE
+ match_invalid_utf set PCRE2_MATCH_INVALID_UTF
match_unset_backref set PCRE2_MATCH_UNSET_BACKREF
match_word set PCRE2_EXTRA_MATCH_WORD
/m multiline set PCRE2_MULTILINE
@@ -671,14 +680,14 @@ information is obtained from the \fBpcre2_pattern_info()\fP function. Here are
some typical examples:
.sp
re> /(?i)(^a|^b)/m,info
- Capturing subpattern count = 1
+ Capture group count = 1
Compile options: multiline
Overall options: caseless multiline
First code unit at start or follows newline
Subject length lower bound = 1
.sp
re> /(?i)abc/info
- Capturing subpattern count = 0
+ Capture group count = 0
Compile options:
Overall options: caseless
First code unit = 'a' (caseless)
@@ -692,7 +701,9 @@ options, the line is omitted. "First code unit" is where any match must start;
if there is more than one they are listed as "starting code units". "Last code
unit" is the last literal code unit that must be present in any match. This is
not necessarily the last character. These lines are omitted if no starting or
-ending code units are recorded.
+ending code units are recorded. The subject length line is omitted when
+\fBno_start_optimize\fP is set because the minimum length is not calculated
+when it can never be used.
.P
The \fBframesize\fP modifier shows the size, in bytes, of the storage frames
used by \fBpcre2_match()\fP for handling backtracking. The size depends on the
@@ -1003,6 +1014,7 @@ process.
aftertext show text after match
allaftertext show text after captures
allcaptures show all captures
+ allvector show the entire ovector
allusedtext show all consulted text
altglobal alternative global matching
/g global global matching
@@ -1010,8 +1022,11 @@ process.
mark show mark values
replace= specify a replacement string
startchar show starting character when relevant
+ substitute_callout use substitution callouts
substitute_extended use PCRE2_SUBSTITUTE_EXTENDED
+ substitute_skip= skip substitution number n
substitute_overflow_length use PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+ substitute_stop= skip substitution number n and greater
substitute_unknown_unset use PCRE2_SUBSTITUTE_UNKNOWN_UNSET
substitute_unset_empty use PCRE2_SUBSTITUTE_UNSET_EMPTY
.sp
@@ -1154,6 +1169,7 @@ pattern.
aftertext show text after match
allaftertext show text after captures
allcaptures show all captures
+ allvector show the entire ovector
allusedtext show all consulted text (non-JIT only)
altglobal alternative global matching
callout_capture show captures at callout time
@@ -1183,8 +1199,11 @@ pattern.
replace= specify a replacement string
startchar show startchar when relevant
startoffset= same as offset=
+ substitute_callout use substitution callouts
substitute_extedded use PCRE2_SUBSTITUTE_EXTENDED
+ substitute_skip= skip substitution number n
substitute_overflow_length use PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+ substitute_stop= skip substitution number n and greater
substitute_unknown_unset use PCRE2_SUBSTITUTE_UNKNOWN_UNSET
substitute_unset_empty use PCRE2_SUBSTITUTE_UNSET_EMPTY
zero_terminate pass the subject as zero-terminated
@@ -1207,22 +1226,27 @@ well as the main matched substring. In each case the remainder is output on the
following line with a plus character following the capture number.
.P
The \fBallusedtext\fP modifier requests that all the text that was consulted
-during a successful pattern match by the interpreter should be shown. This
-feature is not supported for JIT matching, and if requested with JIT it is
-ignored (with a warning message). Setting this modifier affects the output if
-there is a lookbehind at the start of a match, or a lookahead at the end, or if
-\eK is used in the pattern. Characters that precede or follow the start and end
-of the actual match are indicated in the output by '<' or '>' characters
-underneath them. Here is an example:
+during a successful pattern match by the interpreter should be shown, for both
+full and partial matches. This feature is not supported for JIT matching, and
+if requested with JIT it is ignored (with a warning message). Setting this
+modifier affects the output if there is a lookbehind at the start of a match,
+or, for a complete match, a lookahead at the end, or if \eK is used in the
+pattern. Characters that precede or follow the start and end of the actual
+match are indicated in the output by '<' or '>' characters underneath them.
+Here is an example:
.sp
re> /(?<=pqr)abc(?=xyz)/
data> 123pqrabcxyz456\e=allusedtext
0: pqrabcxyz
<<< >>>
+ data> 123pqrabcxy\e=ph,allusedtext
+ Partial match: pqrabcxy
+ <<<
.sp
-This shows that the matched string is "abc", with the preceding and following
-strings "pqr" and "xyz" having been consulted during the match (when processing
-the assertions).
+The first, complete match shows that the matched string is "abc", with the
+preceding and following strings "pqr" and "xyz" having been consulted during
+the match (when processing the assertions). The partial match can indicate only
+the preceding string.
.P
The \fBstartchar\fP modifier requests that the starting character for the match
be indicated, if it is different to the start of the matched string. The only
@@ -1248,10 +1272,28 @@ captured parentheses be output after a match. By default, only those up to the
highest one actually used in the match are output (corresponding to the return
code from \fBpcre2_match()\fP). Groups that did not take part in the match
are output as "". This modifier is not relevant for DFA matching (which
-does no capturing); it is ignored, with a warning message, if present.
+does no capturing) and does not apply when \fBreplace\fP is specified; it is
+ignored, with a warning message, if present.
.
.
-.SS "Testing callouts"
+.SS "Showing the entire ovector, for all outcomes"
+.rs
+.sp
+The \fBallvector\fP modifier requests that the entire ovector be shown,
+whatever the outcome of the match. Compare \fBallcaptures\fP, which shows only
+up to the maximum number of capture groups for the pattern, and then only for a
+successful complete non-DFA match. This modifier, which acts after any match
+result, and also for DFA matching, provides a means of checking that there are
+no unexpected modifications to ovector fields. Before each match attempt, the
+ovector is filled with a special value, and if this is found in both elements
+of a capturing pair, "" is output. After a successful match, this
+applies to all groups after the maximum capture group for the pattern. In other
+cases it applies to the entire ovector. After a partial match, the first two
+elements are the only ones that should be set. After a DFA match, the amount of
+ovector that is used depends on the number of matches that were found.
+.
+.
+.SS "Testing pattern callouts"
.rs
.sp
A callout function is supplied when \fBpcre2test\fP calls the library matching
@@ -1262,6 +1304,12 @@ controlled by various modifiers listed above whose names begin with
.\"
below.
.\"
+Testing callouts from \fBpcre2_substitute()\fP is decribed separately in
+"Testing the substitution function"
+.\" HTML
+.\"
+below.
+.\"
.
.
.SS "Finding all matches in a string"
@@ -1292,8 +1340,8 @@ current character is CR followed by LF, an advance of two characters occurs.
.sp
The \fBcopy\fP and \fBget\fP modifiers can be used to test the
\fBpcre2_substring_copy_xxx()\fP and \fBpcre2_substring_get_xxx()\fP functions.
-They can be given more than once, and each can specify a group name or number,
-for example:
+They can be given more than once, and each can specify a capture group name or
+number, for example:
.sp
abcd\e=copy=1,copy=3,get=G1
.sp
@@ -1312,6 +1360,7 @@ parentheses after each substring, followed by the name when the extraction was
by name.
.
.
+.\" HTML
.SS "Testing the substitution function"
.rs
.sp
@@ -1364,10 +1413,10 @@ The default action of \fBpcre2_substitute()\fP is to return
PCRE2_ERROR_NOMEMORY when the output buffer is too small. However, if the
PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option is set (by using the
\fBsubstitute_overflow_length\fP modifier), \fBpcre2_substitute()\fP continues
-to go through the motions of matching and substituting, in order to compute the
-size of buffer that is required. When this happens, \fBpcre2test\fP shows the
-required buffer length (which includes space for the trailing zero) as part of
-the error message. For example:
+to go through the motions of matching and substituting (but not doing any
+callouts), in order to compute the size of buffer that is required. When this
+happens, \fBpcre2test\fP shows the required buffer length (which includes space
+for the trailing zero) as part of the error message. For example:
.sp
/abc/substitute_overflow_length
123abc123\e=replace=[9]XYZ
@@ -1378,6 +1427,48 @@ matching provokes an error return ("bad option value") from
\fBpcre2_substitute()\fP.
.
.
+.SS "Testing substitute callouts"
+.rs
+.sp
+If the \fBsubstitute_callout\fP modifier is set, a substitution callout
+function is set up. The \fBnull_context\fP modifier must not be set, because
+the address of the callout function is passed in a match context. When the
+callout function is called (after each substitution), details of the the input
+and output strings are output. For example:
+.sp
+ /abc/g,replace=<$0>,substitute_callout
+ abcdefabcpqr
+ 1(1) Old 0 3 "abc" New 0 5 ""
+ 2(1) Old 6 9 "abc" New 8 13 ""
+ 2: defpqr
+.sp
+The first number on each callout line is the count of matches. The
+parenthesized number is the number of pairs that are set in the ovector (that
+is, one more than the number of capturing groups that were set). Then are
+listed the offsets of the old substring, its contents, and the same for the
+replacement.
+.P
+By default, the substitution callout function returns zero, which accepts the
+replacement and causes matching to continue if /g was used. Two further
+modifiers can be used to test other return values. If \fBsubstitute_skip\fP is
+set to a value greater than zero the callout function returns +1 for the match
+of that number, and similarly \fBsubstitute_stop\fP returns -1. These cause the
+replacement to be rejected, and -1 causes no further matching to take place. If
+either of them are set, \fBsubstitute_callout\fP is assumed. For example:
+.sp
+ /abc/g,replace=<$0>,substitute_skip=1
+ abcdefabcpqr
+ 1(1) Old 0 3 "abc" New 0 5 " SKIPPED"
+ 2(1) Old 6 9 "abc" New 6 11 ""
+ 2: abcdefpqr
+ abcdefabcpqr\e=substitute_stop=1
+ 1(1) Old 0 3 "abc" New 0 5 " STOPPED"
+ 1: abcdefabcpqr
+.sp
+If both are set for the same number, stop takes precedence. Only a single skip
+or stop is supported, which is sufficient for testing that the feature works.
+.
+.
.SS "Setting the JIT stack size"
.rs
.sp
@@ -1512,11 +1603,11 @@ passing the replacement string as zero-terminated.
.rs
.sp
Normally, \fBpcre2test\fP passes a context block to \fBpcre2_match()\fP,
-\fBpcre2_dfa_match()\fP or \fBpcre2_jit_match()\fP. If the \fBnull_context\fP
-modifier is set, however, NULL is passed. This is for testing that the matching
-functions behave correctly in this case (they use default values). This
-modifier cannot be used with the \fBfind_limits\fP modifier or when testing the
-substitution function.
+\fBpcre2_dfa_match()\fP, \fBpcre2_jit_match()\fP or \fBpcre2_substitute()\fP.
+If the \fBnull_context\fP modifier is set, however, NULL is passed. This is for
+testing that the matching and substitution functions behave correctly in this
+case (they use default values). This modifier cannot be used with the
+\fBfind_limits\fP or \fBsubstitute_callout\fP modifiers.
.
.
.SH "THE ALTERNATIVE MATCHING FUNCTION"
@@ -1668,7 +1759,7 @@ restart the match with additional subject data by means of the
\fBdfa_restart\fP modifier. For example:
.sp
re> /^\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed$/
- data> 23ja\e=P,dfa
+ data> 23ja\e=ps,dfa
Partial match: 23ja
data> n05\e=dfa,dfa_restart
0: n05
@@ -1982,6 +2073,6 @@ Cambridge, England.
.rs
.sp
.nf
-Last updated: 21 July 2018
-Copyright (c) 1997-2018 University of Cambridge.
+Last updated: 30 July 2019
+Copyright (c) 1997-2019 University of Cambridge.
.fi
diff --git a/doc/pcre2test.txt b/doc/pcre2test.txt
index 44727a7..fcd830f 100644
--- a/doc/pcre2test.txt
+++ b/doc/pcre2test.txt
@@ -13,8 +13,8 @@ SYNOPSIS
but it can also be used for experimenting with regular expressions.
This document describes the features of the test program; for details
of the regular expressions themselves, see the pcre2pattern documenta-
- tion. For details of the PCRE2 library function calls and their
- options, see the pcre2api documentation.
+ tion. For details of the PCRE2 library function calls and their op-
+ tions, see the pcre2api documentation.
The input for pcre2test is a sequence of regular expression patterns
and subject strings to be matched. There are also command lines for
@@ -33,26 +33,26 @@ SYNOPSIS
which are specifically designed for use in conjunction with the test
script and data files that are distributed as part of PCRE2. All the
modifiers are documented here, some without much justification, but
- many of them are unlikely to be of use except when testing the
- libraries.
+ many of them are unlikely to be of use except when testing the li-
+ braries.
PCRE2's 8-BIT, 16-BIT AND 32-BIT LIBRARIES
Different versions of the PCRE2 library can be built to support charac-
ter strings that are encoded in 8-bit, 16-bit, or 32-bit code units.
- One, two, or all three of these libraries may be simultaneously
- installed. The pcre2test program can be used to test all the libraries.
+ One, two, or all three of these libraries may be simultaneously in-
+ stalled. The pcre2test program can be used to test all the libraries.
However, its own input and output are always in 8-bit format. When
testing the 16-bit or 32-bit libraries, patterns and subject strings
- are converted to 16-bit or 32-bit format before being passed to the
- library functions. Results are converted back to 8-bit code units for
+ are converted to 16-bit or 32-bit format before being passed to the li-
+ brary functions. Results are converted back to 8-bit code units for
output.
In the rest of this document, the names of library functions and struc-
- tures are given in generic form, for example, pcre_compile(). The
- actual names used in the libraries have a suffix _8, _16, or _32, as
- appropriate.
+ tures are given in generic form, for example, pcre_compile(). The ac-
+ tual names used in the libraries have a suffix _8, _16, or _32, as ap-
+ propriate.
INPUT ENCODING
@@ -70,18 +70,18 @@ INPUT ENCODING
processed for backslash escapes, which makes it possible to include any
data value in strings that are passed to the library for matching. For
patterns, there is a facility for specifying some or all of the 8-bit
- input characters as hexadecimal pairs, which makes it possible to
- include binary zeros.
+ input characters as hexadecimal pairs, which makes it possible to in-
+ clude binary zeros.
Input for the 16-bit and 32-bit libraries
When testing the 16-bit or 32-bit libraries, there is a need to be able
to generate character code points greater than 255 in the strings that
are passed to the library. For subject lines, backslash escapes can be
- used. In addition, when the utf modifier (see "Setting compilation
- options" below) is set, the pattern and any following subject lines are
- interpreted as UTF-8 strings and translated to UTF-16 or UTF-32 as
- appropriate.
+ used. In addition, when the utf modifier (see "Setting compilation op-
+ tions" below) is set, the pattern and any following subject lines are
+ interpreted as UTF-8 strings and translated to UTF-16 or UTF-32 as ap-
+ propriate.
For non-UTF testing of wide characters, the utf8_input modifier can be
used. This is mutually exclusive with utf, and is allowed only in
@@ -121,8 +121,8 @@ COMMAND LINE OPTIONS
piled.
-AC As for -ac, but in addition behave as if each subject line
- has the callout_extra modifier, that is, show additional
- information from callouts.
+ has the callout_extra modifier, that is, show additional in-
+ formation from callouts.
-b Behave as if each pattern has the fullbincode modifier; the
full internal binary form of the pattern is output after com-
@@ -130,9 +130,9 @@ COMMAND LINE OPTIONS
-C Output the version number of the PCRE2 library, and all
available information about the optional features that are
- included, and then exit with zero exit code. All other
- options are ignored. If both -C and -LM are present, which-
- ever is first is recognized.
+ included, and then exit with zero exit code. All other op-
+ tions are ignored. If both -C and -LM are present, whichever
+ is first is recognized.
-C option Output information about a specific build-time option, then
exit. This functionality is intended for use in scripts such
@@ -190,15 +190,20 @@ COMMAND LINE OPTIONS
successful compilation, each pattern is passed to the just-
in-time compiler, if available.
+ -jitfast Behave as if each pattern line has the jitfast modifier; af-
+ ter successful compilation, each pattern is passed to the
+ just-in-time compiler, if available, and each subject line is
+ passed directly to the JIT matcher via its "fast path".
+
-jitverify
- Behave as if each pattern line has the jitverify modifier;
- after successful compilation, each pattern is passed to the
- just-in-time compiler, if available, and the use of JIT is
- verified.
+ Behave as if each pattern line has the jitverify modifier;
+ after successful compilation, each pattern is passed to the
+ just-in-time compiler, if available, and the use of JIT for
+ matching is verified.
-LM List modifiers: write a list of available pattern and subject
- modifiers to the standard output, then exit with zero exit
- code. All other options are ignored. If both -C and -LM are
+ modifiers to the standard output, then exit with zero exit
+ code. All other options are ignored. If both -C and -LM are
present, whichever is first is recognized.
-pattern modifier-list
@@ -207,25 +212,25 @@ COMMAND LINE OPTIONS
-q Do not output the version number of pcre2test at the start of
execution.
- -S size On Unix-like systems, set the size of the run-time stack to
+ -S size On Unix-like systems, set the size of the run-time stack to
size mebibytes (units of 1024*1024 bytes).
-subject modifier-list
Behave as if each subject line contains the given modifiers.
- -t Run each compile and match many times with a timer, and out-
- put the resulting times per compile or match. When JIT is
- used, separate times are given for the initial compile and
- the JIT compile. You can control the number of iterations
- that are used for timing by following -t with a number (as a
- separate item on the command line). For example, "-t 1000"
+ -t Run each compile and match many times with a timer, and out-
+ put the resulting times per compile or match. When JIT is
+ used, separate times are given for the initial compile and
+ the JIT compile. You can control the number of iterations
+ that are used for timing by following -t with a number (as a
+ separate item on the command line). For example, "-t 1000"
iterates 1000 times. The default is to iterate 500,000 times.
-tm This is like -t except that it times only the matching phase,
not the compile phase.
- -T -TM These behave like -t and -tm, but in addition, at the end of
- a run, the total times for all compiles and matches are out-
+ -T -TM These behave like -t and -tm, but in addition, at the end of
+ a run, the total times for all compiles and matches are out-
put.
-version Output the PCRE2 version number and then exit.
@@ -233,140 +238,140 @@ COMMAND LINE OPTIONS
DESCRIPTION
- If pcre2test is given two filename arguments, it reads from the first
+ If pcre2test is given two filename arguments, it reads from the first
and writes to the second. If the first name is "-", input is taken from
- the standard input. If pcre2test is given only one argument, it reads
+ the standard input. If pcre2test is given only one argument, it reads
from that file and writes to stdout. Otherwise, it reads from stdin and
writes to stdout.
- When pcre2test is built, a configuration option can specify that it
- should be linked with the libreadline or libedit library. When this is
- done, if the input is from a terminal, it is read using the readline()
+ When pcre2test is built, a configuration option can specify that it
+ should be linked with the libreadline or libedit library. When this is
+ done, if the input is from a terminal, it is read using the readline()
function. This provides line-editing and history facilities. The output
from the -help option states whether or not readline() will be used.
- The program handles any number of tests, each of which consists of a
- set of input lines. Each set starts with a regular expression pattern,
+ The program handles any number of tests, each of which consists of a
+ set of input lines. Each set starts with a regular expression pattern,
followed by any number of subject lines to be matched against that pat-
tern. In between sets of test data, command lines that begin with # may
appear. This file format, with some restrictions, can also be processed
- by the perltest.sh script that is distributed with PCRE2 as a means of
+ by the perltest.sh script that is distributed with PCRE2 as a means of
checking that the behaviour of PCRE2 and Perl is the same. For a speci-
fication of perltest.sh, see the comments near its beginning.
When the input is a terminal, pcre2test prompts for each line of input,
- using "re>" to prompt for regular expression patterns, and "data>" to
- prompt for subject lines. Command lines starting with # can be entered
+ using "re>" to prompt for regular expression patterns, and "data>" to
+ prompt for subject lines. Command lines starting with # can be entered
only in response to the "re>" prompt.
- Each subject line is matched separately and independently. If you want
+ Each subject line is matched separately and independently. If you want
to do multi-line matches, you have to use the \n escape sequence (or \r
- or \r\n, etc., depending on the newline setting) in a single line of
- input to encode the newline sequences. There is no limit on the length
- of subject lines; the input buffer is automatically extended if it is
- too small. There are replication features that makes it possible to
- generate long repetitive pattern or subject lines without having to
+ or \r\n, etc., depending on the newline setting) in a single line of
+ input to encode the newline sequences. There is no limit on the length
+ of subject lines; the input buffer is automatically extended if it is
+ too small. There are replication features that makes it possible to
+ generate long repetitive pattern or subject lines without having to
supply them explicitly.
- An empty line or the end of the file signals the end of the subject
- lines for a test, at which point a new pattern or command line is
- expected if there is still input to be read.
+ An empty line or the end of the file signals the end of the subject
+ lines for a test, at which point a new pattern or command line is ex-
+ pected if there is still input to be read.
COMMAND LINES
- In between sets of test data, a line that begins with # is interpreted
+ In between sets of test data, a line that begins with # is interpreted
as a command line. If the first character is followed by white space or
- an exclamation mark, the line is treated as a comment, and ignored.
+ an exclamation mark, the line is treated as a comment, and ignored.
Otherwise, the following commands are recognized:
#forbid_utf
- Subsequent patterns automatically have the PCRE2_NEVER_UTF and
- PCRE2_NEVER_UCP options set, which locks out the use of the PCRE2_UTF
- and PCRE2_UCP options and the use of (*UTF) and (*UCP) at the start of
- patterns. This command also forces an error if a subsequent pattern
- contains any occurrences of \P, \p, or \X, which are still supported
- when PCRE2_UTF is not set, but which require Unicode property support
+ Subsequent patterns automatically have the PCRE2_NEVER_UTF and
+ PCRE2_NEVER_UCP options set, which locks out the use of the PCRE2_UTF
+ and PCRE2_UCP options and the use of (*UTF) and (*UCP) at the start of
+ patterns. This command also forces an error if a subsequent pattern
+ contains any occurrences of \P, \p, or \X, which are still supported
+ when PCRE2_UTF is not set, but which require Unicode property support
to be included in the library.
- This is a trigger guard that is used in test files to ensure that UTF
- or Unicode property tests are not accidentally added to files that are
- used when Unicode support is not included in the library. Setting
- PCRE2_NEVER_UTF and PCRE2_NEVER_UCP as a default can also be obtained
- by the use of #pattern; the difference is that #forbid_utf cannot be
- unset, and the automatic options are not displayed in pattern informa-
+ This is a trigger guard that is used in test files to ensure that UTF
+ or Unicode property tests are not accidentally added to files that are
+ used when Unicode support is not included in the library. Setting
+ PCRE2_NEVER_UTF and PCRE2_NEVER_UCP as a default can also be obtained
+ by the use of #pattern; the difference is that #forbid_utf cannot be
+ unset, and the automatic options are not displayed in pattern informa-
tion, to avoid cluttering up test output.
#load
This command is used to load a set of precompiled patterns from a file,
- as described in the section entitled "Saving and restoring compiled
+ as described in the section entitled "Saving and restoring compiled
patterns" below.
#newline_default []
- When PCRE2 is built, a default newline convention can be specified.
- This determines which characters and/or character pairs are recognized
+ When PCRE2 is built, a default newline convention can be specified.
+ This determines which characters and/or character pairs are recognized
as indicating a newline in a pattern or subject string. The default can
- be overridden when a pattern is compiled. The standard test files con-
- tain tests of various newline conventions, but the majority of the
- tests expect a single linefeed to be recognized as a newline by
- default. Without special action the tests would fail when PCRE2 is com-
+ be overridden when a pattern is compiled. The standard test files con-
+ tain tests of various newline conventions, but the majority of the
+ tests expect a single linefeed to be recognized as a newline by de-
+ fault. Without special action the tests would fail when PCRE2 is com-
piled with either CR or CRLF as the default newline.
The #newline_default command specifies a list of newline types that are
- acceptable as the default. The types must be one of CR, LF, CRLF, ANY-
+ acceptable as the default. The types must be one of CR, LF, CRLF, ANY-
CRLF, ANY, or NUL (in upper or lower case), for example:
#newline_default LF Any anyCRLF
If the default newline is in the list, this command has no effect. Oth-
- erwise, except when testing the POSIX API, a newline modifier that
- specifies the first newline convention in the list (LF in the above
- example) is added to any pattern that does not already have a newline
+ erwise, except when testing the POSIX API, a newline modifier that
+ specifies the first newline convention in the list (LF in the above ex-
+ ample) is added to any pattern that does not already have a newline
modifier. If the newline list is empty, the feature is turned off. This
command is present in a number of the standard test input files.
- When the POSIX API is being tested there is no way to override the
- default newline convention, though it is possible to set the newline
- convention from within the pattern. A warning is given if the posix or
- posix_nosub modifier is used when #newline_default would set a default
+ When the POSIX API is being tested there is no way to override the de-
+ fault newline convention, though it is possible to set the newline con-
+ vention from within the pattern. A warning is given if the posix or
+ posix_nosub modifier is used when #newline_default would set a default
for the non-POSIX API.
#pattern
- This command sets a default modifier list that applies to all subse-
+ This command sets a default modifier list that applies to all subse-
quent patterns. Modifiers on a pattern can change these settings.
#perltest
- The appearance of this line causes all subsequent modifier settings to
+ The appearance of this line causes all subsequent modifier settings to
be checked for compatibility with the perltest.sh script, which is used
- to confirm that Perl gives the same results as PCRE2. Also, apart from
- comment lines, #pattern commands, and #subject commands that set or
- unset "mark", no command lines are permitted, because they and many of
+ to confirm that Perl gives the same results as PCRE2. Also, apart from
+ comment lines, #pattern commands, and #subject commands that set or un-
+ set "mark", no command lines are permitted, because they and many of
the modifiers are specific to pcre2test, and should not be used in test
- files that are also processed by perltest.sh. The #perltest command
+ files that are also processed by perltest.sh. The #perltest command
helps detect tests that are accidentally put in the wrong file.
#pop []
#popcopy []
- These commands are used to manipulate the stack of compiled patterns,
- as described in the section entitled "Saving and restoring compiled
+ These commands are used to manipulate the stack of compiled patterns,
+ as described in the section entitled "Saving and restoring compiled
patterns" below.
#save
- This command is used to save a set of compiled patterns to a file, as
- described in the section entitled "Saving and restoring compiled pat-
+ This command is used to save a set of compiled patterns to a file, as
+ described in the section entitled "Saving and restoring compiled pat-
terns" below.
#subject
- This command sets a default modifier list that applies to all subse-
- quent subject lines. Modifiers on a subject line can change these set-
+ This command sets a default modifier list that applies to all subse-
+ quent subject lines. Modifiers on a subject line can change these set-
tings.
@@ -374,58 +379,58 @@ MODIFIER SYNTAX
Modifier lists are used with both pattern and subject lines. Items in a
list are separated by commas followed by optional white space. Trailing
- whitespace in a modifier list is ignored. Some modifiers may be given
- for both patterns and subject lines, whereas others are valid only for
- one or the other. Each modifier has a long name, for example
- "anchored", and some of them must be followed by an equals sign and a
- value, for example, "offset=12". Values cannot contain comma charac-
- ters, but may contain spaces. Modifiers that do not take values may be
+ whitespace in a modifier list is ignored. Some modifiers may be given
+ for both patterns and subject lines, whereas others are valid only for
+ one or the other. Each modifier has a long name, for example "an-
+ chored", and some of them must be followed by an equals sign and a
+ value, for example, "offset=12". Values cannot contain comma charac-
+ ters, but may contain spaces. Modifiers that do not take values may be
preceded by a minus sign to turn off a previous setting.
A few of the more common modifiers can also be specified as single let-
- ters, for example "i" for "caseless". In documentation, following the
+ ters, for example "i" for "caseless". In documentation, following the
Perl convention, these are written with a slash ("the /i modifier") for
- clarity. Abbreviated modifiers must all be concatenated in the first
- item of a modifier list. If the first item is not recognized as a long
- modifier name, it is interpreted as a sequence of these abbreviations.
+ clarity. Abbreviated modifiers must all be concatenated in the first
+ item of a modifier list. If the first item is not recognized as a long
+ modifier name, it is interpreted as a sequence of these abbreviations.
For example:
/abc/ig,newline=cr,jit=3
- This is a pattern line whose modifier list starts with two one-letter
- modifiers (/i and /g). The lower-case abbreviated modifiers are the
+ This is a pattern line whose modifier list starts with two one-letter
+ modifiers (/i and /g). The lower-case abbreviated modifiers are the
same as used in Perl.
PATTERN SYNTAX
- A pattern line must start with one of the following characters (common
+ A pattern line must start with one of the following characters (common
symbols, excluding pattern meta-characters):
/ ! " ' ` - = _ : ; , % & @ ~
- This is interpreted as the pattern's delimiter. A regular expression
- may be continued over several input lines, in which case the newline
+ This is interpreted as the pattern's delimiter. A regular expression
+ may be continued over several input lines, in which case the newline
characters are included within it. It is possible to include the delim-
iter within the pattern by escaping it with a backslash, for example
/abc\/def/
- If you do this, the escape and the delimiter form part of the pattern,
+ If you do this, the escape and the delimiter form part of the pattern,
but since the delimiters are all non-alphanumeric, this does not affect
- its interpretation. If the terminating delimiter is immediately fol-
+ its interpretation. If the terminating delimiter is immediately fol-
lowed by a backslash, for example,
/abc/\
- then a backslash is added to the end of the pattern. This is done to
- provide a way of testing the error condition that arises if a pattern
+ then a backslash is added to the end of the pattern. This is done to
+ provide a way of testing the error condition that arises if a pattern
finishes with a backslash, because
/abc\/
- is interpreted as the first line of a pattern that starts with "abc/",
- causing pcre2test to read the next line as a continuation of the regu-
+ is interpreted as the first line of a pattern that starts with "abc/",
+ causing pcre2test to read the next line as a continuation of the regu-
lar expression.
A pattern can be followed by a modifier list (details below).
@@ -433,7 +438,7 @@ PATTERN SYNTAX
SUBJECT LINE SYNTAX
- Before each subject line is passed to pcre2_match() or
+ Before each subject line is passed to pcre2_match() or
pcre2_dfa_match(), leading and trailing white space is removed, and the
line is scanned for backslash escapes, unless the subject_literal modi-
fier was set for the pattern. The following provide a means of encoding
@@ -454,23 +459,23 @@ SUBJECT LINE SYNTAX
\x{hh...} hexadecimal character (any number of hex digits)
The use of \x{hh...} is not dependent on the use of the utf modifier on
- the pattern. It is recognized always. There may be any number of hexa-
- decimal digits inside the braces; invalid values provoke error mes-
+ the pattern. It is recognized always. There may be any number of hexa-
+ decimal digits inside the braces; invalid values provoke error mes-
sages.
- Note that \xhh specifies one byte rather than one character in UTF-8
- mode; this makes it possible to construct invalid UTF-8 sequences for
- testing purposes. On the other hand, \x{hh} is interpreted as a UTF-8
- character in UTF-8 mode, generating more than one byte if the value is
- greater than 127. When testing the 8-bit library not in UTF-8 mode,
+ Note that \xhh specifies one byte rather than one character in UTF-8
+ mode; this makes it possible to construct invalid UTF-8 sequences for
+ testing purposes. On the other hand, \x{hh} is interpreted as a UTF-8
+ character in UTF-8 mode, generating more than one byte if the value is
+ greater than 127. When testing the 8-bit library not in UTF-8 mode,
\x{hh} generates one byte for values less than 256, and causes an error
for greater values.
In UTF-16 mode, all 4-digit \x{hhhh} values are accepted. This makes it
possible to construct invalid UTF-16 sequences for testing purposes.
- In UTF-32 mode, all 4- to 8-digit \x{...} values are accepted. This
- makes it possible to construct invalid UTF-32 sequences for testing
+ In UTF-32 mode, all 4- to 8-digit \x{...} values are accepted. This
+ makes it possible to construct invalid UTF-32 sequences for testing
purposes.
There is a special backslash sequence that specifies replication of one
@@ -478,31 +483,31 @@ SUBJECT LINE SYNTAX
\[]{}
- This makes it possible to test long strings without having to provide
+ This makes it possible to test long strings without having to provide
them as part of the file. For example:
\[abc]{4}
- is converted to "abcabcabcabc". This feature does not support nesting.
+ is converted to "abcabcabcabc". This feature does not support nesting.
To include a closing square bracket in the characters, code it as \x5D.
- A backslash followed by an equals sign marks the end of the subject
+ A backslash followed by an equals sign marks the end of the subject
string and the start of a modifier list. For example:
abc\=notbol,notempty
- If the subject string is empty and \= is followed by whitespace, the
- line is treated as a comment line, and is not used for matching. For
+ If the subject string is empty and \= is followed by whitespace, the
+ line is treated as a comment line, and is not used for matching. For
example:
\= This is a comment.
abc\= This is an invalid modifier list.
- A backslash followed by any other non-alphanumeric character just
- escapes that character. A backslash followed by anything else causes an
- error. However, if the very last character in the line is a backslash
- (and there is no modifier list), it is ignored. This gives a way of
- passing an empty line as data, since a real empty line terminates the
+ A backslash followed by any other non-alphanumeric character just es-
+ capes that character. A backslash followed by anything else causes an
+ error. However, if the very last character in the line is a backslash
+ (and there is no modifier list), it is ignored. This gives a way of
+ passing an empty line as data, since a real empty line terminates the
data input.
If the subject_literal modifier is set for a pattern, all subject lines
@@ -513,23 +518,23 @@ SUBJECT LINE SYNTAX
PATTERN MODIFIERS
- There are several types of modifier that can appear in pattern lines.
+ There are several types of modifier that can appear in pattern lines.
Except where noted below, they may also be used in #pattern commands. A
- pattern's modifier list can add to or override default modifiers that
+ pattern's modifier list can add to or override default modifiers that
were set by a previous #pattern command.
Setting compilation options
- The following modifiers set options for pcre2_compile(). Most of them
- set bits in the options argument of that function, but those whose
+ The following modifiers set options for pcre2_compile(). Most of them
+ set bits in the options argument of that function, but those whose
names start with PCRE2_EXTRA are additional options that are set in the
- compile context. For the main options, there are some single-letter
- abbreviations that are the same as Perl options. There is special han-
- dling for /x: if a second x is present, PCRE2_EXTENDED is converted
- into PCRE2_EXTENDED_MORE as in Perl. A third appearance adds
- PCRE2_EXTENDED as well, though this makes no difference to the way
- pcre2_compile() behaves. See pcre2api for a description of the effects
- of these options.
+ compile context. For the main options, there are some single-letter ab-
+ breviations that are the same as Perl options. There is special han-
+ dling for /x: if a second x is present, PCRE2_EXTENDED is converted
+ into PCRE2_EXTENDED_MORE as in Perl. A third appearance adds PCRE2_EX-
+ TENDED as well, though this makes no difference to the way pcre2_com-
+ pile() behaves. See pcre2api for a description of the effects of these
+ options.
allow_empty_class set PCRE2_ALLOW_EMPTY_CLASS
allow_surrogate_escapes set PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES
@@ -544,11 +549,14 @@ PATTERN MODIFIERS
/s dotall set PCRE2_DOTALL
dupnames set PCRE2_DUPNAMES
endanchored set PCRE2_ENDANCHORED
+ escaped_cr_is_lf set PCRE2_EXTRA_ESCAPED_CR_IS_LF
/x extended set PCRE2_EXTENDED
/xx extended_more set PCRE2_EXTENDED_MORE
+ extra_alt_bsux set PCRE2_EXTRA_ALT_BSUX
firstline set PCRE2_FIRSTLINE
literal set PCRE2_LITERAL
match_line set PCRE2_EXTRA_MATCH_LINE
+ match_invalid_utf set PCRE2_MATCH_INVALID_UTF
match_unset_backref set PCRE2_MATCH_UNSET_BACKREF
match_word set PCRE2_EXTRA_MATCH_WORD
/m multiline set PCRE2_MULTILINE
@@ -566,17 +574,17 @@ PATTERN MODIFIERS
utf set PCRE2_UTF
As well as turning on the PCRE2_UTF option, the utf modifier causes all
- non-printing characters in output strings to be printed using the
- \x{hh...} notation. Otherwise, those less than 0x100 are output in hex
- without the curly brackets. Setting utf in 16-bit or 32-bit mode also
- causes pattern and subject strings to be translated to UTF-16 or
+ non-printing characters in output strings to be printed using the
+ \x{hh...} notation. Otherwise, those less than 0x100 are output in hex
+ without the curly brackets. Setting utf in 16-bit or 32-bit mode also
+ causes pattern and subject strings to be translated to UTF-16 or
UTF-32, respectively, before being passed to library functions.
Setting compilation controls
- The following modifiers affect the compilation process or request
- information about the pattern. There are single-letter abbreviations
- for some that are heavily used in the test files.
+ The following modifiers affect the compilation process or request in-
+ formation about the pattern. There are single-letter abbreviations for
+ some that are heavily used in the test files.
bsr=[anycrlf|unicode] specify \R handling
/B bincode show binary code without lengths
@@ -613,161 +621,163 @@ PATTERN MODIFIERS
Newline and \R handling
- The bsr modifier specifies what \R in a pattern should match. If it is
- set to "anycrlf", \R matches CR, LF, or CRLF only. If it is set to
- "unicode", \R matches any Unicode newline sequence. The default can be
+ The bsr modifier specifies what \R in a pattern should match. If it is
+ set to "anycrlf", \R matches CR, LF, or CRLF only. If it is set to
+ "unicode", \R matches any Unicode newline sequence. The default can be
specified when PCRE2 is built; if it is not, the default is set to Uni-
code.
- The newline modifier specifies which characters are to be interpreted
+ The newline modifier specifies which characters are to be interpreted
as newlines, both in the pattern and in subject lines. The type must be
one of CR, LF, CRLF, ANYCRLF, ANY, or NUL (in upper or lower case).
Information about a pattern
- The debug modifier is a shorthand for info,fullbincode, requesting all
+ The debug modifier is a shorthand for info,fullbincode, requesting all
available information.
The bincode modifier causes a representation of the compiled code to be
- output after compilation. This information does not contain length and
+ output after compilation. This information does not contain length and
offset values, which ensures that the same output is generated for dif-
- ferent internal link sizes and different code unit widths. By using
- bincode, the same regression tests can be used in different environ-
+ ferent internal link sizes and different code unit widths. By using
+ bincode, the same regression tests can be used in different environ-
ments.
- The fullbincode modifier, by contrast, does include length and offset
- values. This is used in a few special tests that run only for specific
+ The fullbincode modifier, by contrast, does include length and offset
+ values. This is used in a few special tests that run only for specific
code unit widths and link sizes, and is also useful for one-off tests.
- The info modifier requests information about the compiled pattern
- (whether it is anchored, has a fixed first character, and so on). The
- information is obtained from the pcre2_pattern_info() function. Here
+ The info modifier requests information about the compiled pattern
+ (whether it is anchored, has a fixed first character, and so on). The
+ information is obtained from the pcre2_pattern_info() function. Here
are some typical examples:
re> /(?i)(^a|^b)/m,info
- Capturing subpattern count = 1
+ Capture group count = 1
Compile options: multiline
Overall options: caseless multiline
First code unit at start or follows newline
Subject length lower bound = 1
re> /(?i)abc/info
- Capturing subpattern count = 0
+ Capture group count = 0
Compile options:
Overall options: caseless
First code unit = 'a' (caseless)
Last code unit = 'c' (caseless)
Subject length lower bound = 3
- "Compile options" are those specified by modifiers; "overall options"
- have added options that are taken or deduced from the pattern. If both
- sets of options are the same, just a single "options" line is output;
- if there are no options, the line is omitted. "First code unit" is
- where any match must start; if there is more than one they are listed
- as "starting code units". "Last code unit" is the last literal code
- unit that must be present in any match. This is not necessarily the
- last character. These lines are omitted if no starting or ending code
- units are recorded.
-
- The framesize modifier shows the size, in bytes, of the storage frames
- used by pcre2_match() for handling backtracking. The size depends on
+ "Compile options" are those specified by modifiers; "overall options"
+ have added options that are taken or deduced from the pattern. If both
+ sets of options are the same, just a single "options" line is output;
+ if there are no options, the line is omitted. "First code unit" is
+ where any match must start; if there is more than one they are listed
+ as "starting code units". "Last code unit" is the last literal code
+ unit that must be present in any match. This is not necessarily the
+ last character. These lines are omitted if no starting or ending code
+ units are recorded. The subject length line is omitted when
+ no_start_optimize is set because the minimum length is not calculated
+ when it can never be used.
+
+ The framesize modifier shows the size, in bytes, of the storage frames
+ used by pcre2_match() for handling backtracking. The size depends on
the number of capturing parentheses in the pattern.
- The callout_info modifier requests information about all the callouts
+ The callout_info modifier requests information about all the callouts
in the pattern. A list of them is output at the end of any other infor-
mation that is requested. For each callout, either its number or string
is given, followed by the item that follows it in the pattern.
Passing a NULL context
- Normally, pcre2test passes a context block to pcre2_compile(). If the
- null_context modifier is set, however, NULL is passed. This is for
- testing that pcre2_compile() behaves correctly in this case (it uses
+ Normally, pcre2test passes a context block to pcre2_compile(). If the
+ null_context modifier is set, however, NULL is passed. This is for
+ testing that pcre2_compile() behaves correctly in this case (it uses
default values).
Specifying pattern characters in hexadecimal
- The hex modifier specifies that the characters of the pattern, except
- for substrings enclosed in single or double quotes, are to be inter-
- preted as pairs of hexadecimal digits. This feature is provided as a
+ The hex modifier specifies that the characters of the pattern, except
+ for substrings enclosed in single or double quotes, are to be inter-
+ preted as pairs of hexadecimal digits. This feature is provided as a
way of creating patterns that contain binary zeros and other non-print-
- ing characters. White space is permitted between pairs of digits. For
+ ing characters. White space is permitted between pairs of digits. For
example, this pattern contains three characters:
/ab 32 59/hex
- Parts of such a pattern are taken literally if quoted. This pattern
- contains nine characters, only two of which are specified in hexadeci-
+ Parts of such a pattern are taken literally if quoted. This pattern
+ contains nine characters, only two of which are specified in hexadeci-
mal:
/ab "literal" 32/hex
- Either single or double quotes may be used. There is no way of includ-
- ing the delimiter within a substring. The hex and expand modifiers are
+ Either single or double quotes may be used. There is no way of includ-
+ ing the delimiter within a substring. The hex and expand modifiers are
mutually exclusive.
Specifying the pattern's length
By default, patterns are passed to the compiling functions as zero-ter-
- minated strings but can be passed by length instead of being zero-ter-
- minated. The use_length modifier causes this to happen. Using a length
- happens automatically (whether or not use_length is set) when hex is
- set, because patterns specified in hexadecimal may contain binary
- zeros.
+ minated strings but can be passed by length instead of being zero-ter-
+ minated. The use_length modifier causes this to happen. Using a length
+ happens automatically (whether or not use_length is set) when hex is
+ set, because patterns specified in hexadecimal may contain binary ze-
+ ros.
If hex or use_length is used with the POSIX wrapper API (see "Using the
- POSIX wrapper API" below), the REG_PEND extension is used to pass the
+ POSIX wrapper API" below), the REG_PEND extension is used to pass the
pattern's length.
Specifying wide characters in 16-bit and 32-bit modes
In 16-bit and 32-bit modes, all input is automatically treated as UTF-8
- and translated to UTF-16 or UTF-32 when the utf modifier is set. For
+ and translated to UTF-16 or UTF-32 when the utf modifier is set. For
testing the 16-bit and 32-bit libraries in non-UTF mode, the utf8_input
- modifier can be used. It is mutually exclusive with utf. Input lines
+ modifier can be used. It is mutually exclusive with utf. Input lines
are interpreted as UTF-8 as a means of specifying wide characters. More
details are given in "Input encoding" above.
Generating long repetitive patterns
- Some tests use long patterns that are very repetitive. Instead of cre-
- ating a very long input line for such a pattern, you can use a special
- repetition feature, similar to the one described for subject lines
- above. If the expand modifier is present on a pattern, parts of the
+ Some tests use long patterns that are very repetitive. Instead of cre-
+ ating a very long input line for such a pattern, you can use a special
+ repetition feature, similar to the one described for subject lines
+ above. If the expand modifier is present on a pattern, parts of the
pattern that have the form
\[]{}
are expanded before the pattern is passed to pcre2_compile(). For exam-
ple, \[AB]{6000} is expanded to "ABAB..." 6000 times. This construction
- cannot be nested. An initial "\[" sequence is recognized only if "]{"
- followed by decimal digits and "}" is found later in the pattern. If
+ cannot be nested. An initial "\[" sequence is recognized only if "]{"
+ followed by decimal digits and "}" is found later in the pattern. If
not, the characters remain in the pattern unaltered. The expand and hex
modifiers are mutually exclusive.
- If part of an expanded pattern looks like an expansion, but is really
+ If part of an expanded pattern looks like an expansion, but is really
part of the actual pattern, unwanted expansion can be avoided by giving
two values in the quantifier. For example, \[AB]{6000,6000} is not rec-
ognized as an expansion item.
- If the info modifier is set on an expanded pattern, the result of the
+ If the info modifier is set on an expanded pattern, the result of the
expansion is included in the information that is output.
JIT compilation
- Just-in-time (JIT) compiling is a heavyweight optimization that can
- greatly speed up pattern matching. See the pcre2jit documentation for
- details. JIT compiling happens, optionally, after a pattern has been
- successfully compiled into an internal form. The JIT compiler converts
+ Just-in-time (JIT) compiling is a heavyweight optimization that can
+ greatly speed up pattern matching. See the pcre2jit documentation for
+ details. JIT compiling happens, optionally, after a pattern has been
+ successfully compiled into an internal form. The JIT compiler converts
this to optimized machine code. It needs to know whether the match-time
options PCRE2_PARTIAL_HARD and PCRE2_PARTIAL_SOFT are going to be used,
- because different code is generated for the different cases. See the
- partial modifier in "Subject Modifiers" below for details of how these
+ because different code is generated for the different cases. See the
+ partial modifier in "Subject Modifiers" below for details of how these
options are specified for each match attempt.
- JIT compilation is requested by the jit pattern modifier, which may
- optionally be followed by an equals sign and a number in the range 0 to
- 7. The three bits that make up the number specify which of the three
+ JIT compilation is requested by the jit pattern modifier, which may op-
+ tionally be followed by an equals sign and a number in the range 0 to
+ 7. The three bits that make up the number specify which of the three
JIT operating modes are to be compiled:
1 compile JIT code for non-partial matching
@@ -784,31 +794,31 @@ PATTERN MODIFIERS
6 soft and hard partial matching only
7 all three modes
- If no number is given, 7 is assumed. The phrase "partial matching"
+ If no number is given, 7 is assumed. The phrase "partial matching"
means a call to pcre2_match() with either the PCRE2_PARTIAL_SOFT or the
- PCRE2_PARTIAL_HARD option set. Note that such a call may return a com-
+ PCRE2_PARTIAL_HARD option set. Note that such a call may return a com-
plete match; the options enable the possibility of a partial match, but
- do not require it. Note also that if you request JIT compilation only
- for partial matching (for example, jit=2) but do not set the partial
- modifier on a subject line, that match will not use JIT code because
+ do not require it. Note also that if you request JIT compilation only
+ for partial matching (for example, jit=2) but do not set the partial
+ modifier on a subject line, that match will not use JIT code because
none was compiled for non-partial matching.
- If JIT compilation is successful, the compiled JIT code will automati-
- cally be used when an appropriate type of match is run, except when
- incompatible run-time options are specified. For more details, see the
- pcre2jit documentation. See also the jitstack modifier below for a way
+ If JIT compilation is successful, the compiled JIT code will automati-
+ cally be used when an appropriate type of match is run, except when in-
+ compatible run-time options are specified. For more details, see the
+ pcre2jit documentation. See also the jitstack modifier below for a way
of setting the size of the JIT stack.
- If the jitfast modifier is specified, matching is done using the JIT
- "fast path" interface, pcre2_jit_match(), which skips some of the san-
- ity checks that are done by pcre2_match(), and of course does not work
- when JIT is not supported. If jitfast is specified without jit, jit=7
+ If the jitfast modifier is specified, matching is done using the JIT
+ "fast path" interface, pcre2_jit_match(), which skips some of the san-
+ ity checks that are done by pcre2_match(), and of course does not work
+ when JIT is not supported. If jitfast is specified without jit, jit=7
is assumed.
- If the jitverify modifier is specified, information about the compiled
- pattern shows whether JIT compilation was or was not successful. If
- jitverify is specified without jit, jit=7 is assumed. If JIT compila-
- tion is successful when jitverify is set, the text "(JIT)" is added to
+ If the jitverify modifier is specified, information about the compiled
+ pattern shows whether JIT compilation was or was not successful. If
+ jitverify is specified without jit, jit=7 is assumed. If JIT compila-
+ tion is successful when jitverify is set, the text "(JIT)" is added to
the first output line after a match or non match when JIT-compiled code
was actually used in the match.
@@ -819,19 +829,19 @@ PATTERN MODIFIERS
/pattern/locale=fr_FR
The given locale is set, pcre2_maketables() is called to build a set of
- character tables for the locale, and this is then passed to pcre2_com-
- pile() when compiling the regular expression. The same tables are used
- when matching the following subject lines. The locale modifier applies
+ character tables for the locale, and this is then passed to pcre2_com-
+ pile() when compiling the regular expression. The same tables are used
+ when matching the following subject lines. The locale modifier applies
only to the pattern on which it appears, but can be given in a #pattern
- command if a default is needed. Setting a locale and alternate charac-
+ command if a default is needed. Setting a locale and alternate charac-
ter tables are mutually exclusive.
Showing pattern memory
The memory modifier causes the size in bytes of the memory used to hold
- the compiled pattern to be output. This does not include the size of
- the pcre2_code block; it is just the actual compiled data. If the pat-
- tern is subsequently passed to the JIT compiler, the size of the JIT
+ the compiled pattern to be output. This does not include the size of
+ the pcre2_code block; it is just the actual compiled data. If the pat-
+ tern is subsequently passed to the JIT compiler, the size of the JIT
compiled code is also output. Here is an example:
re> /a(b)c/jit,memory
@@ -841,27 +851,27 @@ PATTERN MODIFIERS
Limiting nested parentheses
- The parens_nest_limit modifier sets a limit on the depth of nested
- parentheses in a pattern. Breaching the limit causes a compilation
- error. The default for the library is set when PCRE2 is built, but
- pcre2test sets its own default of 220, which is required for running
+ The parens_nest_limit modifier sets a limit on the depth of nested
+ parentheses in a pattern. Breaching the limit causes a compilation er-
+ ror. The default for the library is set when PCRE2 is built, but
+ pcre2test sets its own default of 220, which is required for running
the standard test suite.
Limiting the pattern length
- The max_pattern_length modifier sets a limit, in code units, to the
+ The max_pattern_length modifier sets a limit, in code units, to the
length of pattern that pcre2_compile() will accept. Breaching the limit
- causes a compilation error. The default is the largest number a
+ causes a compilation error. The default is the largest number a
PCRE2_SIZE variable can hold (essentially unlimited).
Using the POSIX wrapper API
- The posix and posix_nosub modifiers cause pcre2test to call PCRE2 via
- the POSIX wrapper API rather than its native API. When posix_nosub is
- used, the POSIX option REG_NOSUB is passed to regcomp(). The POSIX
- wrapper supports only the 8-bit library. Note that it does not imply
+ The posix and posix_nosub modifiers cause pcre2test to call PCRE2 via
+ the POSIX wrapper API rather than its native API. When posix_nosub is
+ used, the POSIX option REG_NOSUB is passed to regcomp(). The POSIX
+ wrapper supports only the 8-bit library. Note that it does not imply
POSIX matching semantics; for more detail see the pcre2posix documenta-
- tion. The following pattern modifiers set options for the regcomp()
+ tion. The following pattern modifiers set options for the regcomp()
function:
caseless REG_ICASE
@@ -871,39 +881,39 @@ PATTERN MODIFIERS
ucp REG_UCP ) the POSIX standard
utf REG_UTF8 )
- The regerror_buffsize modifier specifies a size for the error buffer
- that is passed to regerror() in the event of a compilation error. For
+ The regerror_buffsize modifier specifies a size for the error buffer
+ that is passed to regerror() in the event of a compilation error. For
example:
/abc/posix,regerror_buffsize=20
- This provides a means of testing the behaviour of regerror() when the
- buffer is too small for the error message. If this modifier has not
+ This provides a means of testing the behaviour of regerror() when the
+ buffer is too small for the error message. If this modifier has not
been set, a large buffer is used.
- The aftertext and allaftertext subject modifiers work as described
- below. All other modifiers are either ignored, with a warning message,
- or cause an error.
+ The aftertext and allaftertext subject modifiers work as described be-
+ low. All other modifiers are either ignored, with a warning message, or
+ cause an error.
- The pattern is passed to regcomp() as a zero-terminated string by
- default, but if the use_length or hex modifiers are set, the REG_PEND
- extension is used to pass it by length.
+ The pattern is passed to regcomp() as a zero-terminated string by de-
+ fault, but if the use_length or hex modifiers are set, the REG_PEND ex-
+ tension is used to pass it by length.
Testing the stack guard feature
- The stackguard modifier is used to test the use of pcre2_set_com-
- pile_recursion_guard(), a function that is provided to enable stack
- availability to be checked during compilation (see the pcre2api docu-
- mentation for details). If the number specified by the modifier is
+ The stackguard modifier is used to test the use of pcre2_set_com-
+ pile_recursion_guard(), a function that is provided to enable stack
+ availability to be checked during compilation (see the pcre2api docu-
+ mentation for details). If the number specified by the modifier is
greater than zero, pcre2_set_compile_recursion_guard() is called to set
- up callback from pcre2_compile() to a local function. The argument it
- receives is the current nesting parenthesis depth; if this is greater
+ up callback from pcre2_compile() to a local function. The argument it
+ receives is the current nesting parenthesis depth; if this is greater
than the value given by the modifier, non-zero is returned, causing the
compilation to be aborted.
Using alternative character tables
- The value specified for the tables modifier must be one of the digits
+ The value specified for the tables modifier must be one of the digits
0, 1, or 2. It causes a specific set of built-in character tables to be
passed to pcre2_compile(). This is used in the PCRE2 tests to check be-
haviour with different character tables. The digit specifies the tables
@@ -914,21 +924,22 @@ PATTERN MODIFIERS
pcre2_chartables.c.dist
2 a set of tables defining ISO 8859 characters
- In table 2, some characters whose codes are greater than 128 are iden-
- tified as letters, digits, spaces, etc. Setting alternate character
- tables and a locale are mutually exclusive.
+ In table 2, some characters whose codes are greater than 128 are iden-
+ tified as letters, digits, spaces, etc. Setting alternate character ta-
+ bles and a locale are mutually exclusive.
Setting certain match controls
The following modifiers are really subject modifiers, and are described
- under "Subject Modifiers" below. However, they may be included in a
- pattern's modifier list, in which case they are applied to every sub-
- ject line that is processed with that pattern. These modifiers do not
+ under "Subject Modifiers" below. However, they may be included in a
+ pattern's modifier list, in which case they are applied to every sub-
+ ject line that is processed with that pattern. These modifiers do not
affect the compilation process.
aftertext show text after match
allaftertext show text after captures
allcaptures show all captures
+ allvector show the entire ovector
allusedtext show all consulted text
altglobal alternative global matching
/g global global matching
@@ -936,44 +947,47 @@ PATTERN MODIFIERS
mark show mark values
replace= specify a replacement string
startchar show starting character when relevant
+ substitute_callout use substitution callouts
substitute_extended use PCRE2_SUBSTITUTE_EXTENDED
+ substitute_skip= skip substitution number n
substitute_overflow_length use PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+ substitute_stop= skip substitution number n and greater
substitute_unknown_unset use PCRE2_SUBSTITUTE_UNKNOWN_UNSET
substitute_unset_empty use PCRE2_SUBSTITUTE_UNSET_EMPTY
- These modifiers may not appear in a #pattern command. If you want them
+ These modifiers may not appear in a #pattern command. If you want them
as defaults, set them in a #subject command.
Specifying literal subject lines
- If the subject_literal modifier is present on a pattern, all the sub-
+ If the subject_literal modifier is present on a pattern, all the sub-
ject lines that it matches are taken as literal strings, with no inter-
- pretation of backslashes. It is not possible to set subject modifiers
- on such lines, but any that are set as defaults by a #subject command
+ pretation of backslashes. It is not possible to set subject modifiers
+ on such lines, but any that are set as defaults by a #subject command
are recognized.
Saving a compiled pattern
- When a pattern with the push modifier is successfully compiled, it is
- pushed onto a stack of compiled patterns, and pcre2test expects the
- next line to contain a new pattern (or a command) instead of a subject
+ When a pattern with the push modifier is successfully compiled, it is
+ pushed onto a stack of compiled patterns, and pcre2test expects the
+ next line to contain a new pattern (or a command) instead of a subject
line. This facility is used when saving compiled patterns to a file, as
- described in the section entitled "Saving and restoring compiled pat-
- terns" below. If pushcopy is used instead of push, a copy of the com-
- piled pattern is stacked, leaving the original as current, ready to
- match the following input lines. This provides a way of testing the
- pcre2_code_copy() function. The push and pushcopy modifiers are
- incompatible with compilation modifiers such as global that act at
- match time. Any that are specified are ignored (for the stacked copy),
- with a warning message, except for replace, which causes an error. Note
- that jitverify, which is allowed, does not carry through to any subse-
- quent matching that uses a stacked pattern.
+ described in the section entitled "Saving and restoring compiled pat-
+ terns" below. If pushcopy is used instead of push, a copy of the com-
+ piled pattern is stacked, leaving the original as current, ready to
+ match the following input lines. This provides a way of testing the
+ pcre2_code_copy() function. The push and pushcopy modifiers are in-
+ compatible with compilation modifiers such as global that act at match
+ time. Any that are specified are ignored (for the stacked copy), with a
+ warning message, except for replace, which causes an error. Note that
+ jitverify, which is allowed, does not carry through to any subsequent
+ matching that uses a stacked pattern.
Testing foreign pattern conversion
- The experimental foreign pattern conversion functions in PCRE2 can be
- tested by setting the convert modifier. Its argument is a colon-sepa-
- rated list of options, which set the equivalent option for the
+ The experimental foreign pattern conversion functions in PCRE2 can be
+ tested by setting the convert modifier. Its argument is a colon-sepa-
+ rated list of options, which set the equivalent option for the
pcre2_pattern_convert() function:
glob PCRE2_CONVERT_GLOB
@@ -985,19 +999,19 @@ PATTERN MODIFIERS
The "unset" value is useful for turning off a default that has been set
by a #pattern command. When one of these options is set, the input pat-
- tern is passed to pcre2_pattern_convert(). If the conversion is suc-
- cessful, the result is reflected in the output and then passed to
+ tern is passed to pcre2_pattern_convert(). If the conversion is suc-
+ cessful, the result is reflected in the output and then passed to
pcre2_compile(). The normal utf and no_utf_check options, if set, cause
- the PCRE2_CONVERT_UTF and PCRE2_CONVERT_NO_UTF_CHECK options to be
+ the PCRE2_CONVERT_UTF and PCRE2_CONVERT_NO_UTF_CHECK options to be
passed to pcre2_pattern_convert().
By default, the conversion function is allowed to allocate a buffer for
- its output. However, if the convert_length modifier is set to a value
- greater than zero, pcre2test passes a buffer of the given length. This
+ its output. However, if the convert_length modifier is set to a value
+ greater than zero, pcre2test passes a buffer of the given length. This
makes it possible to test the length check.
- The convert_glob_escape and convert_glob_separator modifiers can be
- used to specify the escape and separator characters for glob process-
+ The convert_glob_escape and convert_glob_separator modifiers can be
+ used to specify the escape and separator characters for glob process-
ing, overriding the defaults, which are operating-system dependent.
@@ -1008,7 +1022,7 @@ SUBJECT MODIFIERS
Setting match options
- The following modifiers set options for pcre2_match() or
+ The following modifiers set options for pcre2_match() or
pcre2_dfa_match(). See pcreapi for a description of their effects.
anchored set PCRE2_ANCHORED
@@ -1024,39 +1038,40 @@ SUBJECT MODIFIERS
partial_hard (or ph) set PCRE2_PARTIAL_HARD
partial_soft (or ps) set PCRE2_PARTIAL_SOFT
- The partial matching modifiers are provided with abbreviations because
+ The partial matching modifiers are provided with abbreviations because
they appear frequently in tests.
- If the posix or posix_nosub modifier was present on the pattern, caus-
+ If the posix or posix_nosub modifier was present on the pattern, caus-
ing the POSIX wrapper API to be used, the only option-setting modifiers
that have any effect are notbol, notempty, and noteol, causing REG_NOT-
- BOL, REG_NOTEMPTY, and REG_NOTEOL, respectively, to be passed to
+ BOL, REG_NOTEMPTY, and REG_NOTEOL, respectively, to be passed to
regexec(). The other modifiers are ignored, with a warning message.
- There is one additional modifier that can be used with the POSIX wrap-
+ There is one additional modifier that can be used with the POSIX wrap-
per. It is ignored (with a warning) if used for non-POSIX matching.
posix_startend=[:]
- This causes the subject string to be passed to regexec() using the
- REG_STARTEND option, which uses offsets to specify which part of the
- string is searched. If only one number is given, the end offset is
- passed as the end of the subject string. For more detail of REG_STAR-
- TEND, see the pcre2posix documentation. If the subject string contains
- binary zeros (coded as escapes such as \x{00} because pcre2test does
+ This causes the subject string to be passed to regexec() using the
+ REG_STARTEND option, which uses offsets to specify which part of the
+ string is searched. If only one number is given, the end offset is
+ passed as the end of the subject string. For more detail of REG_STAR-
+ TEND, see the pcre2posix documentation. If the subject string contains
+ binary zeros (coded as escapes such as \x{00} because pcre2test does
not support actual binary zeros in its input), you must use posix_star-
tend to specify its length.
Setting match controls
- The following modifiers affect the matching process or request addi-
- tional information. Some of them may also be specified on a pattern
- line (see above), in which case they apply to every subject line that
+ The following modifiers affect the matching process or request addi-
+ tional information. Some of them may also be specified on a pattern
+ line (see above), in which case they apply to every subject line that
is matched against that pattern.
aftertext show text after match
allaftertext show text after captures
allcaptures show all captures
+ allvector show the entire ovector
allusedtext show all consulted text (non-JIT only)
altglobal alternative global matching
callout_capture show captures at callout time
@@ -1086,54 +1101,61 @@ SUBJECT MODIFIERS
replace= specify a replacement string
startchar show startchar when relevant
startoffset= same as offset=
+ substitute_callout use substitution callouts
substitute_extedded use PCRE2_SUBSTITUTE_EXTENDED
+ substitute_skip= skip substitution number n
substitute_overflow_length use PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+ substitute_stop= skip substitution number n and greater
substitute_unknown_unset use PCRE2_SUBSTITUTE_UNKNOWN_UNSET
substitute_unset_empty use PCRE2_SUBSTITUTE_UNSET_EMPTY
zero_terminate pass the subject as zero-terminated
The effects of these modifiers are described in the following sections.
- When matching via the POSIX wrapper API, the aftertext, allaftertext,
- and ovector subject modifiers work as described below. All other modi-
+ When matching via the POSIX wrapper API, the aftertext, allaftertext,
+ and ovector subject modifiers work as described below. All other modi-
fiers are either ignored, with a warning message, or cause an error.
Showing more text
- The aftertext modifier requests that as well as outputting the part of
+ The aftertext modifier requests that as well as outputting the part of
the subject string that matched the entire pattern, pcre2test should in
addition output the remainder of the subject string. This is useful for
tests where the subject contains multiple copies of the same substring.
- The allaftertext modifier requests the same action for captured sub-
+ The allaftertext modifier requests the same action for captured sub-
strings as well as the main matched substring. In each case the remain-
der is output on the following line with a plus character following the
capture number.
- The allusedtext modifier requests that all the text that was consulted
- during a successful pattern match by the interpreter should be shown.
- This feature is not supported for JIT matching, and if requested with
- JIT it is ignored (with a warning message). Setting this modifier
- affects the output if there is a lookbehind at the start of a match, or
- a lookahead at the end, or if \K is used in the pattern. Characters
- that precede or follow the start and end of the actual match are indi-
- cated in the output by '<' or '>' characters underneath them. Here is
- an example:
+ The allusedtext modifier requests that all the text that was consulted
+ during a successful pattern match by the interpreter should be shown,
+ for both full and partial matches. This feature is not supported for
+ JIT matching, and if requested with JIT it is ignored (with a warning
+ message). Setting this modifier affects the output if there is a look-
+ behind at the start of a match, or, for a complete match, a lookahead
+ at the end, or if \K is used in the pattern. Characters that precede or
+ follow the start and end of the actual match are indicated in the out-
+ put by '<' or '>' characters underneath them. Here is an example:
re> /(?<=pqr)abc(?=xyz)/
data> 123pqrabcxyz456\=allusedtext
0: pqrabcxyz
<<< >>>
+ data> 123pqrabcxy\=ph,allusedtext
+ Partial match: pqrabcxy
+ <<<
- This shows that the matched string is "abc", with the preceding and
- following strings "pqr" and "xyz" having been consulted during the
- match (when processing the assertions).
+ The first, complete match shows that the matched string is "abc", with
+ the preceding and following strings "pqr" and "xyz" having been con-
+ sulted during the match (when processing the assertions). The partial
+ match can indicate only the preceding string.
The startchar modifier requests that the starting character for the
match be indicated, if it is different to the start of the matched
string. The only time when this occurs is when \K has been processed as
part of the match. In this situation, the output for the matched string
is displayed from the starting character instead of from the match
- point, with circumflex characters under the earlier characters. For
- example:
+ point, with circumflex characters under the earlier characters. For ex-
+ ample:
re> /abc\Kxyz/
data> abcxyz\=startchar
@@ -1150,76 +1172,95 @@ SUBJECT MODIFIERS
the highest one actually used in the match are output (corresponding to
the return code from pcre2_match()). Groups that did not take part in
the match are output as "". This modifier is not relevant for
- DFA matching (which does no capturing); it is ignored, with a warning
- message, if present.
-
- Testing callouts
-
- A callout function is supplied when pcre2test calls the library match-
- ing functions, unless callout_none is specified. Its behaviour can be
- controlled by various modifiers listed above whose names begin with
- callout_. Details are given in the section entitled "Callouts" below.
+ DFA matching (which does no capturing) and does not apply when replace
+ is specified; it is ignored, with a warning message, if present.
+
+ Showing the entire ovector, for all outcomes
+
+ The allvector modifier requests that the entire ovector be shown, what-
+ ever the outcome of the match. Compare allcaptures, which shows only up
+ to the maximum number of capture groups for the pattern, and then only
+ for a successful complete non-DFA match. This modifier, which acts af-
+ ter any match result, and also for DFA matching, provides a means of
+ checking that there are no unexpected modifications to ovector fields.
+ Before each match attempt, the ovector is filled with a special value,
+ and if this is found in both elements of a capturing pair, "" is output. After a successful match, this applies to all
+ groups after the maximum capture group for the pattern. In other cases
+ it applies to the entire ovector. After a partial match, the first two
+ elements are the only ones that should be set. After a DFA match, the
+ amount of ovector that is used depends on the number of matches that
+ were found.
+
+ Testing pattern callouts
+
+ A callout function is supplied when pcre2test calls the library match-
+ ing functions, unless callout_none is specified. Its behaviour can be
+ controlled by various modifiers listed above whose names begin with
+ callout_. Details are given in the section entitled "Callouts" below.
+ Testing callouts from pcre2_substitute() is decribed separately in
+ "Testing the substitution function" below.
Finding all matches in a string
Searching for all possible matches within a subject can be requested by
- the global or altglobal modifier. After finding a match, the matching
- function is called again to search the remainder of the subject. The
- difference between global and altglobal is that the former uses the
- start_offset argument to pcre2_match() or pcre2_dfa_match() to start
- searching at a new point within the entire string (which is what Perl
+ the global or altglobal modifier. After finding a match, the matching
+ function is called again to search the remainder of the subject. The
+ difference between global and altglobal is that the former uses the
+ start_offset argument to pcre2_match() or pcre2_dfa_match() to start
+ searching at a new point within the entire string (which is what Perl
does), whereas the latter passes over a shortened subject. This makes a
difference to the matching process if the pattern begins with a lookbe-
hind assertion (including \b or \B).
- If an empty string is matched, the next match is done with the
+ If an empty string is matched, the next match is done with the
PCRE2_NOTEMPTY_ATSTART and PCRE2_ANCHORED flags set, in order to search
for another, non-empty, match at the same point in the subject. If this
- match fails, the start offset is advanced, and the normal match is
- retried. This imitates the way Perl handles such cases when using the
- /g modifier or the split() function. Normally, the start offset is
- advanced by one character, but if the newline convention recognizes
- CRLF as a newline, and the current character is CR followed by LF, an
- advance of two characters occurs.
+ match fails, the start offset is advanced, and the normal match is re-
+ tried. This imitates the way Perl handles such cases when using the /g
+ modifier or the split() function. Normally, the start offset is ad-
+ vanced by one character, but if the newline convention recognizes CRLF
+ as a newline, and the current character is CR followed by LF, an ad-
+ vance of two characters occurs.
Testing substring extraction functions
- The copy and get modifiers can be used to test the pcre2_sub-
+ The copy and get modifiers can be used to test the pcre2_sub-
string_copy_xxx() and pcre2_substring_get_xxx() functions. They can be
- given more than once, and each can specify a group name or number, for
- example:
+ given more than once, and each can specify a capture group name or num-
+ ber, for example:
abcd\=copy=1,copy=3,get=G1
- If the #subject command is used to set default copy and/or get lists,
- these can be unset by specifying a negative number to cancel all num-
+ If the #subject command is used to set default copy and/or get lists,
+ these can be unset by specifying a negative number to cancel all num-
bered groups and an empty name to cancel all named groups.
- The getall modifier tests pcre2_substring_list_get(), which extracts
+ The getall modifier tests pcre2_substring_list_get(), which extracts
all captured substrings.
- If the subject line is successfully matched, the substrings extracted
- by the convenience functions are output with C, G, or L after the
- string number instead of a colon. This is in addition to the normal
- full list. The string length (that is, the return from the extraction
+ If the subject line is successfully matched, the substrings extracted
+ by the convenience functions are output with C, G, or L after the
+ string number instead of a colon. This is in addition to the normal
+ full list. The string length (that is, the return from the extraction
function) is given in parentheses after each substring, followed by the
name when the extraction was by name.
Testing the substitution function
- If the replace modifier is set, the pcre2_substitute() function is
- called instead of one of the matching functions. Note that replacement
- strings cannot contain commas, because a comma signifies the end of a
+ If the replace modifier is set, the pcre2_substitute() function is
+ called instead of one of the matching functions. Note that replacement
+ strings cannot contain commas, because a comma signifies the end of a
modifier. This is not thought to be an issue in a test program.
- Unlike subject strings, pcre2test does not process replacement strings
- for escape sequences. In UTF mode, a replacement string is checked to
- see if it is a valid UTF-8 string. If so, it is correctly converted to
- a UTF string of the appropriate code unit width. If it is not a valid
- UTF-8 string, the individual code units are copied directly. This pro-
+ Unlike subject strings, pcre2test does not process replacement strings
+ for escape sequences. In UTF mode, a replacement string is checked to
+ see if it is a valid UTF-8 string. If so, it is correctly converted to
+ a UTF string of the appropriate code unit width. If it is not a valid
+ UTF-8 string, the individual code units are copied directly. This pro-
vides a means of passing an invalid UTF-8 string for testing purposes.
- The following modifiers set options (in additional to the normal match
+ The following modifiers set options (in additional to the normal match
options) for pcre2_substitute():
global PCRE2_SUBSTITUTE_GLOBAL
@@ -1229,8 +1270,8 @@ SUBJECT MODIFIERS
substitute_unset_empty PCRE2_SUBSTITUTE_UNSET_EMPTY
- After a successful substitution, the modified string is output, pre-
- ceded by the number of replacements. This may be zero if there were no
+ After a successful substitution, the modified string is output, pre-
+ ceded by the number of replacements. This may be zero if there were no
matches. Here is a simple example of a substitution test:
/abc/replace=xxx
@@ -1239,12 +1280,12 @@ SUBJECT MODIFIERS
=abc=abc=\=global
2: =xxx=xxx=
- Subject and replacement strings should be kept relatively short (fewer
- than 256 characters) for substitution tests, as fixed-size buffers are
- used. To make it easy to test for buffer overflow, if the replacement
- string starts with a number in square brackets, that number is passed
- to pcre2_substitute() as the size of the output buffer, with the
- replacement string starting at the next character. Here is an example
+ Subject and replacement strings should be kept relatively short (fewer
+ than 256 characters) for substitution tests, as fixed-size buffers are
+ used. To make it easy to test for buffer overflow, if the replacement
+ string starts with a number in square brackets, that number is passed
+ to pcre2_substitute() as the size of the output buffer, with the re-
+ placement string starting at the next character. Here is an example
that tests the edge case:
/abc/
@@ -1253,14 +1294,15 @@ SUBJECT MODIFIERS
123abc123\=replace=[9]XYZ
Failed: error -47: no more memory
- The default action of pcre2_substitute() is to return
- PCRE2_ERROR_NOMEMORY when the output buffer is too small. However, if
- the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option is set (by using the sub-
- stitute_overflow_length modifier), pcre2_substitute() continues to go
- through the motions of matching and substituting, in order to compute
- the size of buffer that is required. When this happens, pcre2test shows
- the required buffer length (which includes space for the trailing zero)
- as part of the error message. For example:
+ The default action of pcre2_substitute() is to return PCRE2_ER-
+ ROR_NOMEMORY when the output buffer is too small. However, if the
+ PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option is set (by using the substi-
+ tute_overflow_length modifier), pcre2_substitute() continues to go
+ through the motions of matching and substituting (but not doing any
+ callouts), in order to compute the size of buffer that is required.
+ When this happens, pcre2test shows the required buffer length (which
+ includes space for the trailing zero) as part of the error message. For
+ example:
/abc/substitute_overflow_length
123abc123\=replace=[9]XYZ
@@ -1270,162 +1312,204 @@ SUBJECT MODIFIERS
partial matching provokes an error return ("bad option value") from
pcre2_substitute().
+ Testing substitute callouts
+
+ If the substitute_callout modifier is set, a substitution callout func-
+ tion is set up. The null_context modifier must not be set, because the
+ address of the callout function is passed in a match context. When the
+ callout function is called (after each substitution), details of the
+ the input and output strings are output. For example:
+
+ /abc/g,replace=<$0>,substitute_callout
+ abcdefabcpqr
+ 1(1) Old 0 3 "abc" New 0 5 ""
+ 2(1) Old 6 9 "abc" New 8 13 ""
+ 2: defpqr
+
+ The first number on each callout line is the count of matches. The
+ parenthesized number is the number of pairs that are set in the ovector
+ (that is, one more than the number of capturing groups that were set).
+ Then are listed the offsets of the old substring, its contents, and the
+ same for the replacement.
+
+ By default, the substitution callout function returns zero, which ac-
+ cepts the replacement and causes matching to continue if /g was used.
+ Two further modifiers can be used to test other return values. If sub-
+ stitute_skip is set to a value greater than zero the callout function
+ returns +1 for the match of that number, and similarly substitute_stop
+ returns -1. These cause the replacement to be rejected, and -1 causes
+ no further matching to take place. If either of them are set, substi-
+ tute_callout is assumed. For example:
+
+ /abc/g,replace=<$0>,substitute_skip=1
+ abcdefabcpqr
+ 1(1) Old 0 3 "abc" New 0 5 " SKIPPED"
+ 2(1) Old 6 9 "abc" New 6 11 ""
+ 2: abcdefpqr
+ abcdefabcpqr\=substitute_stop=1
+ 1(1) Old 0 3 "abc" New 0 5 " STOPPED"
+ 1: abcdefabcpqr
+
+ If both are set for the same number, stop takes precedence. Only a sin-
+ gle skip or stop is supported, which is sufficient for testing that the
+ feature works.
+
Setting the JIT stack size
- The jitstack modifier provides a way of setting the maximum stack size
- that is used by the just-in-time optimization code. It is ignored if
- JIT optimization is not being used. The value is a number of kibibytes
- (units of 1024 bytes). Setting zero reverts to the default of 32KiB.
+ The jitstack modifier provides a way of setting the maximum stack size
+ that is used by the just-in-time optimization code. It is ignored if
+ JIT optimization is not being used. The value is a number of kibibytes
+ (units of 1024 bytes). Setting zero reverts to the default of 32KiB.
Providing a stack that is larger than the default is necessary only for
- very complicated patterns. If jitstack is set non-zero on a subject
+ very complicated patterns. If jitstack is set non-zero on a subject
line it overrides any value that was set on the pattern.
Setting heap, match, and depth limits
- The heap_limit, match_limit, and depth_limit modifiers set the appro-
- priate limits in the match context. These values are ignored when the
+ The heap_limit, match_limit, and depth_limit modifiers set the appro-
+ priate limits in the match context. These values are ignored when the
find_limits modifier is specified.
Finding minimum limits
- If the find_limits modifier is present on a subject line, pcre2test
- calls the relevant matching function several times, setting different
- values in the match context via pcre2_set_heap_limit(),
- pcre2_set_match_limit(), or pcre2_set_depth_limit() until it finds the
- minimum values for each parameter that allows the match to complete
+ If the find_limits modifier is present on a subject line, pcre2test
+ calls the relevant matching function several times, setting different
+ values in the match context via pcre2_set_heap_limit(),
+ pcre2_set_match_limit(), or pcre2_set_depth_limit() until it finds the
+ minimum values for each parameter that allows the match to complete
without error. If JIT is being used, only the match limit is relevant.
When using this modifier, the pattern should not contain any limit set-
- tings such as (*LIMIT_MATCH=...) within it. If such a setting is
+ tings such as (*LIMIT_MATCH=...) within it. If such a setting is
present and is lower than the minimum matching value, the minimum value
- cannot be found because pcre2_set_match_limit() etc. are only able to
+ cannot be found because pcre2_set_match_limit() etc. are only able to
reduce the value of an in-pattern limit; they cannot increase it.
- For non-DFA matching, the minimum depth_limit number is a measure of
+ For non-DFA matching, the minimum depth_limit number is a measure of
how much nested backtracking happens (that is, how deeply the pattern's
- tree is searched). In the case of DFA matching, depth_limit controls
- the depth of recursive calls of the internal function that is used for
+ tree is searched). In the case of DFA matching, depth_limit controls
+ the depth of recursive calls of the internal function that is used for
handling pattern recursion, lookaround assertions, and atomic groups.
For non-DFA matching, the match_limit number is a measure of the amount
of backtracking that takes place, and learning the minimum value can be
- instructive. For most simple matches, the number is quite small, but
- for patterns with very large numbers of matching possibilities, it can
- become large very quickly with increasing length of subject string. In
- the case of DFA matching, match_limit controls the total number of
+ instructive. For most simple matches, the number is quite small, but
+ for patterns with very large numbers of matching possibilities, it can
+ become large very quickly with increasing length of subject string. In
+ the case of DFA matching, match_limit controls the total number of
calls, both recursive and non-recursive, to the internal matching func-
tion, thus controlling the overall amount of computing resource that is
used.
- For both kinds of matching, the heap_limit number, which is in
- kibibytes (units of 1024 bytes), limits the amount of heap memory used
+ For both kinds of matching, the heap_limit number, which is in
+ kibibytes (units of 1024 bytes), limits the amount of heap memory used
for matching. A value of zero disables the use of any heap memory; many
- simple pattern matches can be done without using the heap, so zero is
+ simple pattern matches can be done without using the heap, so zero is
not an unreasonable setting.
Showing MARK names
The mark modifier causes the names from backtracking control verbs that
- are returned from calls to pcre2_match() to be displayed. If a mark is
- returned for a match, non-match, or partial match, pcre2test shows it.
- For a match, it is on a line by itself, tagged with "MK:". Otherwise,
+ are returned from calls to pcre2_match() to be displayed. If a mark is
+ returned for a match, non-match, or partial match, pcre2test shows it.
+ For a match, it is on a line by itself, tagged with "MK:". Otherwise,
it is added to the non-match message.
Showing memory usage
- The memory modifier causes pcre2test to log the sizes of all heap mem-
- ory allocation and freeing calls that occur during a call to
- pcre2_match() or pcre2_dfa_match(). These occur only when a match
- requires a bigger vector than the default for remembering backtracking
- points (pcre2_match()) or for internal workspace (pcre2_dfa_match()).
- In many cases there will be no heap memory used and therefore no addi-
+ The memory modifier causes pcre2test to log the sizes of all heap mem-
+ ory allocation and freeing calls that occur during a call to
+ pcre2_match() or pcre2_dfa_match(). These occur only when a match re-
+ quires a bigger vector than the default for remembering backtracking
+ points (pcre2_match()) or for internal workspace (pcre2_dfa_match()).
+ In many cases there will be no heap memory used and therefore no addi-
tional output. No heap memory is allocated during matching with JIT, so
- in that case the memory modifier never has any effect. For this modi-
- fier to work, the null_context modifier must not be set on both the
+ in that case the memory modifier never has any effect. For this modi-
+ fier to work, the null_context modifier must not be set on both the
pattern and the subject, though it can be set on one or the other.
Setting a starting offset
- The offset modifier sets an offset in the subject string at which
+ The offset modifier sets an offset in the subject string at which
matching starts. Its value is a number of code units, not characters.
Setting an offset limit
- The offset_limit modifier sets a limit for unanchored matches. If a
+ The offset_limit modifier sets a limit for unanchored matches. If a
match cannot be found starting at or before this offset in the subject,
a "no match" return is given. The data value is a number of code units,
- not characters. When this modifier is used, the use_offset_limit modi-
+ not characters. When this modifier is used, the use_offset_limit modi-
fier must have been set for the pattern; if not, an error is generated.
Setting the size of the output vector
- The ovector modifier applies only to the subject line in which it
- appears, though of course it can also be used to set a default in a
- #subject command. It specifies the number of pairs of offsets that are
+ The ovector modifier applies only to the subject line in which it ap-
+ pears, though of course it can also be used to set a default in a #sub-
+ ject command. It specifies the number of pairs of offsets that are
available for storing matching information. The default is 15.
- A value of zero is useful when testing the POSIX API because it causes
+ A value of zero is useful when testing the POSIX API because it causes
regexec() to be called with a NULL capture vector. When not testing the
- POSIX API, a value of zero is used to cause pcre2_match_data_cre-
- ate_from_pattern() to be called, in order to create a match block of
+ POSIX API, a value of zero is used to cause pcre2_match_data_cre-
+ ate_from_pattern() to be called, in order to create a match block of
exactly the right size for the pattern. (It is not possible to create a
- match block with a zero-length ovector; there is always at least one
+ match block with a zero-length ovector; there is always at least one
pair of offsets.)
Passing the subject as zero-terminated
By default, the subject string is passed to a native API matching func-
tion with its correct length. In order to test the facility for passing
- a zero-terminated string, the zero_terminate modifier is provided. It
- causes the length to be passed as PCRE2_ZERO_TERMINATED. When matching
+ a zero-terminated string, the zero_terminate modifier is provided. It
+ causes the length to be passed as PCRE2_ZERO_TERMINATED. When matching
via the POSIX interface, this modifier is ignored, with a warning.
- When testing pcre2_substitute(), this modifier also has the effect of
+ When testing pcre2_substitute(), this modifier also has the effect of
passing the replacement string as zero-terminated.
Passing a NULL context
- Normally, pcre2test passes a context block to pcre2_match(),
- pcre2_dfa_match() or pcre2_jit_match(). If the null_context modifier is
- set, however, NULL is passed. This is for testing that the matching
- functions behave correctly in this case (they use default values). This
- modifier cannot be used with the find_limits modifier or when testing
- the substitution function.
+ Normally, pcre2test passes a context block to pcre2_match(),
+ pcre2_dfa_match(), pcre2_jit_match() or pcre2_substitute(). If the
+ null_context modifier is set, however, NULL is passed. This is for
+ testing that the matching and substitution functions behave correctly
+ in this case (they use default values). This modifier cannot be used
+ with the find_limits or substitute_callout modifiers.
THE ALTERNATIVE MATCHING FUNCTION
- By default, pcre2test uses the standard PCRE2 matching function,
+ By default, pcre2test uses the standard PCRE2 matching function,
pcre2_match() to match each subject line. PCRE2 also supports an alter-
- native matching function, pcre2_dfa_match(), which operates in a dif-
- ferent way, and has some restrictions. The differences between the two
+ native matching function, pcre2_dfa_match(), which operates in a dif-
+ ferent way, and has some restrictions. The differences between the two
functions are described in the pcre2matching documentation.
- If the dfa modifier is set, the alternative matching function is used.
- This function finds all possible matches at a given point in the sub-
- ject. If, however, the dfa_shortest modifier is set, processing stops
- after the first match is found. This is always the shortest possible
+ If the dfa modifier is set, the alternative matching function is used.
+ This function finds all possible matches at a given point in the sub-
+ ject. If, however, the dfa_shortest modifier is set, processing stops
+ after the first match is found. This is always the shortest possible
match.
DEFAULT OUTPUT FROM pcre2test
- This section describes the output when the normal matching function,
+ This section describes the output when the normal matching function,
pcre2_match(), is being used.
- When a match succeeds, pcre2test outputs the list of captured sub-
- strings, starting with number 0 for the string that matched the whole
- pattern. Otherwise, it outputs "No match" when the return is
- PCRE2_ERROR_NOMATCH, or "Partial match:" followed by the partially
- matching substring when the return is PCRE2_ERROR_PARTIAL. (Note that
- this is the entire substring that was inspected during the partial
- match; it may include characters before the actual match start if a
- lookbehind assertion, \K, \b, or \B was involved.)
+ When a match succeeds, pcre2test outputs the list of captured sub-
+ strings, starting with number 0 for the string that matched the whole
+ pattern. Otherwise, it outputs "No match" when the return is PCRE2_ER-
+ ROR_NOMATCH, or "Partial match:" followed by the partially matching
+ substring when the return is PCRE2_ERROR_PARTIAL. (Note that this is
+ the entire substring that was inspected during the partial match; it
+ may include characters before the actual match start if a lookbehind
+ assertion, \K, \b, or \B was involved.)
For any other return, pcre2test outputs the PCRE2 negative error number
- and a short descriptive phrase. If the error is a failed UTF string
- check, the code unit offset of the start of the failing character is
+ and a short descriptive phrase. If the error is a failed UTF string
+ check, the code unit offset of the start of the failing character is
also output. Here is an example of an interactive pcre2test run.
$ pcre2test
@@ -1441,8 +1525,8 @@ DEFAULT OUTPUT FROM pcre2test
Unset capturing substrings that are not followed by one that is set are
not shown by pcre2test unless the allcaptures modifier is specified. In
the following example, there are two capturing substrings, but when the
- first data line is matched, the second, unset substring is not shown.
- An "internal" unset substring is shown as "", as for the second
+ first data line is matched, the second, unset substring is not shown.
+ An "internal" unset substring is shown as "", as for the second
data line.
re> /(a)|(b)/
@@ -1454,11 +1538,11 @@ DEFAULT OUTPUT FROM pcre2test
1:
2: b
- If the strings contain any non-printing characters, they are output as
- \xhh escapes if the value is less than 256 and UTF mode is not set.
+ If the strings contain any non-printing characters, they are output as
+ \xhh escapes if the value is less than 256 and UTF mode is not set.
Otherwise they are output as \x{hh...} escapes. See below for the defi-
- nition of non-printing characters. If the aftertext modifier is set,
- the output for substring 0 is followed by the the rest of the subject
+ nition of non-printing characters. If the aftertext modifier is set,
+ the output for substring 0 is followed by the the rest of the subject
string, identified by "0+" like this:
re> /cat/aftertext
@@ -1466,8 +1550,8 @@ DEFAULT OUTPUT FROM pcre2test
0: cat
0+ aract
- If global matching is requested, the results of successive matching
- attempts are output in sequence, like this:
+ If global matching is requested, the results of successive matching at-
+ tempts are output in sequence, like this:
re> /\Bi(\w\w)/g
data> Mississippi
@@ -1478,8 +1562,8 @@ DEFAULT OUTPUT FROM pcre2test
0: ipp
1: pp
- "No match" is output only if the first match attempt fails. Here is an
- example of a failure message (the offset 4 that is specified by the
+ "No match" is output only if the first match attempt fails. Here is an
+ example of a failure message (the offset 4 that is specified by the
offset modifier is past the end of the subject string):
re> /xyz/
@@ -1487,7 +1571,7 @@ DEFAULT OUTPUT FROM pcre2test
Error -24 (bad offset value)
Note that whereas patterns can be continued over several lines (a plain
- ">" prompt is used for continuations), subject lines may not. However
+ ">" prompt is used for continuations), subject lines may not. However
newlines can be included in a subject by means of the \n escape (or \r,
\r\n, etc., depending on the newline sequence setting).
@@ -1495,7 +1579,7 @@ DEFAULT OUTPUT FROM pcre2test
OUTPUT FROM THE ALTERNATIVE MATCHING FUNCTION
When the alternative matching function, pcre2_dfa_match(), is used, the
- output consists of a list of all the matches that start at the first
+ output consists of a list of all the matches that start at the first
point in the subject where there is at least one match. For example:
re> /(tang|tangerine|tan)/
@@ -1504,13 +1588,13 @@ OUTPUT FROM THE ALTERNATIVE MATCHING FUNCTION
1: tang
2: tan
- Using the normal matching function on this data finds only "tang". The
- longest matching string is always given first (and numbered zero).
- After a PCRE2_ERROR_PARTIAL return, the output is "Partial match:",
- followed by the partially matching substring. Note that this is the
- entire substring that was inspected during the partial match; it may
- include characters before the actual match start if a lookbehind asser-
- tion, \b, or \B was involved. (\K is not supported for DFA matching.)
+ Using the normal matching function on this data finds only "tang". The
+ longest matching string is always given first (and numbered zero). Af-
+ ter a PCRE2_ERROR_PARTIAL return, the output is "Partial match:", fol-
+ lowed by the partially matching substring. Note that this is the entire
+ substring that was inspected during the partial match; it may include
+ characters before the actual match start if a lookbehind assertion, \b,
+ or \B was involved. (\K is not supported for DFA matching.)
If global matching is requested, the search for further matches resumes
at the end of the longest match. For example:
@@ -1524,55 +1608,55 @@ OUTPUT FROM THE ALTERNATIVE MATCHING FUNCTION
1: tan
0: tan
- The alternative matching function does not support substring capture,
- so the modifiers that are concerned with captured substrings are not
+ The alternative matching function does not support substring capture,
+ so the modifiers that are concerned with captured substrings are not
relevant.
RESTARTING AFTER A PARTIAL MATCH
- When the alternative matching function has given the PCRE2_ERROR_PAR-
+ When the alternative matching function has given the PCRE2_ERROR_PAR-
TIAL return, indicating that the subject partially matched the pattern,
- you can restart the match with additional subject data by means of the
+ you can restart the match with additional subject data by means of the
dfa_restart modifier. For example:
re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
- data> 23ja\=P,dfa
+ data> 23ja\=ps,dfa
Partial match: 23ja
data> n05\=dfa,dfa_restart
0: n05
- For further information about partial matching, see the pcre2partial
+ For further information about partial matching, see the pcre2partial
documentation.
CALLOUTS
If the pattern contains any callout requests, pcre2test's callout func-
- tion is called during matching unless callout_none is specified. This
+ tion is called during matching unless callout_none is specified. This
works with both matching functions, and with JIT, though there are some
- differences in behaviour. The output for callouts with numerical argu-
+ differences in behaviour. The output for callouts with numerical argu-
ments and those with string arguments is slightly different.
Callouts with numerical arguments
By default, the callout function displays the callout number, the start
- and current positions in the subject text at the callout time, and the
+ and current positions in the subject text at the callout time, and the
next pattern item to be tested. For example:
--->pqrabcdef
0 ^ ^ \d
- This output indicates that callout number 0 occurred for a match
- attempt starting at the fourth character of the subject string, when
- the pointer was at the seventh character, and when the next pattern
- item was \d. Just one circumflex is output if the start and current
- positions are the same, or if the current position precedes the start
- position, which can happen if the callout is in a lookbehind assertion.
+ This output indicates that callout number 0 occurred for a match at-
+ tempt starting at the fourth character of the subject string, when the
+ pointer was at the seventh character, and when the next pattern item
+ was \d. Just one circumflex is output if the start and current posi-
+ tions are the same, or if the current position precedes the start posi-
+ tion, which can happen if the callout is in a lookbehind assertion.
Callouts numbered 255 are assumed to be automatic callouts, inserted as
a result of the auto_callout pattern modifier. In this case, instead of
- showing the callout number, the offset in the pattern, preceded by a
+ showing the callout number, the offset in the pattern, preceded by a
plus, is output. For example:
re> /\d?[A-E]\*/auto_callout
@@ -1585,8 +1669,8 @@ CALLOUTS
0: E*
If a pattern contains (*MARK) items, an additional line is output when-
- ever a change of latest mark is passed to the callout function. For
- example:
+ ever a change of latest mark is passed to the callout function. For ex-
+ ample:
re> /a(*MARK:X)bc/auto_callout
data> abc
@@ -1599,17 +1683,17 @@ CALLOUTS
+12 ^ ^
0: abc
- The mark changes between matching "a" and "b", but stays the same for
- the rest of the match, so nothing more is output. If, as a result of
- backtracking, the mark reverts to being unset, the text "" is
+ The mark changes between matching "a" and "b", but stays the same for
+ the rest of the match, so nothing more is output. If, as a result of
+ backtracking, the mark reverts to being unset, the text "" is
output.
Callouts with string arguments
The output for a callout with a string argument is similar, except that
- instead of outputting a callout number before the position indicators,
- the callout string and its offset in the pattern string are output
- before the reflection of the subject string, and the subject string is
+ instead of outputting a callout number before the position indicators,
+ the callout string and its offset in the pattern string are output be-
+ fore the reflection of the subject string, and the subject string is
reflected for each callout. For example:
re> /^ab(?C'first')cd(?C"second")ef/
@@ -1625,26 +1709,26 @@ CALLOUTS
Callout modifiers
- The callout function in pcre2test returns zero (carry on matching) by
- default, but you can use a callout_fail modifier in a subject line to
+ The callout function in pcre2test returns zero (carry on matching) by
+ default, but you can use a callout_fail modifier in a subject line to
change this and other parameters of the callout (see below).
If the callout_capture modifier is set, the current captured groups are
output when a callout occurs. This is useful only for non-DFA matching,
- as pcre2_dfa_match() does not support capturing, so no captures are
+ as pcre2_dfa_match() does not support capturing, so no captures are
ever shown.
The normal callout output, showing the callout number or pattern offset
- (as described above) is suppressed if the callout_no_where modifier is
+ (as described above) is suppressed if the callout_no_where modifier is
set.
- When using the interpretive matching function pcre2_match() without
- JIT, setting the callout_extra modifier causes additional output from
- pcre2test's callout function to be generated. For the first callout in
- a match attempt at a new starting position in the subject, "New match
- attempt" is output. If there has been a backtrack since the last call-
+ When using the interpretive matching function pcre2_match() without
+ JIT, setting the callout_extra modifier causes additional output from
+ pcre2test's callout function to be generated. For the first callout in
+ a match attempt at a new starting position in the subject, "New match
+ attempt" is output. If there has been a backtrack since the last call-
out (or start of matching if this is the first callout), "Backtrack" is
- output, followed by "No other matching paths" if the backtrack ended
+ output, followed by "No other matching paths" if the backtrack ended
the previous match attempt. For example:
re> /(a+)b/auto_callout,no_start_optimize,no_auto_possess
@@ -1681,86 +1765,86 @@ CALLOUTS
+1 ^ a+
No match
- Notice that various optimizations must be turned off if you want all
- possible matching paths to be scanned. If no_start_optimize is not
- used, there is an immediate "no match", without any callouts, because
- the starting optimization fails to find "b" in the subject, which it
- knows must be present for any match. If no_auto_possess is not used,
- the "a+" item is turned into "a++", which reduces the number of back-
+ Notice that various optimizations must be turned off if you want all
+ possible matching paths to be scanned. If no_start_optimize is not
+ used, there is an immediate "no match", without any callouts, because
+ the starting optimization fails to find "b" in the subject, which it
+ knows must be present for any match. If no_auto_possess is not used,
+ the "a+" item is turned into "a++", which reduces the number of back-
tracks.
- The callout_extra modifier has no effect if used with the DFA matching
+ The callout_extra modifier has no effect if used with the DFA matching
function, or with JIT.
Return values from callouts
- The default return from the callout function is zero, which allows
+ The default return from the callout function is zero, which allows
matching to continue. The callout_fail modifier can be given one or two
numbers. If there is only one number, 1 is returned instead of 0 (caus-
ing matching to backtrack) when a callout of that number is reached. If
- two numbers (:) are given, 1 is returned when callout is
- reached and there have been at least callouts. The callout_error
+ two numbers (:) are given, 1 is returned when callout is
+ reached and there have been at least callouts. The callout_error
modifier is similar, except that PCRE2_ERROR_CALLOUT is returned, caus-
- ing the entire matching process to be aborted. If both these modifiers
- are set for the same callout number, callout_error takes precedence.
- Note that callouts with string arguments are always given the number
+ ing the entire matching process to be aborted. If both these modifiers
+ are set for the same callout number, callout_error takes precedence.
+ Note that callouts with string arguments are always given the number
zero.
- The callout_data modifier can be given an unsigned or a negative num-
- ber. This is set as the "user data" that is passed to the matching
- function, and passed back when the callout function is invoked. Any
- value other than zero is used as a return from pcre2test's callout
+ The callout_data modifier can be given an unsigned or a negative num-
+ ber. This is set as the "user data" that is passed to the matching
+ function, and passed back when the callout function is invoked. Any
+ value other than zero is used as a return from pcre2test's callout
function.
Inserting callouts can be helpful when using pcre2test to check compli-
- cated regular expressions. For further information about callouts, see
+ cated regular expressions. For further information about callouts, see
the pcre2callout documentation.
NON-PRINTING CHARACTERS
When pcre2test is outputting text in the compiled version of a pattern,
- bytes other than 32-126 are always treated as non-printing characters
+ bytes other than 32-126 are always treated as non-printing characters
and are therefore shown as hex escapes.
- When pcre2test is outputting text that is a matched part of a subject
- string, it behaves in the same way, unless a different locale has been
- set for the pattern (using the locale modifier). In this case, the
- isprint() function is used to distinguish printing and non-printing
- characters.
+ When pcre2test is outputting text that is a matched part of a subject
+ string, it behaves in the same way, unless a different locale has been
+ set for the pattern (using the locale modifier). In this case, the is-
+ print() function is used to distinguish printing and non-printing char-
+ acters.
SAVING AND RESTORING COMPILED PATTERNS
- It is possible to save compiled patterns on disc or elsewhere, and
+ It is possible to save compiled patterns on disc or elsewhere, and
reload them later, subject to a number of restrictions. JIT data cannot
- be saved. The host on which the patterns are reloaded must be running
+ be saved. The host on which the patterns are reloaded must be running
the same version of PCRE2, with the same code unit width, and must also
- have the same endianness, pointer width and PCRE2_SIZE type. Before
- compiled patterns can be saved they must be serialized, that is, con-
- verted to a stream of bytes. A single byte stream may contain any num-
- ber of compiled patterns, but they must all use the same character
- tables. A single copy of the tables is included in the byte stream (its
+ have the same endianness, pointer width and PCRE2_SIZE type. Before
+ compiled patterns can be saved they must be serialized, that is, con-
+ verted to a stream of bytes. A single byte stream may contain any num-
+ ber of compiled patterns, but they must all use the same character ta-
+ bles. A single copy of the tables is included in the byte stream (its
size is 1088 bytes).
- The functions whose names begin with pcre2_serialize_ are used for
- serializing and de-serializing. They are described in the pcre2serial-
- ize documentation. In this section we describe the features of
- pcre2test that can be used to test these functions.
+ The functions whose names begin with pcre2_serialize_ are used for se-
+ rializing and de-serializing. They are described in the pcre2serialize
+ documentation. In this section we describe the features of pcre2test
+ that can be used to test these functions.
- Note that "serialization" in PCRE2 does not convert compiled patterns
- to an abstract format like Java or .NET. It just makes a reloadable
+ Note that "serialization" in PCRE2 does not convert compiled patterns
+ to an abstract format like Java or .NET. It just makes a reloadable
byte code stream. Hence the restrictions on reloading mentioned above.
- In pcre2test, when a pattern with push modifier is successfully com-
- piled, it is pushed onto a stack of compiled patterns, and pcre2test
- expects the next line to contain a new pattern (or command) instead of
+ In pcre2test, when a pattern with push modifier is successfully com-
+ piled, it is pushed onto a stack of compiled patterns, and pcre2test
+ expects the next line to contain a new pattern (or command) instead of
a subject line. By contrast, the pushcopy modifier causes a copy of the
- compiled pattern to be stacked, leaving the original available for
- immediate matching. By using push and/or pushcopy, a number of patterns
- can be compiled and retained. These modifiers are incompatible with
+ compiled pattern to be stacked, leaving the original available for im-
+ mediate matching. By using push and/or pushcopy, a number of patterns
+ can be compiled and retained. These modifiers are incompatible with
posix, and control modifiers that act at match time are ignored (with a
- message) for the stacked patterns. The jitverify modifier applies only
+ message) for the stacked patterns. The jitverify modifier applies only
at compile time.
The command
@@ -1768,21 +1852,21 @@ SAVING AND RESTORING COMPILED PATTERNS
#save
causes all the stacked patterns to be serialized and the result written
- to the named file. Afterwards, all the stacked patterns are freed. The
+ to the named file. Afterwards, all the stacked patterns are freed. The
command
#load
- reads the data in the file, and then arranges for it to be de-serial-
- ized, with the resulting compiled patterns added to the pattern stack.
- The pattern on the top of the stack can be retrieved by the #pop com-
- mand, which must be followed by lines of subjects that are to be
- matched with the pattern, terminated as usual by an empty line or end
- of file. This command may be followed by a modifier list containing
- only control modifiers that act after a pattern has been compiled. In
- particular, hex, posix, posix_nosub, push, and pushcopy are not
- allowed, nor are any option-setting modifiers. The JIT modifiers are,
- however permitted. Here is an example that saves and reloads two pat-
+ reads the data in the file, and then arranges for it to be de-serial-
+ ized, with the resulting compiled patterns added to the pattern stack.
+ The pattern on the top of the stack can be retrieved by the #pop com-
+ mand, which must be followed by lines of subjects that are to be
+ matched with the pattern, terminated as usual by an empty line or end
+ of file. This command may be followed by a modifier list containing
+ only control modifiers that act after a pattern has been compiled. In
+ particular, hex, posix, posix_nosub, push, and pushcopy are not al-
+ lowed, nor are any option-setting modifiers. The JIT modifiers are,
+ however permitted. Here is an example that saves and reloads two pat-
terns.
/abc/push
@@ -1795,10 +1879,10 @@ SAVING AND RESTORING COMPILED PATTERNS
#pop jit,bincode
abc
- If jitverify is used with #pop, it does not automatically imply jit,
+ If jitverify is used with #pop, it does not automatically imply jit,
which is different behaviour from when it is used on a pattern.
- The #popcopy command is analagous to the pushcopy modifier in that it
+ The #popcopy command is analagous to the pushcopy modifier in that it
makes current a copy of the topmost stack pattern, leaving the original
still on the stack.
@@ -1818,5 +1902,5 @@ AUTHOR
REVISION
- Last updated: 21 July 2018
- Copyright (c) 1997-2018 University of Cambridge.
+ Last updated: 30 July 2019
+ Copyright (c) 1997-2019 University of Cambridge.
diff --git a/doc/pcre2unicode.3 b/doc/pcre2unicode.3
index 877d887..10efd7d 100644
--- a/doc/pcre2unicode.3
+++ b/doc/pcre2unicode.3
@@ -1,36 +1,49 @@
-.TH PCRE2UNICODE 3 "02 September 2018" "PCRE2 10.32"
+.TH PCRE2UNICODE 3 "24 May 2019" "PCRE2 10.34"
.SH NAME
PCRE - Perl-compatible regular expressions (revised API)
.SH "UNICODE AND UTF SUPPORT"
.rs
.sp
-When PCRE2 is built with Unicode support (which is the default), it has
-knowledge of Unicode character properties and can process text strings in
-UTF-8, UTF-16, or UTF-32 format (depending on the code unit width). However, by
-default, PCRE2 assumes that one code unit is one character. To process a
-pattern as a UTF string, where a character may require more than one code unit,
-you must call
+PCRE2 is normally built with Unicode support, though if you do not need it, you
+can build it without, in which case the library will be smaller. With Unicode
+support, PCRE2 has knowledge of Unicode character properties and can process
+text strings in UTF-8, UTF-16, or UTF-32 format (depending on the code unit
+width), but this is not the default. Unless specifically requested, PCRE2
+treats each code unit in a string as one character.
+.P
+There are two ways of telling PCRE2 to switch to UTF mode, where characters may
+consist of more than one code unit and the range of values is constrained. The
+program can call
.\" HREF
\fBpcre2_compile()\fP
.\"
-with the PCRE2_UTF option flag, or the pattern must start with the sequence
-(*UTF). When either of these is the case, both the pattern and any subject
-strings that are matched against it are treated as UTF strings instead of
-strings of individual one-code-unit characters. There are also some other
-changes to the way characters are handled, as documented below.
-.P
-If you do not need Unicode support you can build PCRE2 without it, in which
-case the library will be smaller.
+with the PCRE2_UTF option, or the pattern may start with the sequence (*UTF).
+However, the latter facility can be locked out by the PCRE2_NEVER_UTF option.
+That is, the programmer can prevent the supplier of the pattern from switching
+to UTF mode.
+.P
+Note that the PCRE2_MATCH_INVALID_UTF option (see
+.\" HTML
+.\"
+below)
+.\"
+forces PCRE2_UTF to be set.
+.P
+In UTF mode, both the pattern and any subject strings that are matched against
+it are treated as UTF strings instead of strings of individual one-code-unit
+characters. There are also some other changes to the way characters are
+handled, as documented below.
.
.
.SH "UNICODE PROPERTY SUPPORT"
.rs
.sp
When PCRE2 is built with Unicode support, the escape sequences \ep{..},
-\eP{..}, and \eX can be used. The Unicode properties that can be tested are
-limited to the general category properties such as Lu for an upper case letter
-or Nd for a decimal number, the Unicode script names such as Arabic or Han, and
-the derived properties Any and L&. Full lists are given in the
+\eP{..}, and \eX can be used. This is not dependent on the PCRE2_UTF setting.
+The Unicode properties that can be tested are limited to the general category
+properties such as Lu for an upper case letter or Nd for a decimal number, the
+Unicode script names such as Arabic or Han, and the derived properties Any and
+L&. Full lists are given in the
.\" HREF
\fBpcre2pattern\fP
.\"
@@ -54,21 +67,26 @@ also recognized; larger ones can be coded using \eo{...}.
.P
The escape sequence \eN{U+} is recognized as another way of
specifying a Unicode character by code point in a UTF mode. It is not allowed
-in non-UTF modes.
+in non-UTF mode.
.P
-In UTF modes, repeat quantifiers apply to complete UTF characters, not to
+In UTF mode, repeat quantifiers apply to complete UTF characters, not to
individual code units.
.P
-In UTF modes, the dot metacharacter matches one UTF character instead of a
+In UTF mode, the dot metacharacter matches one UTF character instead of a
single code unit.
.P
-The escape sequence \eC can be used to match a single code unit in a UTF mode,
+In UTF mode, capture group names are not restricted to ASCII, and may contain
+any Unicode letters and decimal digits, as well as underscore.
+.P
+The escape sequence \eC can be used to match a single code unit in UTF mode,
but its use can lead to some strange effects because it breaks up multi-unit
characters (see the description of \eC in the
.\" HREF
\fBpcre2pattern\fP
.\"
-documentation).
+documentation). For this reason, there is a build-time option that disables
+support for \eC completely. There is also a less draconian compile-time option
+for locking out the use of \eC when a pattern is compiled.
.P
The use of \eC is not supported by the alternative matching function
\fBpcre2_dfa_match()\fP when in UTF-8 or UTF-16 mode, that is, when a character
@@ -76,7 +94,7 @@ may consist of more than one code unit. The use of \eC in these modes provokes
a match-time error. Also, the JIT optimization does not support \eC in these
modes. If JIT optimization is requested for a UTF-8 or UTF-16 pattern that
contains \eC, it will not succeed, and so when \fBpcre2_match()\fP is called,
-the matching will be carried out by the normal interpretive function.
+the matching will be carried out by the interpretive function.
.P
The character escapes \eb, \eB, \ed, \eD, \es, \eS, \ew, and \eW correctly test
characters of any code value, but, by default, the characters that PCRE2
@@ -108,37 +126,159 @@ However, the special horizontal and vertical white space matching escapes (\eh,
not PCRE2_UCP is set.
.
.
-.SH "CASE-EQUIVALENCE IN UTF MODES"
+.SH "CASE-EQUIVALENCE IN UTF MODE"
.rs
.sp
-Case-insensitive matching in a UTF mode makes use of Unicode properties except
+Case-insensitive matching in UTF mode makes use of Unicode properties except
for characters whose code points are less than 128 and that have at most two
case-equivalent values. For these, a direct table lookup is used for speed. A
few Unicode characters such as Greek sigma have more than two code points that
-are case-equivalent, and these are treated as such.
+are case-equivalent, and these are treated specially.
+.
+.
+.\" HTML
+.SH "SCRIPT RUNS"
+.rs
+.sp
+The pattern constructs (*script_run:...) and (*atomic_script_run:...), with
+synonyms (*sr:...) and (*asr:...), verify that the string matched within the
+parentheses is a script run. In concept, a script run is a sequence of
+characters that are all from the same Unicode script. However, because some
+scripts are commonly used together, and because some diacritical and other
+marks are used with multiple scripts, it is not that simple.
+.P
+Every Unicode character has a Script property, mostly with a value
+corresponding to the name of a script, such as Latin, Greek, or Cyrillic. There
+are also three special values:
+.P
+"Unknown" is used for code points that have not been assigned, and also for the
+surrogate code points. In the PCRE2 32-bit library, characters whose code
+points are greater than the Unicode maximum (U+10FFFF), which are accessible
+only in non-UTF mode, are assigned the Unknown script.
+.P
+"Common" is used for characters that are used with many scripts. These include
+punctuation, emoji, mathematical, musical, and currency symbols, and the ASCII
+digits 0 to 9.
+.P
+"Inherited" is used for characters such as diacritical marks that modify a
+previous character. These are considered to take on the script of the character
+that they modify.
+.P
+Some Inherited characters are used with many scripts, but many of them are only
+normally used with a small number of scripts. For example, U+102E0 (Coptic
+Epact thousands mark) is used only with Arabic and Coptic. In order to make it
+possible to check this, a Unicode property called Script Extension exists. Its
+value is a list of scripts that apply to the character. For the majority of
+characters, the list contains just one script, the same one as the Script
+property. However, for characters such as U+102E0 more than one Script is
+listed. There are also some Common characters that have a single, non-Common
+script in their Script Extension list.
+.P
+The next section describes the basic rules for deciding whether a given string
+of characters is a script run. Note, however, that there are some special cases
+involving the Chinese Han script, and an additional constraint for decimal
+digits. These are covered in subsequent sections.
+.
+.
+.SS "Basic script run rules"
+.rs
+.sp
+A string that is less than two characters long is a script run. This is the
+only case in which an Unknown character can be part of a script run. Longer
+strings are checked using only the Script Extensions property, not the basic
+Script property.
+.P
+If a character's Script Extension property is the single value "Inherited", it
+is always accepted as part of a script run. This is also true for the property
+"Common", subject to the checking of decimal digits described below. All the
+remaining characters in a script run must have at least one script in common in
+their Script Extension lists. In set-theoretic terminology, the intersection of
+all the sets of scripts must not be empty.
+.P
+A simple example is an Internet name such as "google.com". The letters are all
+in the Latin script, and the dot is Common, so this string is a script run.
+However, the Cyrillic letter "o" looks exactly the same as the Latin "o"; a
+string that looks the same, but with Cyrillic "o"s is not a script run.
+.P
+More interesting examples involve characters with more than one script in their
+Script Extension. Consider the following characters:
+.sp
+ U+060C Arabic comma
+ U+06D4 Arabic full stop
+.sp
+The first has the Script Extension list Arabic, Hanifi Rohingya, Syriac, and
+Thaana; the second has just Arabic and Hanifi Rohingya. Both of them could
+appear in script runs of either Arabic or Hanifi Rohingya. The first could also
+appear in Syriac or Thaana script runs, but the second could not.
+.
+.
+.SS "The Chinese Han script"
+.rs
+.sp
+The Chinese Han script is commonly used in conjunction with other scripts for
+writing certain languages. Japanese uses the Hiragana and Katakana scripts
+together with Han; Korean uses Hangul and Han; Taiwanese Mandarin uses Bopomofo
+and Han. These three combinations are treated as special cases when checking
+script runs and are, in effect, "virtual scripts". Thus, a script run may
+contain a mixture of Hiragana, Katakana, and Han, or a mixture of Hangul and
+Han, or a mixture of Bopomofo and Han, but not, for example, a mixture of
+Hangul and Bopomofo and Han. PCRE2 (like Perl) follows Unicode's Technical
+Standard 39 ("Unicode Security Mechanisms", http://unicode.org/reports/tr39/)
+in allowing such mixtures.
+.
+.
+.SS "Decimal digits"
+.rs
+.sp
+Unicode contains many sets of 10 decimal digits in different scripts, and some
+scripts (including the Common script) contain more than one set. Some of these
+decimal digits them are visually indistinguishable from the common ASCII
+digits. In addition to the script checking described above, if a script run
+contains any decimal digits, they must all come from the same set of 10
+adjacent characters.
.
.
.SH "VALIDITY OF UTF STRINGS"
.rs
.sp
When the PCRE2_UTF option is set, the strings passed as patterns and subjects
-are (by default) checked for validity on entry to the relevant functions.
-If an invalid UTF string is passed, an negative error code is returned. The
-code unit offset to the offending character can be extracted from the match
-data block by calling \fBpcre2_get_startchar()\fP, which is used for this
-purpose after a UTF error.
+are (by default) checked for validity on entry to the relevant functions. If an
+invalid UTF string is passed, a negative error code is returned. The code unit
+offset to the offending character can be extracted from the match data block by
+calling \fBpcre2_get_startchar()\fP, which is used for this purpose after a UTF
+error.
+.P
+In some situations, you may already know that your strings are valid, and
+therefore want to skip these checks in order to improve performance, for
+example in the case of a long subject string that is being scanned repeatedly.
+If you set the PCRE2_NO_UTF_CHECK option at compile time or at match time,
+PCRE2 assumes that the pattern or subject it is given (respectively) contains
+only valid UTF code unit sequences.
+.P
+If you pass an invalid UTF string when PCRE2_NO_UTF_CHECK is set, the result
+is undefined and your program may crash or loop indefinitely or give incorrect
+results. There is, however, one mode of matching that can handle invalid UTF
+subject strings. This is enabled by passing PCRE2_MATCH_INVALID_UTF to
+\fBpcre2_compile()\fP and is discussed below in the next section. The rest of
+this section covers the case when PCRE2_MATCH_INVALID_UTF is not set.
+.P
+Passing PCRE2_NO_UTF_CHECK to \fBpcre2_compile()\fP just disables the UTF check
+for the pattern; it does not also apply to subject strings. If you want to
+disable the check for a subject string you must pass this same option to
+\fBpcre2_match()\fP or \fBpcre2_dfa_match()\fP.
.P
UTF-16 and UTF-32 strings can indicate their endianness by special code knows
as a byte-order mark (BOM). The PCRE2 functions do not handle this, expecting
strings to be in host byte order.
.P
-A UTF string is checked before any other processing takes place. In the case of
-\fBpcre2_match()\fP and \fBpcre2_dfa_match()\fP calls with a non-zero starting
-offset, the check is applied only to that part of the subject that could be
-inspected during matching, and there is a check that the starting offset points
-to the first code unit of a character or to the end of the subject. If there
-are no lookbehind assertions in the pattern, the check starts at the starting
-offset. Otherwise, it starts at the length of the longest lookbehind before the
+Unless PCRE2_NO_UTF_CHECK is set, a UTF string is checked before any other
+processing takes place. In the case of \fBpcre2_match()\fP and
+\fBpcre2_dfa_match()\fP calls with a non-zero starting offset, the check is
+applied only to that part of the subject that could be inspected during
+matching, and there is a check that the starting offset points to the first
+code unit of a character or to the end of the subject. If there are no
+lookbehind assertions in the pattern, the check starts at the starting offset.
+Otherwise, it starts at the length of the longest lookbehind before the
starting offset, or at the start of the subject if there are not that many
characters before the starting offset. Note that the sequences \eb and \eB are
one-character lookbehinds.
@@ -155,28 +295,12 @@ independently in the UTF-8 and UTF-32 encodings. (In other words, the whole
surrogate thing is a fudge for UTF-16 which unfortunately messes up UTF-8 and
UTF-32.)
.P
-In some situations, you may already know that your strings are valid, and
-therefore want to skip these checks in order to improve performance, for
-example in the case of a long subject string that is being scanned repeatedly.
-If you set the PCRE2_NO_UTF_CHECK option at compile time or at match time,
-PCRE2 assumes that the pattern or subject it is given (respectively) contains
-only valid UTF code unit sequences.
-.P
-Passing PCRE2_NO_UTF_CHECK to \fBpcre2_compile()\fP just disables the check for
-the pattern; it does not also apply to subject strings. If you want to disable
-the check for a subject string you must pass this option to \fBpcre2_match()\fP
-or \fBpcre2_dfa_match()\fP.
-.P
-If you pass an invalid UTF string when PCRE2_NO_UTF_CHECK is set, the result
-is undefined and your program may crash or loop indefinitely.
-.P
-Note that setting PCRE2_NO_UTF_CHECK at compile time does not disable the error
-that is given if an escape sequence for an invalid Unicode code point is
-encountered in the pattern. If you want to allow escape sequences such as
-\ex{d800} (a surrogate code point) you can set the
-PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES extra option. However, this is possible
-only in UTF-8 and UTF-32 modes, because these values are not representable in
-UTF-16.
+Setting PCRE2_NO_UTF_CHECK at compile time does not disable the error that is
+given if an escape sequence for an invalid Unicode code point is encountered in
+the pattern. If you want to allow escape sequences such as \ex{d800} (a
+surrogate code point) you can set the PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES extra
+option. However, this is possible only in UTF-8 and UTF-32 modes, because these
+values are not representable in UTF-16.
.
.
.\" HTML
@@ -215,7 +339,7 @@ these code points are excluded by RFC 3629.
.sp
PCRE2_ERROR_UTF8_ERR13
.sp
-A 4-byte character has a value greater than 0x10fff; these code points are
+A 4-byte character has a value greater than 0x10ffff; these code points are
excluded by RFC 3629.
.sp
PCRE2_ERROR_UTF8_ERR14
@@ -271,6 +395,52 @@ The following negative error codes are given for invalid UTF-32 strings:
.sp
.
.
+.\" HTML
+.SH "MATCHING IN INVALID UTF STRINGS"
+.rs
+.sp
+You can run pattern matches on subject strings that may contain invalid UTF
+sequences if you call \fBpcre2_compile()\fP with the PCRE2_MATCH_INVALID_UTF
+option. This is supported by \fBpcre2_match()\fP, including JIT matching, but
+not by \fBpcre2_dfa_match()\fP. When PCRE2_MATCH_INVALID_UTF is set, it forces
+PCRE2_UTF to be set as well. Note, however, that the pattern itself must be a
+valid UTF string.
+.P
+Setting PCRE2_MATCH_INVALID_UTF does not affect what \fBpcre2_compile()\fP
+generates, but if \fBpcre2_jit_compile()\fP is subsequently called, it does
+generate different code. If JIT is not used, the option affects the behaviour
+of the interpretive code in \fBpcre2_match()\fP. When PCRE2_MATCH_INVALID_UTF
+is set at compile time, PCRE2_NO_UTF_CHECK is ignored at match time.
+.P
+In this mode, an invalid code unit sequence in the subject never matches any
+pattern item. It does not match dot, it does not match \ep{Any}, it does not
+even match negative items such as [^X]. A lookbehind assertion fails if it
+encounters an invalid sequence while moving the current point backwards. In
+other words, an invalid UTF code unit sequence acts as a barrier which no match
+can cross.
+.P
+You can also think of this as the subject being split up into fragments of
+valid UTF, delimited internally by invalid code unit sequences. The pattern is
+matched fragment by fragment. The result of a successful match, however, is
+given as code unit offsets in the entire subject string in the usual way. There
+are a few points to consider:
+.P
+The internal boundaries are not interpreted as the beginnings or ends of lines
+and so do not match circumflex or dollar characters in the pattern.
+.P
+If \fBpcre2_match()\fP is called with an offset that points to an invalid
+UTF-sequence, that sequence is skipped, and the match starts at the next valid
+UTF character, or the end of the subject.
+.P
+At internal fragment boundaries, \eb and \eB behave in the same way as at the
+beginning and end of the subject. For example, a sequence such as \ebWORD\eb
+would match an instance of WORD that is surrounded by invalid UTF code units.
+.P
+Using PCRE2_MATCH_INVALID_UTF, an application can run matches on arbitrary
+data, knowing that any matched strings that are returned are valid UTF. This
+can be useful when searching for UTF text in executable or other binary files.
+.
+.
.SH AUTHOR
.rs
.sp
@@ -285,6 +455,6 @@ Cambridge, England.
.rs
.sp
.nf
-Last updated: 02 September 2018
-Copyright (c) 1997-2018 University of Cambridge.
+Last updated: 24 May 2019
+Copyright (c) 1997-2019 University of Cambridge.
.fi
diff --git a/install-sh b/install-sh
index 0360b79..8175c64 100755
--- a/install-sh
+++ b/install-sh
@@ -1,7 +1,7 @@
#!/bin/sh
# install - install a program, script, or datafile
-scriptversion=2016-01-11.22; # UTC
+scriptversion=2018-03-11.20; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
@@ -271,15 +271,18 @@ do
fi
dst=$dst_arg
- # If destination is a directory, append the input filename; won't work
- # if double slashes aren't ignored.
+ # If destination is a directory, append the input filename.
if test -d "$dst"; then
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
- dst=$dstdir/`basename "$src"`
+ dstbase=`basename "$src"`
+ case $dst in
+ */) dst=$dst$dstbase;;
+ *) dst=$dst/$dstbase;;
+ esac
dstdir_status=0
else
dstdir=`dirname "$dst"`
@@ -288,6 +291,11 @@ do
fi
fi
+ case $dstdir in
+ */) dstdirslash=$dstdir;;
+ *) dstdirslash=$dstdir/;;
+ esac
+
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
@@ -324,34 +332,43 @@ do
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
+ # Note that $RANDOM variable is not portable (e.g. dash); Use it
+ # here however when possible just to lower collision chance.
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
- trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+ trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ # Because "mkdir -p" follows existing symlinks and we likely work
+ # directly in world-writeable /tmp, make sure that the '$tmpdir'
+ # directory is successfully created first before we actually test
+ # 'mkdir -p' feature.
if (umask $mkdir_umask &&
- exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ $mkdirprog $mkdir_mode "$tmpdir" &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
- ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ test_tmpdir="$tmpdir/a"
+ ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
- $mkdirprog -m$different_mode -p -- "$tmpdir" && {
- ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
- rmdir "$tmpdir/d" "$tmpdir"
+ rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
- rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi
trap '' 0;;
esac;;
@@ -427,8 +444,8 @@ do
else
# Make a couple of temp file names in the proper directory.
- dsttmp=$dstdir/_inst.$$_
- rmtmp=$dstdir/_rm.$$_
+ dsttmp=${dstdirslash}_inst.$$_
+ rmtmp=${dstdirslash}_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
@@ -493,7 +510,7 @@ do
done
# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
+# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
diff --git a/ltmain.sh b/ltmain.sh
index 857338f..d3ab94d 100644
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -1,12 +1,12 @@
#! /bin/sh
## DO NOT EDIT - This file generated from ./build-aux/ltmain.in
-## by inline-source v2016-02-21.11
+## by inline-source v2018-07-24.06
-# libtool (GNU libtool) 2.4.6.40-6ca5-dirty
+# libtool (GNU libtool) 2.4.6.42-b88ce
# Provide generalized library-building support services.
# Written by Gordon Matzigkeit , 1996
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2018 Free Software Foundation, Inc.
# This is free software; see the source for copying conditions. There is NO
# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
@@ -31,8 +31,8 @@
PROGRAM=libtool
PACKAGE=libtool
-VERSION=2.4.6.40-6ca5-dirty
-package_revision=2.4.6.40
+VERSION=2.4.6.42-b88ce
+package_revision=2.4.6.42
## ------ ##
@@ -64,7 +64,7 @@ package_revision=2.4.6.40
# libraries, which are installed to $pkgauxdir.
# Set a version string for this script.
-scriptversion=2017-04-19.12; # UTC
+scriptversion=2018-07-24.06; # UTC
# General shell script boiler plate, and helper functions.
# Written by Gary V. Vaughan, 2004
@@ -72,7 +72,7 @@ scriptversion=2017-04-19.12; # UTC
# This is free software. There is NO warranty; not even for
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
-# Copyright (C) 2004-2017 Bootstrap Authors
+# Copyright (C) 2004-2018 Bootstrap Authors
#
# This file is dual licensed under the terms of the MIT license
# , and GPL version 3 or later
@@ -1497,7 +1497,7 @@ func_lt_ver ()
# This is free software. There is NO warranty; not even for
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
-# Copyright (C) 2010-2017 Bootstrap Authors
+# Copyright (C) 2010-2018 Bootstrap Authors
#
# This file is dual licensed under the terms of the MIT license
# , and GPL version 3 or later
@@ -1510,7 +1510,7 @@ func_lt_ver ()
#
# Set a version string for this script.
-scriptversion=2016-03-06.01; # UTC
+scriptversion=2018-07-24.06; # UTC
## ------ ##
@@ -2171,12 +2171,12 @@ func_version ()
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'before-save-hook 'time-stamp)
-# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC"
+# time-stamp-pattern: "30/scriptversion=%:y-%02m-%02d.%02H; # UTC"
# time-stamp-time-zone: "UTC"
# End:
# Set a version string.
-scriptversion='(GNU libtool) 2.4.6.40-6ca5-dirty'
+scriptversion='(GNU libtool) 2.4.6.42-b88ce'
# func_echo ARG...
@@ -2267,7 +2267,7 @@ include the following information:
compiler: $LTCC
compiler flags: $LTCFLAGS
linker: $LD (gnu? $with_gnu_ld)
- version: $progname (GNU libtool) 2.4.6.40-6ca5-dirty
+ version: $progname (GNU libtool) 2.4.6.42-b88ce
automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q`
diff --git a/m4/libtool.m4 b/m4/libtool.m4
index 597c604..b55a6e5 100644
--- a/m4/libtool.m4
+++ b/m4/libtool.m4
@@ -1,6 +1,6 @@
# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
#
-# Copyright (C) 1996-2001, 2003-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2001, 2003-2018 Free Software Foundation, Inc.
# Written by Gordon Matzigkeit, 1996
#
# This file is free software; the Free Software Foundation gives
@@ -219,8 +219,8 @@ esac
ofile=libtool
can_build_shared=yes
-# All known linkers require a '.a' archive for static linking (except MSVC,
-# which needs '.lib').
+# All known linkers require a '.a' archive for static linking (except MSVC and
+# ICC, which need '.lib').
libext=a
with_gnu_ld=$lt_cv_prog_gnu_ld
@@ -2587,8 +2587,8 @@ m4_if([$1], [],[
dynamic_linker='Win32 ld.exe'
;;
- *,cl*)
- # Native MSVC
+ *,cl* | *,icl*)
+ # Native MSVC or ICC
libname_spec='$name'
soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
library_names_spec='$libname.dll.lib'
@@ -2644,7 +2644,7 @@ m4_if([$1], [],[
;;
*)
- # Assume MSVC wrapper
+ # Assume MSVC and ICC wrapper
library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
dynamic_linker='Win32 ld.exe'
;;
@@ -4032,7 +4032,7 @@ for ac_symprfx in "" "_"; do
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
# Fake it for dumpbin and say T for any non-static function,
# D for any global variable and I for any imported variable.
- # Also find C++ and __fastcall symbols from MSVC++,
+ # Also find C++ and __fastcall symbols from MSVC++ or ICC,
# which start with @ or ?.
lt_cv_sys_global_symbol_pipe="$AWK ['"\
" {last_section=section; section=\$ 3};"\
@@ -4949,7 +4949,7 @@ m4_if([$1], [CXX], [
;;
cygwin* | mingw* | cegcc*)
case $cc_basename in
- cl*)
+ cl* | icl*)
_LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
;;
*)
@@ -5006,15 +5006,15 @@ dnl Note also adjust exclude_expsyms for C++ above.
case $host_os in
cygwin* | mingw* | pw32* | cegcc*)
- # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
# When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
+ # Microsoft Visual C++ or Intel C++ Compiler.
if test yes != "$GCC"; then
with_gnu_ld=no
fi
;;
interix*)
- # we just hope/assume this is gcc and not c89 (= MSVC++)
+ # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
with_gnu_ld=yes
;;
openbsd* | bitrig*)
@@ -5579,12 +5579,12 @@ _LT_EOF
cygwin* | mingw* | pw32* | cegcc*)
# When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
+ # Microsoft Visual C++ or Intel C++ Compiler.
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
case $cc_basename in
- cl*)
- # Native MSVC
+ cl* | icl*)
+ # Native MSVC or ICC
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=yes
@@ -5625,7 +5625,7 @@ _LT_EOF
fi'
;;
*)
- # Assume MSVC wrapper
+ # Assume MSVC and ICC wrapper
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
# Tell ltmain to make .lib files, not .a files.
@@ -6655,8 +6655,8 @@ if test yes != "$_lt_caught_CXX_error"; then
cygwin* | mingw* | pw32* | cegcc*)
case $GXX,$cc_basename in
- ,cl* | no,cl*)
- # Native MSVC
+ ,cl* | no,cl* | ,icl* | no,icl*)
+ # Native MSVC or ICC
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4
index 621bd18..07421d9 100644
--- a/m4/ltoptions.m4
+++ b/m4/ltoptions.m4
@@ -1,6 +1,6 @@
# Helper functions for option handling. -*- Autoconf -*-
#
-# Copyright (C) 2004-2005, 2007-2009, 2011-2017 Free Software
+# Copyright (C) 2004-2005, 2007-2009, 2011-2018 Free Software
# Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4
index ab69a6b..3985c56 100644
--- a/m4/ltsugar.m4
+++ b/m4/ltsugar.m4
@@ -1,6 +1,6 @@
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
-# Copyright (C) 2004-2005, 2007-2008, 2011-2017 Free Software
+# Copyright (C) 2004-2005, 2007-2008, 2011-2018 Free Software
# Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
diff --git a/m4/ltversion.m4 b/m4/ltversion.m4
index 8250ea4..86b2ad7 100644
--- a/m4/ltversion.m4
+++ b/m4/ltversion.m4
@@ -1,6 +1,6 @@
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
-# Copyright (C) 2004, 2011-2017 Free Software Foundation, Inc.
+# Copyright (C) 2004, 2011-2018 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004
#
# This file is free software; the Free Software Foundation gives
@@ -9,15 +9,15 @@
# @configure_input@
-# serial 4219 ltversion.m4
+# serial 4221 ltversion.m4
# This file is part of GNU Libtool
-m4_define([LT_PACKAGE_VERSION], [2.4.6.40-6ca5-dirty])
-m4_define([LT_PACKAGE_REVISION], [2.4.6.40])
+m4_define([LT_PACKAGE_VERSION], [2.4.6.42-b88ce])
+m4_define([LT_PACKAGE_REVISION], [2.4.6.42])
AC_DEFUN([LTVERSION_VERSION],
-[macro_version='2.4.6.40-6ca5-dirty'
-macro_revision='2.4.6.40'
+[macro_version='2.4.6.42-b88ce'
+macro_revision='2.4.6.42'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])
diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4
index 9919d4d..54ea1c4 100644
--- a/m4/lt~obsolete.m4
+++ b/m4/lt~obsolete.m4
@@ -1,6 +1,6 @@
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
-# Copyright (C) 2004-2005, 2007, 2009, 2011-2017 Free Software
+# Copyright (C) 2004-2005, 2007, 2009, 2011-2018 Free Software
# Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
diff --git a/missing b/missing
index c6e3795..625aeb1 100755
--- a/missing
+++ b/missing
@@ -1,9 +1,9 @@
#! /bin/sh
# Common wrapper for a few potentially missing GNU programs.
-scriptversion=2016-01-11.22; # UTC
+scriptversion=2018-03-07.03; # UTC
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2018 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard , 1996.
# This program is free software; you can redistribute it and/or modify
@@ -17,7 +17,7 @@ scriptversion=2016-01-11.22; # UTC
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
+# along with this program. If not, see .
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -101,9 +101,9 @@ else
exit $st
fi
-perl_URL=http://www.perl.org/
-flex_URL=http://flex.sourceforge.net/
-gnu_software_URL=http://www.gnu.org/software
+perl_URL=https://www.perl.org/
+flex_URL=https://github.com/westes/flex
+gnu_software_URL=https://www.gnu.org/software
program_details ()
{
@@ -207,7 +207,7 @@ give_advice "$1" | sed -e '1s/^/WARNING: /' \
exit $st
# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
+# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
diff --git a/perltest.sh b/perltest.sh
index 5e6c466..8368781 100755
--- a/perltest.sh
+++ b/perltest.sh
@@ -1,8 +1,10 @@
#! /bin/sh
# Script for testing regular expressions with perl to check that PCRE2 handles
-# them the same. If the first argument to this script is "-w", Perl is also
-# called with "-w", which turns on its warning mode.
+# them the same. For testing with different versions of Perl, if the first
+# argument is -perl then the second is taken as the Perl command to use, and
+# both are then removed. If the next argument is "-w", Perl is called with
+# "-w", which turns on its warning mode.
#
# The Perl code has to have "use utf8" and "require Encode" at the start when
# running UTF-8 tests, but *not* for non-utf8 tests. (The "require" would
@@ -10,8 +12,8 @@
# the script will always run for these tests.)
#
# The desired effect is achieved by making this a shell script that passes the
-# Perl script to Perl through a pipe. If the first argument (possibly after
-# removing "-w") is "-utf8", a suitable prefix is set up.
+# Perl script to Perl through a pipe. If the next argument is "-utf8", a
+# suitable prefix is set up.
#
# The remaining arguments, if any, are passed to Perl. They are an input file
# and an output file. If there is one argument, the output is written to
@@ -23,6 +25,12 @@ perl=perl
perlarg=''
prefix=''
+if [ $# -gt 1 -a "$1" = "-perl" ] ; then
+ shift
+ perl=$1
+ shift
+fi
+
if [ $# -gt 0 -a "$1" = "-w" ] ; then
perlarg="-w"
shift
@@ -75,6 +83,11 @@ fi
(echo "$prefix" ; cat <<'PERLEND'
+# The alpha assertions currently give warnings even when -w is not specified.
+
+no warnings "experimental::alpha_assertions";
+no warnings "experimental::script_run";
+
# Function for turning a string into a string of printing chars.
sub pchars {
@@ -127,7 +140,10 @@ if (@ARGV > 1)
}
else { $outfile = "STDOUT"; }
-printf($outfile "Perl $] Regular Expressions\n\n");
+printf($outfile "Perl $^V\n\n");
+
+$extra_modifiers = "";
+$default_show_mark = 0;
# Main loop
@@ -370,7 +386,10 @@ for (;;)
}
}
-# printf $outfile "\n";
+# By closing OUTFILE explicitly, we avoid a Perl warning in -w mode
+# "main::OUTFILE" used only once".
+
+close(OUTFILE) if $outfile eq "OUTFILE";
PERLEND
) | $perl $perlarg - $@
diff --git a/src/config.h.generic b/src/config.h.generic
index 89a52ef..787bb9c 100644
--- a/src/config.h.generic
+++ b/src/config.h.generic
@@ -35,6 +35,10 @@ sure both macros are undefined; an emulation function will then be used. */
*/
/* #undef BSR_ANYCRLF */
+/* Define to any value to disable the use of the z and t modifiers in
+ formatting settings such as %zu or %td (this is rarely needed). */
+/* #undef DISABLE_PERCENT_ZT */
+
/* If you are compiling for a system that uses EBCDIC instead of ASCII
character codes, define this macro to any value. When EBCDIC is set, PCRE2
assumes that all input strings are in EBCDIC. If you do not define this
@@ -214,7 +218,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_NAME "PCRE2"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "PCRE2 10.32"
+#define PACKAGE_STRING "PCRE2 10.34"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "pcre2"
@@ -223,7 +227,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "10.32"
+#define PACKAGE_VERSION "10.34"
/* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested
parentheses (of any kind) in a pattern. This limits the amount of system
@@ -299,6 +303,11 @@ sure both macros are undefined; an emulation function will then be used. */
/* Define to any value to enable callout script support in pcre2grep. */
/* #undef SUPPORT_PCRE2GREP_CALLOUT */
+/* Define to any value to enable fork support in pcre2grep callout scripts.
+ This will have no effect unless SUPPORT_PCRE2GREP_CALLOUT is also defined.
+ */
+/* #undef SUPPORT_PCRE2GREP_CALLOUT_FORK */
+
/* Define to any value to enable JIT support in pcre2grep. Note that this will
have no effect unless SUPPORT_JIT is also defined. */
/* #undef SUPPORT_PCRE2GREP_JIT */
@@ -343,7 +352,7 @@ sure both macros are undefined; an emulation function will then be used. */
#endif
/* Version number of package */
-#define VERSION "10.32"
+#define VERSION "10.34"
/* Define to 1 if on MINIX. */
/* #undef _MINIX */
diff --git a/src/config.h.in b/src/config.h.in
index d8a5280..6b8eb7e 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -35,6 +35,10 @@ sure both macros are undefined; an emulation function will then be used. */
*/
#undef BSR_ANYCRLF
+/* Define to any value to disable the use of the z and t modifiers in
+ formatting settings such as %zu or %td (this is rarely needed). */
+#undef DISABLE_PERCENT_ZT
+
/* If you are compiling for a system that uses EBCDIC instead of ASCII
character codes, define this macro to any value. When EBCDIC is set, PCRE2
assumes that all input strings are in EBCDIC. If you do not define this
@@ -286,6 +290,11 @@ sure both macros are undefined; an emulation function will then be used. */
/* Define to any value to enable callout script support in pcre2grep. */
#undef SUPPORT_PCRE2GREP_CALLOUT
+/* Define to any value to enable fork support in pcre2grep callout scripts.
+ This will have no effect unless SUPPORT_PCRE2GREP_CALLOUT is also defined.
+ */
+#undef SUPPORT_PCRE2GREP_CALLOUT_FORK
+
/* Define to any value to enable JIT support in pcre2grep. Note that this will
have no effect unless SUPPORT_JIT is also defined. */
#undef SUPPORT_PCRE2GREP_JIT
diff --git a/src/dftables.c b/src/dftables.c
index c0af362..02796cc 100644
--- a/src/dftables.c
+++ b/src/dftables.c
@@ -183,10 +183,10 @@ fprintf(f,
"/* This table identifies various classes of character by individual bits:\n"
" 0x%02x white space character\n"
" 0x%02x letter\n"
+ " 0x%02x lower case letter\n"
" 0x%02x decimal digit\n"
- " 0x%02x hexadecimal digit\n"
" 0x%02x alphanumeric or '_'\n*/\n\n",
- ctype_space, ctype_letter, ctype_digit, ctype_xdigit, ctype_word);
+ ctype_space, ctype_letter, ctype_lcletter, ctype_digit, ctype_word);
fprintf(f, " ");
for (i = 0; i < 256; i++)
diff --git a/src/pcre2.h.generic b/src/pcre2.h.generic
index 3d2feb7..cb9d61a 100644
--- a/src/pcre2.h.generic
+++ b/src/pcre2.h.generic
@@ -5,7 +5,7 @@
/* This is the public header file for the PCRE library, second API, to be
#included by applications that call PCRE2 functions.
- Copyright (c) 2016-2018 University of Cambridge
+ Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -42,15 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */
#define PCRE2_MAJOR 10
-#define PCRE2_MINOR 32
+#define PCRE2_MINOR 34
#define PCRE2_PRERELEASE
-#define PCRE2_DATE 2018-09-10
-
-/* For the benefit of systems without stdint.h, an alternative is to use
-inttypes.h. The existence of these headers is checked by configure or CMake. */
-
-#define PCRE2_HAVE_STDINT_H 1
-#define PCRE2_HAVE_INTTYPES_H 1
+#define PCRE2_DATE 2019-11-21
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE2, the appropriate
@@ -87,18 +81,15 @@ set, we ensure here that it has no effect. */
#define PCRE2_CALL_CONVENTION
#endif
-/* Have to include limits.h, stdlib.h and stdint.h (or inttypes.h) to ensure
-that size_t and uint8_t, UCHAR_MAX, etc are defined. If the system has neither
-header, the relevant values must be provided by some other means. */
+/* Have to include limits.h, stdlib.h, and inttypes.h to ensure that size_t and
+uint8_t, UCHAR_MAX, etc are defined. Some systems that do have inttypes.h do
+not have stdint.h, which is why we use inttypes.h, which according to the C
+standard is a superset of stdint.h. If none of these headers are available,
+the relevant values must be provided by some other means. */
#include
#include
-
-#if PCRE2_HAVE_STDINT_H
-#include
-#elif PCRE2_HAVE_INTTYPES_H
#include
-#endif
/* Allow for C++ users compiling this directly. */
@@ -151,6 +142,7 @@ D is inspected during pcre2_dfa_match() execution
#define PCRE2_USE_OFFSET_LIMIT 0x00800000u /* J M D */
#define PCRE2_EXTENDED_MORE 0x01000000u /* C */
#define PCRE2_LITERAL 0x02000000u /* C */
+#define PCRE2_MATCH_INVALID_UTF 0x04000000u /* J M D */
/* An additional compile options word is available in the compile context. */
@@ -158,43 +150,37 @@ D is inspected during pcre2_dfa_match() execution
#define PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL 0x00000002u /* C */
#define PCRE2_EXTRA_MATCH_WORD 0x00000004u /* C */
#define PCRE2_EXTRA_MATCH_LINE 0x00000008u /* C */
+#define PCRE2_EXTRA_ESCAPED_CR_IS_LF 0x00000010u /* C */
+#define PCRE2_EXTRA_ALT_BSUX 0x00000020u /* C */
/* These are for pcre2_jit_compile(). */
#define PCRE2_JIT_COMPLETE 0x00000001u /* For full matching */
#define PCRE2_JIT_PARTIAL_SOFT 0x00000002u
#define PCRE2_JIT_PARTIAL_HARD 0x00000004u
-
-/* These are for pcre2_match(), pcre2_dfa_match(), and pcre2_jit_match(). Note
-that PCRE2_ANCHORED and PCRE2_NO_UTF_CHECK can also be passed to these
-functions (though pcre2_jit_match() ignores the latter since it bypasses all
-sanity checks). */
-
-#define PCRE2_NOTBOL 0x00000001u
-#define PCRE2_NOTEOL 0x00000002u
-#define PCRE2_NOTEMPTY 0x00000004u /* ) These two must be kept */
-#define PCRE2_NOTEMPTY_ATSTART 0x00000008u /* ) adjacent to each other. */
-#define PCRE2_PARTIAL_SOFT 0x00000010u
-#define PCRE2_PARTIAL_HARD 0x00000020u
-
-/* These are additional options for pcre2_dfa_match(). */
-
-#define PCRE2_DFA_RESTART 0x00000040u
-#define PCRE2_DFA_SHORTEST 0x00000080u
-
-/* These are additional options for pcre2_substitute(), which passes any others
-through to pcre2_match(). */
-
-#define PCRE2_SUBSTITUTE_GLOBAL 0x00000100u
-#define PCRE2_SUBSTITUTE_EXTENDED 0x00000200u
-#define PCRE2_SUBSTITUTE_UNSET_EMPTY 0x00000400u
-#define PCRE2_SUBSTITUTE_UNKNOWN_UNSET 0x00000800u
-#define PCRE2_SUBSTITUTE_OVERFLOW_LENGTH 0x00001000u
-
-/* A further option for pcre2_match(), not allowed for pcre2_dfa_match(),
-ignored for pcre2_jit_match(). */
-
-#define PCRE2_NO_JIT 0x00002000u
+#define PCRE2_JIT_INVALID_UTF 0x00000100u
+
+/* These are for pcre2_match(), pcre2_dfa_match(), pcre2_jit_match(), and
+pcre2_substitute(). Some are allowed only for one of the functions, and in
+these cases it is noted below. Note that PCRE2_ANCHORED, PCRE2_ENDANCHORED and
+PCRE2_NO_UTF_CHECK can also be passed to these functions (though
+pcre2_jit_match() ignores the latter since it bypasses all sanity checks). */
+
+#define PCRE2_NOTBOL 0x00000001u
+#define PCRE2_NOTEOL 0x00000002u
+#define PCRE2_NOTEMPTY 0x00000004u /* ) These two must be kept */
+#define PCRE2_NOTEMPTY_ATSTART 0x00000008u /* ) adjacent to each other. */
+#define PCRE2_PARTIAL_SOFT 0x00000010u
+#define PCRE2_PARTIAL_HARD 0x00000020u
+#define PCRE2_DFA_RESTART 0x00000040u /* pcre2_dfa_match() only */
+#define PCRE2_DFA_SHORTEST 0x00000080u /* pcre2_dfa_match() only */
+#define PCRE2_SUBSTITUTE_GLOBAL 0x00000100u /* pcre2_substitute() only */
+#define PCRE2_SUBSTITUTE_EXTENDED 0x00000200u /* pcre2_substitute() only */
+#define PCRE2_SUBSTITUTE_UNSET_EMPTY 0x00000400u /* pcre2_substitute() only */
+#define PCRE2_SUBSTITUTE_UNKNOWN_UNSET 0x00000800u /* pcre2_substitute() only */
+#define PCRE2_SUBSTITUTE_OVERFLOW_LENGTH 0x00001000u /* pcre2_substitute() only */
+#define PCRE2_NO_JIT 0x00002000u /* Not for pcre2_dfa_match() */
+#define PCRE2_COPY_MATCHED_SUBJECT 0x00004000u
/* Options for pcre2_pattern_convert(). */
@@ -318,6 +304,10 @@ pcre2_pattern_convert(). */
#define PCRE2_ERROR_BAD_LITERAL_OPTIONS 192
#define PCRE2_ERROR_SUPPORTED_ONLY_IN_UNICODE 193
#define PCRE2_ERROR_INVALID_HYPHEN_IN_OPTIONS 194
+#define PCRE2_ERROR_ALPHA_ASSERTION_UNKNOWN 195
+#define PCRE2_ERROR_SCRIPT_RUN_NOT_AVAILABLE 196
+#define PCRE2_ERROR_TOO_MANY_CAPTURES 197
+#define PCRE2_ERROR_CONDITION_ATOMIC_ASSERTION_EXPECTED 198
/* "Expected" matching error codes: no match and partial match. */
@@ -403,6 +393,7 @@ released, the numbers must not be changed. */
#define PCRE2_ERROR_HEAPLIMIT (-63)
#define PCRE2_ERROR_CONVERT_SYNTAX (-64)
#define PCRE2_ERROR_INTERNAL_DUPMATCH (-65)
+#define PCRE2_ERROR_DFA_UINVALID_UTF (-66)
/* Request types for pcre2_pattern_info() */
@@ -504,10 +495,10 @@ typedef struct pcre2_real_jit_stack pcre2_jit_stack; \
typedef pcre2_jit_stack *(*pcre2_jit_callback)(void *);
-/* The structure for passing out data via the pcre_callout_function. We use a
-structure so that new fields can be added on the end in future versions,
-without changing the API of the function, thereby allowing old clients to work
-without modification. Define the generic version in a macro; the width-specific
+/* The structures for passing out data via callout functions. We use structures
+so that new fields can be added on the end in future versions, without changing
+the API of the function, thereby allowing old clients to work without
+modification. Define the generic versions in a macro; the width-specific
versions are generated from this macro below. */
/* Flags for the callout_flags field. These are cleared after a callout. */
@@ -549,7 +540,19 @@ typedef struct pcre2_callout_enumerate_block { \
PCRE2_SIZE callout_string_length; /* Length of string compiled into pattern */ \
PCRE2_SPTR callout_string; /* String compiled into pattern */ \
/* ------------------------------------------------------------------ */ \
-} pcre2_callout_enumerate_block;
+} pcre2_callout_enumerate_block; \
+\
+typedef struct pcre2_substitute_callout_block { \
+ uint32_t version; /* Identifies version of block */ \
+ /* ------------------------ Version 0 ------------------------------- */ \
+ PCRE2_SPTR input; /* Pointer to input subject string */ \
+ PCRE2_SPTR output; /* Pointer to output buffer */ \
+ PCRE2_SIZE output_offsets[2]; /* Changed portion of the output */ \
+ PCRE2_SIZE *ovector; /* Pointer to current ovector */ \
+ uint32_t oveccount; /* Count of pairs set in ovector */ \
+ uint32_t subscount; /* Substitution number */ \
+ /* ------------------------------------------------------------------ */ \
+} pcre2_substitute_callout_block;
/* List the generic forms of all other functions in macros, which will be
@@ -581,7 +584,7 @@ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_bsr(pcre2_compile_context *, uint32_t); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
- pcre2_set_character_tables(pcre2_compile_context *, const unsigned char *); \
+ pcre2_set_character_tables(pcre2_compile_context *, const uint8_t *); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_compile_extra_options(pcre2_compile_context *, uint32_t); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
@@ -604,6 +607,9 @@ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_callout(pcre2_match_context *, \
int (*)(pcre2_callout_block *, void *), void *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_substitute_callout(pcre2_match_context *, \
+ int (*)(pcre2_substitute_callout_block *, void *), void *); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_depth_limit(pcre2_match_context *, uint32_t); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
@@ -673,6 +679,8 @@ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
pcre2_match_data_free(pcre2_match_data *); \
PCRE2_EXP_DECL PCRE2_SPTR PCRE2_CALL_CONVENTION \
pcre2_get_mark(pcre2_match_data *); \
+PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \
+ pcre2_get_match_data_size(pcre2_match_data *); \
PCRE2_EXP_DECL uint32_t PCRE2_CALL_CONVENTION \
pcre2_get_ovector_count(pcre2_match_data *); \
PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \
@@ -771,7 +779,8 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_get_error_message(int, PCRE2_UCHAR *, PCRE2_SIZE); \
PCRE2_EXP_DECL const uint8_t PCRE2_CALL_CONVENTION \
*pcre2_maketables(pcre2_general_context *); \
-
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ pcre2_maketables_free(pcre2_general_context *, const uint8_t *);
/* Define macros that generate width-specific names from generic versions. The
three-level macro scheme is necessary to get the macros expanded when we want
@@ -807,6 +816,7 @@ pcre2_compile are called by application code. */
#define pcre2_callout_block PCRE2_SUFFIX(pcre2_callout_block_)
#define pcre2_callout_enumerate_block PCRE2_SUFFIX(pcre2_callout_enumerate_block_)
+#define pcre2_substitute_callout_block PCRE2_SUFFIX(pcre2_substitute_callout_block_)
#define pcre2_general_context PCRE2_SUFFIX(pcre2_general_context_)
#define pcre2_compile_context PCRE2_SUFFIX(pcre2_compile_context_)
#define pcre2_convert_context PCRE2_SUFFIX(pcre2_convert_context_)
@@ -835,6 +845,7 @@ pcre2_compile are called by application code. */
#define pcre2_general_context_free PCRE2_SUFFIX(pcre2_general_context_free_)
#define pcre2_get_error_message PCRE2_SUFFIX(pcre2_get_error_message_)
#define pcre2_get_mark PCRE2_SUFFIX(pcre2_get_mark_)
+#define pcre2_get_match_data_size PCRE2_SUFFIX(pcre2_get_match_data_size_)
#define pcre2_get_ovector_pointer PCRE2_SUFFIX(pcre2_get_ovector_pointer_)
#define pcre2_get_ovector_count PCRE2_SUFFIX(pcre2_get_ovector_count_)
#define pcre2_get_startchar PCRE2_SUFFIX(pcre2_get_startchar_)
@@ -845,6 +856,7 @@ pcre2_compile are called by application code. */
#define pcre2_jit_stack_create PCRE2_SUFFIX(pcre2_jit_stack_create_)
#define pcre2_jit_stack_free PCRE2_SUFFIX(pcre2_jit_stack_free_)
#define pcre2_maketables PCRE2_SUFFIX(pcre2_maketables_)
+#define pcre2_maketables_free PCRE2_SUFFIX(pcre2_maketables_free_)
#define pcre2_match PCRE2_SUFFIX(pcre2_match_)
#define pcre2_match_context_copy PCRE2_SUFFIX(pcre2_match_context_copy_)
#define pcre2_match_context_create PCRE2_SUFFIX(pcre2_match_context_create_)
@@ -872,6 +884,7 @@ pcre2_compile are called by application code. */
#define pcre2_set_newline PCRE2_SUFFIX(pcre2_set_newline_)
#define pcre2_set_parens_nest_limit PCRE2_SUFFIX(pcre2_set_parens_nest_limit_)
#define pcre2_set_offset_limit PCRE2_SUFFIX(pcre2_set_offset_limit_)
+#define pcre2_set_substitute_callout PCRE2_SUFFIX(pcre2_set_substitute_callout_)
#define pcre2_substitute PCRE2_SUFFIX(pcre2_substitute_)
#define pcre2_substring_copy_byname PCRE2_SUFFIX(pcre2_substring_copy_byname_)
#define pcre2_substring_copy_bynumber PCRE2_SUFFIX(pcre2_substring_copy_bynumber_)
diff --git a/src/pcre2.h.in b/src/pcre2.h.in
index a9396e0..9a0ad0b 100644
--- a/src/pcre2.h.in
+++ b/src/pcre2.h.in
@@ -5,7 +5,7 @@
/* This is the public header file for the PCRE library, second API, to be
#included by applications that call PCRE2 functions.
- Copyright (c) 2016-2018 University of Cambridge
+ Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -46,12 +46,6 @@ POSSIBILITY OF SUCH DAMAGE.
#define PCRE2_PRERELEASE @PCRE2_PRERELEASE@
#define PCRE2_DATE @PCRE2_DATE@
-/* For the benefit of systems without stdint.h, an alternative is to use
-inttypes.h. The existence of these headers is checked by configure or CMake. */
-
-#define PCRE2_HAVE_STDINT_H @PCRE2_HAVE_STDINT_H@
-#define PCRE2_HAVE_INTTYPES_H @PCRE2_HAVE_INTTYPES_H@
-
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE2, the appropriate
export setting is defined in pcre2_internal.h, which includes this file. So we
@@ -87,18 +81,15 @@ set, we ensure here that it has no effect. */
#define PCRE2_CALL_CONVENTION
#endif
-/* Have to include limits.h, stdlib.h and stdint.h (or inttypes.h) to ensure
-that size_t and uint8_t, UCHAR_MAX, etc are defined. If the system has neither
-header, the relevant values must be provided by some other means. */
+/* Have to include limits.h, stdlib.h, and inttypes.h to ensure that size_t and
+uint8_t, UCHAR_MAX, etc are defined. Some systems that do have inttypes.h do
+not have stdint.h, which is why we use inttypes.h, which according to the C
+standard is a superset of stdint.h. If none of these headers are available,
+the relevant values must be provided by some other means. */
#include
#include
-
-#if PCRE2_HAVE_STDINT_H
-#include
-#elif PCRE2_HAVE_INTTYPES_H
#include
-#endif
/* Allow for C++ users compiling this directly. */
@@ -151,6 +142,7 @@ D is inspected during pcre2_dfa_match() execution
#define PCRE2_USE_OFFSET_LIMIT 0x00800000u /* J M D */
#define PCRE2_EXTENDED_MORE 0x01000000u /* C */
#define PCRE2_LITERAL 0x02000000u /* C */
+#define PCRE2_MATCH_INVALID_UTF 0x04000000u /* J M D */
/* An additional compile options word is available in the compile context. */
@@ -158,43 +150,37 @@ D is inspected during pcre2_dfa_match() execution
#define PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL 0x00000002u /* C */
#define PCRE2_EXTRA_MATCH_WORD 0x00000004u /* C */
#define PCRE2_EXTRA_MATCH_LINE 0x00000008u /* C */
+#define PCRE2_EXTRA_ESCAPED_CR_IS_LF 0x00000010u /* C */
+#define PCRE2_EXTRA_ALT_BSUX 0x00000020u /* C */
/* These are for pcre2_jit_compile(). */
#define PCRE2_JIT_COMPLETE 0x00000001u /* For full matching */
#define PCRE2_JIT_PARTIAL_SOFT 0x00000002u
#define PCRE2_JIT_PARTIAL_HARD 0x00000004u
-
-/* These are for pcre2_match(), pcre2_dfa_match(), and pcre2_jit_match(). Note
-that PCRE2_ANCHORED and PCRE2_NO_UTF_CHECK can also be passed to these
-functions (though pcre2_jit_match() ignores the latter since it bypasses all
-sanity checks). */
-
-#define PCRE2_NOTBOL 0x00000001u
-#define PCRE2_NOTEOL 0x00000002u
-#define PCRE2_NOTEMPTY 0x00000004u /* ) These two must be kept */
-#define PCRE2_NOTEMPTY_ATSTART 0x00000008u /* ) adjacent to each other. */
-#define PCRE2_PARTIAL_SOFT 0x00000010u
-#define PCRE2_PARTIAL_HARD 0x00000020u
-
-/* These are additional options for pcre2_dfa_match(). */
-
-#define PCRE2_DFA_RESTART 0x00000040u
-#define PCRE2_DFA_SHORTEST 0x00000080u
-
-/* These are additional options for pcre2_substitute(), which passes any others
-through to pcre2_match(). */
-
-#define PCRE2_SUBSTITUTE_GLOBAL 0x00000100u
-#define PCRE2_SUBSTITUTE_EXTENDED 0x00000200u
-#define PCRE2_SUBSTITUTE_UNSET_EMPTY 0x00000400u
-#define PCRE2_SUBSTITUTE_UNKNOWN_UNSET 0x00000800u
-#define PCRE2_SUBSTITUTE_OVERFLOW_LENGTH 0x00001000u
-
-/* A further option for pcre2_match(), not allowed for pcre2_dfa_match(),
-ignored for pcre2_jit_match(). */
-
-#define PCRE2_NO_JIT 0x00002000u
+#define PCRE2_JIT_INVALID_UTF 0x00000100u
+
+/* These are for pcre2_match(), pcre2_dfa_match(), pcre2_jit_match(), and
+pcre2_substitute(). Some are allowed only for one of the functions, and in
+these cases it is noted below. Note that PCRE2_ANCHORED, PCRE2_ENDANCHORED and
+PCRE2_NO_UTF_CHECK can also be passed to these functions (though
+pcre2_jit_match() ignores the latter since it bypasses all sanity checks). */
+
+#define PCRE2_NOTBOL 0x00000001u
+#define PCRE2_NOTEOL 0x00000002u
+#define PCRE2_NOTEMPTY 0x00000004u /* ) These two must be kept */
+#define PCRE2_NOTEMPTY_ATSTART 0x00000008u /* ) adjacent to each other. */
+#define PCRE2_PARTIAL_SOFT 0x00000010u
+#define PCRE2_PARTIAL_HARD 0x00000020u
+#define PCRE2_DFA_RESTART 0x00000040u /* pcre2_dfa_match() only */
+#define PCRE2_DFA_SHORTEST 0x00000080u /* pcre2_dfa_match() only */
+#define PCRE2_SUBSTITUTE_GLOBAL 0x00000100u /* pcre2_substitute() only */
+#define PCRE2_SUBSTITUTE_EXTENDED 0x00000200u /* pcre2_substitute() only */
+#define PCRE2_SUBSTITUTE_UNSET_EMPTY 0x00000400u /* pcre2_substitute() only */
+#define PCRE2_SUBSTITUTE_UNKNOWN_UNSET 0x00000800u /* pcre2_substitute() only */
+#define PCRE2_SUBSTITUTE_OVERFLOW_LENGTH 0x00001000u /* pcre2_substitute() only */
+#define PCRE2_NO_JIT 0x00002000u /* Not for pcre2_dfa_match() */
+#define PCRE2_COPY_MATCHED_SUBJECT 0x00004000u
/* Options for pcre2_pattern_convert(). */
@@ -318,6 +304,10 @@ pcre2_pattern_convert(). */
#define PCRE2_ERROR_BAD_LITERAL_OPTIONS 192
#define PCRE2_ERROR_SUPPORTED_ONLY_IN_UNICODE 193
#define PCRE2_ERROR_INVALID_HYPHEN_IN_OPTIONS 194
+#define PCRE2_ERROR_ALPHA_ASSERTION_UNKNOWN 195
+#define PCRE2_ERROR_SCRIPT_RUN_NOT_AVAILABLE 196
+#define PCRE2_ERROR_TOO_MANY_CAPTURES 197
+#define PCRE2_ERROR_CONDITION_ATOMIC_ASSERTION_EXPECTED 198
/* "Expected" matching error codes: no match and partial match. */
@@ -403,6 +393,7 @@ released, the numbers must not be changed. */
#define PCRE2_ERROR_HEAPLIMIT (-63)
#define PCRE2_ERROR_CONVERT_SYNTAX (-64)
#define PCRE2_ERROR_INTERNAL_DUPMATCH (-65)
+#define PCRE2_ERROR_DFA_UINVALID_UTF (-66)
/* Request types for pcre2_pattern_info() */
@@ -504,10 +495,10 @@ typedef struct pcre2_real_jit_stack pcre2_jit_stack; \
typedef pcre2_jit_stack *(*pcre2_jit_callback)(void *);
-/* The structure for passing out data via the pcre_callout_function. We use a
-structure so that new fields can be added on the end in future versions,
-without changing the API of the function, thereby allowing old clients to work
-without modification. Define the generic version in a macro; the width-specific
+/* The structures for passing out data via callout functions. We use structures
+so that new fields can be added on the end in future versions, without changing
+the API of the function, thereby allowing old clients to work without
+modification. Define the generic versions in a macro; the width-specific
versions are generated from this macro below. */
/* Flags for the callout_flags field. These are cleared after a callout. */
@@ -549,7 +540,19 @@ typedef struct pcre2_callout_enumerate_block { \
PCRE2_SIZE callout_string_length; /* Length of string compiled into pattern */ \
PCRE2_SPTR callout_string; /* String compiled into pattern */ \
/* ------------------------------------------------------------------ */ \
-} pcre2_callout_enumerate_block;
+} pcre2_callout_enumerate_block; \
+\
+typedef struct pcre2_substitute_callout_block { \
+ uint32_t version; /* Identifies version of block */ \
+ /* ------------------------ Version 0 ------------------------------- */ \
+ PCRE2_SPTR input; /* Pointer to input subject string */ \
+ PCRE2_SPTR output; /* Pointer to output buffer */ \
+ PCRE2_SIZE output_offsets[2]; /* Changed portion of the output */ \
+ PCRE2_SIZE *ovector; /* Pointer to current ovector */ \
+ uint32_t oveccount; /* Count of pairs set in ovector */ \
+ uint32_t subscount; /* Substitution number */ \
+ /* ------------------------------------------------------------------ */ \
+} pcre2_substitute_callout_block;
/* List the generic forms of all other functions in macros, which will be
@@ -581,7 +584,7 @@ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_bsr(pcre2_compile_context *, uint32_t); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
- pcre2_set_character_tables(pcre2_compile_context *, const unsigned char *); \
+ pcre2_set_character_tables(pcre2_compile_context *, const uint8_t *); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_compile_extra_options(pcre2_compile_context *, uint32_t); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
@@ -604,6 +607,9 @@ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_callout(pcre2_match_context *, \
int (*)(pcre2_callout_block *, void *), void *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_substitute_callout(pcre2_match_context *, \
+ int (*)(pcre2_substitute_callout_block *, void *), void *); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_depth_limit(pcre2_match_context *, uint32_t); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
@@ -673,6 +679,8 @@ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
pcre2_match_data_free(pcre2_match_data *); \
PCRE2_EXP_DECL PCRE2_SPTR PCRE2_CALL_CONVENTION \
pcre2_get_mark(pcre2_match_data *); \
+PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \
+ pcre2_get_match_data_size(pcre2_match_data *); \
PCRE2_EXP_DECL uint32_t PCRE2_CALL_CONVENTION \
pcre2_get_ovector_count(pcre2_match_data *); \
PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \
@@ -771,7 +779,8 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_get_error_message(int, PCRE2_UCHAR *, PCRE2_SIZE); \
PCRE2_EXP_DECL const uint8_t PCRE2_CALL_CONVENTION \
*pcre2_maketables(pcre2_general_context *); \
-
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ pcre2_maketables_free(pcre2_general_context *, const uint8_t *);
/* Define macros that generate width-specific names from generic versions. The
three-level macro scheme is necessary to get the macros expanded when we want
@@ -807,6 +816,7 @@ pcre2_compile are called by application code. */
#define pcre2_callout_block PCRE2_SUFFIX(pcre2_callout_block_)
#define pcre2_callout_enumerate_block PCRE2_SUFFIX(pcre2_callout_enumerate_block_)
+#define pcre2_substitute_callout_block PCRE2_SUFFIX(pcre2_substitute_callout_block_)
#define pcre2_general_context PCRE2_SUFFIX(pcre2_general_context_)
#define pcre2_compile_context PCRE2_SUFFIX(pcre2_compile_context_)
#define pcre2_convert_context PCRE2_SUFFIX(pcre2_convert_context_)
@@ -835,6 +845,7 @@ pcre2_compile are called by application code. */
#define pcre2_general_context_free PCRE2_SUFFIX(pcre2_general_context_free_)
#define pcre2_get_error_message PCRE2_SUFFIX(pcre2_get_error_message_)
#define pcre2_get_mark PCRE2_SUFFIX(pcre2_get_mark_)
+#define pcre2_get_match_data_size PCRE2_SUFFIX(pcre2_get_match_data_size_)
#define pcre2_get_ovector_pointer PCRE2_SUFFIX(pcre2_get_ovector_pointer_)
#define pcre2_get_ovector_count PCRE2_SUFFIX(pcre2_get_ovector_count_)
#define pcre2_get_startchar PCRE2_SUFFIX(pcre2_get_startchar_)
@@ -845,6 +856,7 @@ pcre2_compile are called by application code. */
#define pcre2_jit_stack_create PCRE2_SUFFIX(pcre2_jit_stack_create_)
#define pcre2_jit_stack_free PCRE2_SUFFIX(pcre2_jit_stack_free_)
#define pcre2_maketables PCRE2_SUFFIX(pcre2_maketables_)
+#define pcre2_maketables_free PCRE2_SUFFIX(pcre2_maketables_free_)
#define pcre2_match PCRE2_SUFFIX(pcre2_match_)
#define pcre2_match_context_copy PCRE2_SUFFIX(pcre2_match_context_copy_)
#define pcre2_match_context_create PCRE2_SUFFIX(pcre2_match_context_create_)
@@ -872,6 +884,7 @@ pcre2_compile are called by application code. */
#define pcre2_set_newline PCRE2_SUFFIX(pcre2_set_newline_)
#define pcre2_set_parens_nest_limit PCRE2_SUFFIX(pcre2_set_parens_nest_limit_)
#define pcre2_set_offset_limit PCRE2_SUFFIX(pcre2_set_offset_limit_)
+#define pcre2_set_substitute_callout PCRE2_SUFFIX(pcre2_set_substitute_callout_)
#define pcre2_substitute PCRE2_SUFFIX(pcre2_substitute_)
#define pcre2_substring_copy_byname PCRE2_SUFFIX(pcre2_substring_copy_byname_)
#define pcre2_substring_copy_bynumber PCRE2_SUFFIX(pcre2_substring_copy_bynumber_)
diff --git a/src/pcre2_auto_possess.c b/src/pcre2_auto_possess.c
index 2ce152e..5b95b9b 100644
--- a/src/pcre2_auto_possess.c
+++ b/src/pcre2_auto_possess.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -605,6 +605,15 @@ for(;;)
if (cb->had_recurse) return FALSE;
break;
+ /* A script run might have to backtrack if the iterated item can match
+ characters from more than one script. So give up unless repeating an
+ explicit character. */
+
+ case OP_SCRIPT_RUN:
+ if (base_list[0] != OP_CHAR && base_list[0] != OP_CHARI)
+ return FALSE;
+ break;
+
/* Atomic sub-patterns and assertions can always auto-possessify their
last iterator. However, if the group was entered as a result of checking
a previous iterator, this is not possible. */
@@ -614,8 +623,14 @@ for(;;)
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
case OP_ONCE:
-
return !entered_a_group;
+
+ /* Non-atomic assertions - don't possessify last iterator. This needs
+ more thought. */
+
+ case OP_ASSERT_NA:
+ case OP_ASSERTBACK_NA:
+ return FALSE;
}
/* Skip over the bracket and inspect what comes next. */
@@ -1043,7 +1058,7 @@ for(;;)
if (chr > 255) break;
class_bitset = (uint8_t *)
((list_ptr == list ? code : base_end) - list_ptr[2]);
- if ((class_bitset[chr >> 3] & (1 << (chr & 7))) != 0) return FALSE;
+ if ((class_bitset[chr >> 3] & (1u << (chr & 7))) != 0) return FALSE;
break;
#ifdef SUPPORT_WIDE_CHARS
diff --git a/src/pcre2_chartables.c.dist b/src/pcre2_chartables.c.dist
index 4046500..0e07edb 100644
--- a/src/pcre2_chartables.c.dist
+++ b/src/pcre2_chartables.c.dist
@@ -157,8 +157,8 @@ graph print, punct, and cntrl. Other classes are built from combinations. */
/* This table identifies various classes of character by individual bits:
0x01 white space character
0x02 letter
- 0x04 decimal digit
- 0x08 hexadecimal digit
+ 0x04 lower case letter
+ 0x08 decimal digit
0x10 alphanumeric or '_'
*/
@@ -168,16 +168,16 @@ graph print, punct, and cntrl. Other classes are built from combinations. */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - ' */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ( - / */
- 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */
- 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00, /* 8 - ? */
- 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */
+ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0 - 7 */
+ 0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, /* 8 - ? */
+ 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* @ - G */
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */
0x12,0x12,0x12,0x00,0x00,0x00,0x00,0x10, /* X - _ */
- 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */
- 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */
- 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */
- 0x12,0x12,0x12,0x00,0x00,0x00,0x00,0x00, /* x -127 */
+ 0x00,0x16,0x16,0x16,0x16,0x16,0x16,0x16, /* ` - g */
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, /* h - o */
+ 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, /* p - w */
+ 0x16,0x16,0x16,0x00,0x00,0x00,0x00,0x00, /* x -127 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */
diff --git a/src/pcre2_compile.c b/src/pcre2_compile.c
index 6bb1de3..f2e6b6b 100644
--- a/src/pcre2_compile.c
+++ b/src/pcre2_compile.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -135,6 +135,9 @@ static BOOL
set_lookbehind_lengths(uint32_t **, int *, int *, parsed_recurse_check *,
compile_block *);
+static int
+ check_lookbehinds(uint32_t *, uint32_t **, parsed_recurse_check *,
+ compile_block *);
/*************************************************
@@ -240,49 +243,62 @@ code (meta_extra_lengths, just below) must be updated to remain in step. */
#define META_RANGE_LITERAL 0x801f0000u /* range defined literally */
#define META_RECURSE 0x80200000u /* Recursion */
#define META_RECURSE_BYNAME 0x80210000u /* (?&name) */
+#define META_SCRIPT_RUN 0x80220000u /* (*script_run:...) */
/* These must be kept together to make it easy to check that an assertion
is present where expected in a conditional group. */
-#define META_LOOKAHEAD 0x80220000u /* (?= */
-#define META_LOOKAHEADNOT 0x80230000u /* (?! */
-#define META_LOOKBEHIND 0x80240000u /* (?<= */
-#define META_LOOKBEHINDNOT 0x80250000u /* (?flags & PCRE2_DEREF_TABLES) != 0)
{
/* Decoded tables belong to the codes after deserialization, and they must
- be freed when there are no more reference to them. The *ref_count should
+ be freed when there are no more references to them. The *ref_count should
always be > 0. */
ref_count = (PCRE2_SIZE *)(code->tables + tables_length);
@@ -1368,9 +1444,6 @@ the result is "not a repeat quantifier". */
EXIT:
if (yield || *errorcodeptr != 0) *ptrptr = p;
return yield;
-
-
-
}
@@ -1398,7 +1471,7 @@ Arguments:
errorcodeptr points to the errorcode variable (containing zero)
options the current options bits
isclass TRUE if inside a character class
- cb compile data block
+ cb compile data block or NULL when called from pcre2_substitute()
Returns: zero => a data character
positive => a special escape sequence
@@ -1408,7 +1481,8 @@ Returns: zero => a data character
int
PRIV(check_escape)(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, uint32_t *chptr,
- int *errorcodeptr, uint32_t options, BOOL isclass, compile_block *cb)
+ int *errorcodeptr, uint32_t options, uint32_t extra_options, BOOL isclass,
+ compile_block *cb)
{
BOOL utf = (options & PCRE2_UTF) != 0;
PCRE2_SPTR ptr = *ptrptr;
@@ -1429,14 +1503,25 @@ GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */
/* Non-alphanumerics are literals, so we just leave the value in c. An initial
value test saves a memory lookup for code points outside the alphanumeric
-range. Otherwise, do a table lookup. A non-zero result is something that can be
-returned immediately. Otherwise further processing is required. */
+range. */
if (c < ESCAPES_FIRST || c > ESCAPES_LAST) {} /* Definitely literal */
+/* Otherwise, do a table lookup. Non-zero values need little processing here. A
+positive value is a literal value for something like \n. A negative value is
+the negation of one of the ESC_ macros that is passed back for handling by the
+calling function. Some extra checking is needed for \N because only \N{U+dddd}
+is supported. If the value is zero, further processing is handled below. */
+
else if ((i = escapes[c - ESCAPES_FIRST]) != 0)
{
- if (i > 0) c = (uint32_t)i; else /* Positive is a data character */
+ if (i > 0)
+ {
+ c = (uint32_t)i;
+ if (c == CHAR_CR && (extra_options & PCRE2_EXTRA_ESCAPED_CR_IS_LF) != 0)
+ c = CHAR_LF;
+ }
+ else /* Negative table entry */
{
escape = -i; /* Else return a special escape */
if (cb != NULL && (escape == ESC_P || escape == ESC_p || escape == ESC_X))
@@ -1486,23 +1571,29 @@ else if ((i = escapes[c - ESCAPES_FIRST]) != 0)
}
}
-/* Escapes that need further processing, including those that are unknown.
-When called from pcre2_substitute(), only \c, \o, and \x are recognized (and \u
-when BSUX is set). */
+/* Escapes that need further processing, including those that are unknown, have
+a zero entry in the lookup table. When called from pcre2_substitute(), only \c,
+\o, and \x are recognized (\u and \U can never appear as they are used for case
+forcing). */
else
{
+ int s;
PCRE2_SPTR oldptr;
BOOL overflow;
- int s;
+ BOOL alt_bsux =
+ ((options & PCRE2_ALT_BSUX) | (extra_options & PCRE2_EXTRA_ALT_BSUX)) != 0;
/* Filter calls from pcre2_substitute(). */
- if (cb == NULL && c != CHAR_c && c != CHAR_o && c != CHAR_x &&
- (c != CHAR_u || (options & PCRE2_ALT_BSUX) != 0))
+ if (cb == NULL)
{
- *errorcodeptr = ERR3;
- return 0;
+ if (c != CHAR_c && c != CHAR_o && c != CHAR_x)
+ {
+ *errorcodeptr = ERR3;
+ return 0;
+ }
+ alt_bsux = FALSE; /* Do not modify \x handling */
}
switch (c)
@@ -1516,40 +1607,75 @@ else
*errorcodeptr = ERR37;
break;
- /* \u is unrecognized when PCRE2_ALT_BSUX is not set. When it is treated
- specially, \u must be followed by four hex digits. Otherwise it is a
- lowercase u letter. */
+ /* \u is unrecognized when neither PCRE2_ALT_BSUX nor PCRE2_EXTRA_ALT_BSUX
+ is set. Otherwise, \u must be followed by exactly four hex digits or, if
+ PCRE2_EXTRA_ALT_BSUX is set, by any number of hex digits in braces.
+ Otherwise it is a lowercase u letter. This gives some compatibility with
+ ECMAScript (aka JavaScript). */
case CHAR_u:
- if ((options & PCRE2_ALT_BSUX) == 0) *errorcodeptr = ERR37; else
+ if (!alt_bsux) *errorcodeptr = ERR37; else
{
uint32_t xc;
- if (ptrend - ptr < 4) break; /* Less than 4 chars */
- if ((cc = XDIGIT(ptr[0])) == 0xff) break; /* Not a hex digit */
- if ((xc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */
- cc = (cc << 4) | xc;
- if ((xc = XDIGIT(ptr[2])) == 0xff) break; /* Not a hex digit */
- cc = (cc << 4) | xc;
- if ((xc = XDIGIT(ptr[3])) == 0xff) break; /* Not a hex digit */
- c = (cc << 4) | xc;
- ptr += 4;
+
+ if (ptr >= ptrend) break;
+ if (*ptr == CHAR_LEFT_CURLY_BRACKET &&
+ (extra_options & PCRE2_EXTRA_ALT_BSUX) != 0)
+ {
+ PCRE2_SPTR hptr = ptr + 1;
+ cc = 0;
+
+ while (hptr < ptrend && (xc = XDIGIT(*hptr)) != 0xff)
+ {
+ if ((cc & 0xf0000000) != 0) /* Test for 32-bit overflow */
+ {
+ *errorcodeptr = ERR77;
+ ptr = hptr; /* Show where */
+ break; /* *hptr != } will cause another break below */
+ }
+ cc = (cc << 4) | xc;
+ hptr++;
+ }
+
+ if (hptr == ptr + 1 || /* No hex digits */
+ hptr >= ptrend || /* Hit end of input */
+ *hptr != CHAR_RIGHT_CURLY_BRACKET) /* No } terminator */
+ break; /* Hex escape not recognized */
+
+ c = cc; /* Accept the code point */
+ ptr = hptr + 1;
+ }
+
+ else /* Must be exactly 4 hex digits */
+ {
+ if (ptrend - ptr < 4) break; /* Less than 4 chars */
+ if ((cc = XDIGIT(ptr[0])) == 0xff) break; /* Not a hex digit */
+ if ((xc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */
+ cc = (cc << 4) | xc;
+ if ((xc = XDIGIT(ptr[2])) == 0xff) break; /* Not a hex digit */
+ cc = (cc << 4) | xc;
+ if ((xc = XDIGIT(ptr[3])) == 0xff) break; /* Not a hex digit */
+ c = (cc << 4) | xc;
+ ptr += 4;
+ }
+
if (utf)
{
if (c > 0x10ffffU) *errorcodeptr = ERR77;
else
if (c >= 0xd800 && c <= 0xdfff &&
- (cb->cx->extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)
- *errorcodeptr = ERR73;
+ (extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)
+ *errorcodeptr = ERR73;
}
else if (c > MAX_NON_UTF_CHAR) *errorcodeptr = ERR77;
}
break;
- /* \U is unrecognized unless PCRE2_ALT_BSUX is set, in which case it is an
- upper case letter. */
+ /* \U is unrecognized unless PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX is set,
+ in which case it is an upper case letter. */
case CHAR_U:
- if ((options & PCRE2_ALT_BSUX) == 0) *errorcodeptr = ERR37;
+ if (!alt_bsux) *errorcodeptr = ERR37;
break;
/* In a character class, \g is just a literal "g". Outside a character
@@ -1728,8 +1854,8 @@ else
}
else if (ptr < ptrend && *ptr++ == CHAR_RIGHT_CURLY_BRACKET)
{
- if (utf && c >= 0xd800 && c <= 0xdfff && (cb == NULL ||
- (cb->cx->extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0))
+ if (utf && c >= 0xd800 && c <= 0xdfff &&
+ (extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)
{
ptr--;
*errorcodeptr = ERR73;
@@ -1743,11 +1869,11 @@ else
}
break;
- /* \x is complicated. When PCRE2_ALT_BSUX is set, \x must be followed by
- two hexadecimal digits. Otherwise it is a lowercase x letter. */
+ /* When PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX is set, \x must be followed
+ by two hexadecimal digits. Otherwise it is a lowercase x letter. */
case CHAR_x:
- if ((options & PCRE2_ALT_BSUX) != 0)
+ if (alt_bsux)
{
uint32_t xc;
if (ptrend - ptr < 2) break; /* Less than 2 characters */
@@ -1755,9 +1881,9 @@ else
if ((xc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */
c = (cc << 4) | xc;
ptr += 2;
- } /* End PCRE2_ALT_BSUX handling */
+ }
- /* Handle \x in Perl's style. \x{ddd} is a character number which can be
+ /* Handle \x in Perl's style. \x{ddd} is a character code which can be
greater than 0xff in UTF-8 or non-8bit mode, but only if the ddd are hex
digits. If not, { used to be treated as a data character. However, Perl
seems to read hex digits up to the first non-such, and ignore the rest, so
@@ -1801,8 +1927,8 @@ else
}
else if (ptr < ptrend && *ptr++ == CHAR_RIGHT_CURLY_BRACKET)
{
- if (utf && c >= 0xd800 && c <= 0xdfff && (cb == NULL ||
- (cb->cx->extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0))
+ if (utf && c >= 0xd800 && c <= 0xdfff &&
+ (extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)
{
ptr--;
*errorcodeptr = ERR73;
@@ -1874,9 +2000,9 @@ else
c ^= 0x40;
/* Handle \c in an EBCDIC environment. The special case \c? is converted to
- 255 (0xff) or 95 (0x5f) if other character suggest we are using th POSIX-BC
- encoding. (This is the way Perl indicates that it handles \c?.) The other
- valid sequences correspond to a list of specific characters. */
+ 255 (0xff) or 95 (0x5f) if other characters suggest we are using the
+ POSIX-BC encoding. (This is the way Perl indicates that it handles \c?.)
+ The other valid sequences correspond to a list of specific characters. */
#else
if (c == CHAR_QUESTION_MARK)
@@ -2120,9 +2246,10 @@ return -1;
*************************************************/
/* This function is called from parse_regex() below whenever it needs to read
-the name of a subpattern or a (*VERB). The initial pointer must be to the
-character before the name. If that character is '*' we are reading a verb name.
-The pointer is updated to point after the name, for a VERB, or after tha name's
+the name of a subpattern or a (*VERB) or an (*alpha_assertion). The initial
+pointer must be to the character before the name. If that character is '*' we
+are reading a verb or alpha assertion name. The pointer is updated to point
+after the name, for a VERB or alpha assertion name, or after tha name's
terminator for a subpattern name. Returning both the offset and the name
pointer is redundant information, but some callers use one and some the other,
so it is simplest just to return both.
@@ -2130,6 +2257,7 @@ so it is simplest just to return both.
Arguments:
ptrptr points to the character pointer variable
ptrend points to the end of the input string
+ utf true if the input is UTF-encoded
terminator the terminator of a subpattern name must be this
offsetptr where to put the offset from the start of the pattern
nameptr where to put a pointer to the name in the input
@@ -2142,48 +2270,88 @@ Returns: TRUE if a name was read
*/
static BOOL
-read_name(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, uint32_t terminator,
+read_name(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, BOOL utf, uint32_t terminator,
PCRE2_SIZE *offsetptr, PCRE2_SPTR *nameptr, uint32_t *namelenptr,
int *errorcodeptr, compile_block *cb)
{
PCRE2_SPTR ptr = *ptrptr;
-BOOL is_verb = (*ptr == CHAR_ASTERISK);
-uint32_t namelen = 0;
-uint32_t ctype = is_verb? ctype_letter : ctype_word;
+BOOL is_group = (*ptr != CHAR_ASTERISK);
-if (++ptr >= ptrend)
+if (++ptr >= ptrend) /* No characters in name */
{
- *errorcodeptr = is_verb? ERR60: /* Verb not recognized or malformed */
- ERR62; /* Subpattern name expected */
+ *errorcodeptr = is_group? ERR62: /* Subpattern name expected */
+ ERR60; /* Verb not recognized or malformed */
goto FAILED;
}
*nameptr = ptr;
*offsetptr = (PCRE2_SIZE)(ptr - cb->start_pattern);
-if (IS_DIGIT(*ptr))
+/* In UTF mode, a group name may contain letters and decimal digits as defined
+by Unicode properties, and underscores, but must not start with a digit. */
+
+#ifdef SUPPORT_UNICODE
+if (utf && is_group)
{
- *errorcodeptr = ERR44; /* Group name must not start with digit */
- goto FAILED;
+ uint32_t c, type;
+
+ GETCHAR(c, ptr);
+ type = UCD_CHARTYPE(c);
+
+ if (type == ucp_Nd)
+ {
+ *errorcodeptr = ERR44;
+ goto FAILED;
+ }
+
+ for(;;)
+ {
+ if (type != ucp_Nd && PRIV(ucp_gentype)[type] != ucp_L &&
+ c != CHAR_UNDERSCORE) break;
+ ptr++;
+ FORWARDCHARTEST(ptr, ptrend);
+ if (ptr >= ptrend) break;
+ GETCHAR(c, ptr);
+ type = UCD_CHARTYPE(c);
+ }
}
+else
+#else
+(void)utf; /* Avoid compiler warning */
+#endif /* SUPPORT_UNICODE */
+
+/* Handle non-group names and group names in non-UTF modes. A group name must
+not start with a digit. If either of the others start with a digit it just
+won't be recognized. */
-while (ptr < ptrend && MAX_255(*ptr) && (cb->ctypes[*ptr] & ctype) != 0)
{
- ptr++;
- namelen++;
- if (namelen > MAX_NAME_SIZE)
+ if (is_group && IS_DIGIT(*ptr))
{
- *errorcodeptr = ERR48;
+ *errorcodeptr = ERR44;
goto FAILED;
}
+
+ while (ptr < ptrend && MAX_255(*ptr) && (cb->ctypes[*ptr] & ctype_word) != 0)
+ {
+ ptr++;
+ }
+ }
+
+/* Check name length */
+
+if (ptr > *nameptr + MAX_NAME_SIZE)
+ {
+ *errorcodeptr = ERR48;
+ goto FAILED;
}
+*namelenptr = ptr - *nameptr;
/* Subpattern names must not be empty, and their terminator is checked here.
-(What follows a verb name is checked separately.) */
+(What follows a verb or alpha assertion name is checked separately.) */
-if (!is_verb)
+if (is_group)
{
- if (namelen == 0)
+ if (ptr == *nameptr)
{
*errorcodeptr = ERR62; /* Subpattern name expected */
goto FAILED;
@@ -2196,7 +2364,6 @@ if (!is_verb)
ptr++;
}
-*namelenptr = namelen;
*ptrptr = ptr;
return TRUE;
@@ -2289,6 +2456,7 @@ typedef struct nest_save {
#define NSF_RESET 0x0001u
#define NSF_CONDASSERT 0x0002u
+#define NSF_ATOMICSR 0x0004u
/* Options that are changeable within the pattern must be tracked during
parsing. Some (e.g. PCRE2_EXTENDED) are implemented entirely during parsing,
@@ -2304,8 +2472,9 @@ must be last. */
enum { RANGE_NO, RANGE_STARTED, RANGE_OK_ESCAPED, RANGE_OK_LITERAL };
-/* Only in 32-bit mode can there be literals > META_END. A macros encapsulates
-the storing of literal values in the parsed pattern. */
+/* Only in 32-bit mode can there be literals > META_END. A macro encapsulates
+the storing of literal values in the main parsed pattern, where they can always
+be quantified. */
#if PCRE2_CODE_UNIT_WIDTH == 32
#define PARSED_LITERAL(c, p) \
@@ -2328,11 +2497,13 @@ uint32_t delimiter;
uint32_t namelen;
uint32_t class_range_state;
uint32_t *verblengthptr = NULL; /* Value avoids compiler warning */
+uint32_t *verbstartptr = NULL;
uint32_t *previous_callout = NULL;
uint32_t *parsed_pattern = cb->parsed_pattern;
uint32_t *parsed_pattern_end = cb->parsed_pattern_end;
uint32_t meta_quantifier = 0;
uint32_t add_after_mark = 0;
+uint32_t extra_options = cb->cx->extra_options;
uint16_t nest_depth = 0;
int after_manual_callout = 0;
int expect_cond_assert = 0;
@@ -2356,12 +2527,12 @@ nest_save *top_nest, *end_nests;
/* Insert leading items for word and line matching (features provided for the
benefit of pcre2grep). */
-if ((cb->cx->extra_options & PCRE2_EXTRA_MATCH_LINE) != 0)
+if ((extra_options & PCRE2_EXTRA_MATCH_LINE) != 0)
{
*parsed_pattern++ = META_CIRCUMFLEX;
*parsed_pattern++ = META_NOCAPTURE;
}
-else if ((cb->cx->extra_options & PCRE2_EXTRA_MATCH_WORD) != 0)
+else if ((extra_options & PCRE2_EXTRA_MATCH_WORD) != 0)
{
*parsed_pattern++ = META_ESCAPE + ESC_b;
*parsed_pattern++ = META_NOCAPTURE;
@@ -2453,10 +2624,20 @@ while (ptr < ptrend)
errorcode = ERR28;
goto FAILED;
}
- if (!inverbname && after_manual_callout-- <= 0)
- parsed_pattern = manage_callouts(thisptr, &previous_callout,
- auto_callout, parsed_pattern, cb);
- PARSED_LITERAL(c, parsed_pattern);
+ if (inverbname)
+ { /* Don't use PARSED_LITERAL() because it */
+#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */
+ if (c >= META_END) *parsed_pattern++ = META_BIGVALUE;
+#endif
+ *parsed_pattern++ = c;
+ }
+ else
+ {
+ if (after_manual_callout-- <= 0)
+ parsed_pattern = manage_callouts(thisptr, &previous_callout,
+ auto_callout, parsed_pattern, cb);
+ PARSED_LITERAL(c, parsed_pattern);
+ }
meta_quantifier = 0;
}
continue; /* Next character */
@@ -2493,13 +2674,15 @@ while (ptr < ptrend)
switch(c)
{
- default:
- PARSED_LITERAL(c, parsed_pattern);
+ default: /* Don't use PARSED_LITERAL() because it */
+#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */
+ if (c >= META_END) *parsed_pattern++ = META_BIGVALUE;
+#endif
+ *parsed_pattern++ = c;
break;
case CHAR_RIGHT_PARENTHESIS:
inverbname = FALSE;
- okquantifier = FALSE; /* Was probably set by literals */
/* This is the length in characters */
verbnamelength = (PCRE2_SIZE)(parsed_pattern - verblengthptr - 1);
/* But the limit on the length is in code units */
@@ -2526,15 +2709,18 @@ while (ptr < ptrend)
if ((options & PCRE2_ALT_VERBNAMES) != 0)
{
escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options,
- FALSE, cb);
+ cb->cx->extra_options, FALSE, cb);
if (errorcode != 0) goto FAILED;
}
else escape = 0; /* Treat all as literal */
switch(escape)
{
- case 0:
- PARSED_LITERAL(c, parsed_pattern);
+ case 0: /* Don't use PARSED_LITERAL() because it */
+#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */
+ if (c >= META_END) *parsed_pattern++ = META_BIGVALUE;
+#endif
+ *parsed_pattern++ = c;
break;
case ESC_Q:
@@ -2639,23 +2825,30 @@ while (ptr < ptrend)
if (expect_cond_assert > 0)
{
BOOL ok = c == CHAR_LEFT_PARENTHESIS && ptrend - ptr >= 3 &&
- ptr[0] == CHAR_QUESTION_MARK;
- if (ok) switch(ptr[1])
+ (ptr[0] == CHAR_QUESTION_MARK || ptr[0] == CHAR_ASTERISK);
+ if (ok)
{
- case CHAR_C:
- ok = expect_cond_assert == 2;
- break;
+ if (ptr[0] == CHAR_ASTERISK) /* New alpha assertion format, possibly */
+ {
+ ok = MAX_255(ptr[1]) && (cb->ctypes[ptr[1]] & ctype_lcletter) != 0;
+ }
+ else switch(ptr[1]) /* Traditional symbolic format */
+ {
+ case CHAR_C:
+ ok = expect_cond_assert == 2;
+ break;
- case CHAR_EQUALS_SIGN:
- case CHAR_EXCLAMATION_MARK:
- break;
+ case CHAR_EQUALS_SIGN:
+ case CHAR_EXCLAMATION_MARK:
+ break;
- case CHAR_LESS_THAN_SIGN:
- ok = ptr[2] == CHAR_EQUALS_SIGN || ptr[2] == CHAR_EXCLAMATION_MARK;
- break;
+ case CHAR_LESS_THAN_SIGN:
+ ok = ptr[2] == CHAR_EQUALS_SIGN || ptr[2] == CHAR_EXCLAMATION_MARK;
+ break;
- default:
- ok = FALSE;
+ default:
+ ok = FALSE;
+ }
}
if (!ok)
@@ -2709,11 +2902,11 @@ while (ptr < ptrend)
case CHAR_BACKSLASH:
tempptr = ptr;
escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options,
- FALSE, cb);
+ cb->cx->extra_options, FALSE, cb);
if (errorcode != 0)
{
ESCAPE_FAILED:
- if ((cb->cx->extra_options & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0)
+ if ((extra_options & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0)
goto FAILED;
ptr = tempptr;
if (ptr >= ptrend) c = CHAR_BACKSLASH; else
@@ -2907,7 +3100,7 @@ while (ptr < ptrend)
/* Not a numerical recursion */
- if (!read_name(&ptr, ptrend, terminator, &offset, &name, &namelen,
+ if (!read_name(&ptr, ptrend, utf, terminator, &offset, &name, &namelen,
&errorcode, cb)) goto ESCAPE_FAILED;
/* \k and \g when used with braces are back references, whereas \g used
@@ -2981,6 +3174,21 @@ while (ptr < ptrend)
goto FAILED_BACK;
}
+ /* Most (*VERB)s are not allowed to be quantified, but an ungreedy
+ quantifier can be useful for (*ACCEPT) - meaning "succeed on backtrack", a
+ sort of negated (*COMMIT). We therefore allow (*ACCEPT) to be quantified by
+ wrapping it in non-capturing brackets, but we have to allow for a preceding
+ (*MARK) for when (*ACCEPT) has an argument. */
+
+ if (parsed_pattern[-1] == META_ACCEPT)
+ {
+ uint32_t *p;
+ for (p = parsed_pattern - 1; p >= verbstartptr; p--) p[1] = p[0];
+ *verbstartptr = META_NOCAPTURE;
+ parsed_pattern[1] = META_KET;
+ parsed_pattern += 2;
+ }
+
/* Now we can put the quantifier into the parsed pattern vector. At this
stage, we have only the basic quantifier. The check for a following + or ?
modifier happens at the top of the loop, after any intervening comments
@@ -3270,12 +3478,12 @@ while (ptr < ptrend)
else
{
tempptr = ptr;
- escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode,
- options, TRUE, cb);
+ escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options,
+ cb->cx->extra_options, TRUE, cb);
+
if (errorcode != 0)
{
- CLASS_ESCAPE_FAILED:
- if ((cb->cx->extra_options & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0)
+ if ((extra_options & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0)
goto FAILED;
ptr = tempptr;
if (ptr >= ptrend) c = CHAR_BACKSLASH; else
@@ -3285,30 +3493,32 @@ while (ptr < ptrend)
escape = 0; /* Treat as literal character */
}
- if (escape == 0) /* Escaped character code point is in c */
+ switch(escape)
{
+ case 0: /* Escaped character code point is in c */
char_is_literal = FALSE;
goto CLASS_LITERAL;
- }
- /* These three escapes do not alter the class range state. */
-
- if (escape == ESC_b)
- {
- c = CHAR_BS; /* \b is backspace in a class */
+ case ESC_b:
+ c = CHAR_BS; /* \b is backspace in a class */
char_is_literal = FALSE;
goto CLASS_LITERAL;
- }
- else if (escape == ESC_Q)
- {
+ case ESC_Q:
inescq = TRUE; /* Enter literal mode */
goto CLASS_CONTINUE;
- }
- else if (escape == ESC_E) /* Ignore orphan \E */
+ case ESC_E: /* Ignore orphan \E */
goto CLASS_CONTINUE;
+ case ESC_B: /* Always an error in a class */
+ case ESC_R:
+ case ESC_X:
+ errorcode = ERR7;
+ ptr--;
+ goto FAILED;
+ }
+
/* The second part of a range can be a single-character escape
sequence (detected above), but not any of the other escapes. Perl
treats a hyphen as a literal in such circumstances. However, in Perl's
@@ -3318,7 +3528,7 @@ while (ptr < ptrend)
if (class_range_state == RANGE_STARTED)
{
errorcode = ERR50;
- goto CLASS_ESCAPE_FAILED;
+ goto FAILED; /* Not CLASS_ESCAPE_FAILED; always an error */
}
/* Of the remaining escapes, only those that define characters are
@@ -3328,8 +3538,8 @@ while (ptr < ptrend)
switch(escape)
{
case ESC_N:
- errorcode = ERR71; /* Not supported in a class */
- goto CLASS_ESCAPE_FAILED;
+ errorcode = ERR71;
+ goto FAILED;
case ESC_H:
case ESC_h:
@@ -3392,14 +3602,14 @@ while (ptr < ptrend)
}
#else
errorcode = ERR45;
- goto CLASS_ESCAPE_FAILED;
+ goto FAILED;
#endif
break; /* End \P and \p */
default: /* All others are not allowed in a class */
errorcode = ERR7;
ptr--;
- goto CLASS_ESCAPE_FAILED;
+ goto FAILED;
}
/* Perl gives a warning unless a following hyphen is the last character
@@ -3425,6 +3635,8 @@ while (ptr < ptrend)
if (c == CHAR_RIGHT_SQUARE_BRACKET && !inescq) break;
} /* End of class-processing loop */
+ /* -] at the end of a class is a literal '-' */
+
if (class_range_state == RANGE_STARTED)
{
parsed_pattern[-1] = CHAR_MINUS;
@@ -3440,7 +3652,8 @@ while (ptr < ptrend)
case CHAR_LEFT_PARENTHESIS:
if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS;
- /* If ( is not followed by ? it is either a capture or a special verb. */
+ /* If ( is not followed by ? it is either a capture or a special verb or an
+ alpha assertion. */
if (*ptr != CHAR_QUESTION_MARK)
{
@@ -3454,23 +3667,140 @@ while (ptr < ptrend)
nest_depth++;
if ((options & PCRE2_NO_AUTO_CAPTURE) == 0)
{
+ if (cb->bracount >= MAX_GROUP_NUMBER)
+ {
+ errorcode = ERR97;
+ goto FAILED;
+ }
cb->bracount++;
*parsed_pattern++ = META_CAPTURE | cb->bracount;
}
else *parsed_pattern++ = META_NOCAPTURE;
}
+ /* Do nothing for (* followed by end of pattern or ) so it gives a "bad
+ quantifier" error rather than "(*MARK) must have an argument". */
- /* ---- Handle (*VERB) and (*VERB:NAME) ---- */
+ else if (ptrend - ptr <= 1 || (c = ptr[1]) == CHAR_RIGHT_PARENTHESIS)
+ break;
+
+ /* Handle "alpha assertions" such as (*pla:...). Most of these are
+ synonyms for the historical symbolic assertions, but the script run ones
+ are new. They are distinguished by starting with a lower case letter.
+ Checking both ends of the alphabet makes this work in all character
+ codes. */
+
+ else if (CHMAX_255(c) && (cb->ctypes[c] & ctype_lcletter) != 0)
+ {
+ uint32_t meta;
+
+ vn = alasnames;
+ if (!read_name(&ptr, ptrend, utf, 0, &offset, &name, &namelen,
+ &errorcode, cb)) goto FAILED;
+ if (ptr >= ptrend || *ptr != CHAR_COLON)
+ {
+ errorcode = ERR95; /* Malformed */
+ goto FAILED;
+ }
+
+ /* Scan the table of alpha assertion names */
+
+ for (i = 0; i < alascount; i++)
+ {
+ if (namelen == alasmeta[i].len &&
+ PRIV(strncmp_c8)(name, vn, namelen) == 0)
+ break;
+ vn += alasmeta[i].len + 1;
+ }
+
+ if (i >= alascount)
+ {
+ errorcode = ERR95; /* Alpha assertion not recognized */
+ goto FAILED;
+ }
+
+ /* Check for expecting an assertion condition. If so, only atomic
+ lookaround assertions are valid. */
+
+ meta = alasmeta[i].meta;
+ if (prev_expect_cond_assert > 0 &&
+ (meta < META_LOOKAHEAD || meta > META_LOOKBEHINDNOT))
+ {
+ errorcode = (meta == META_LOOKAHEAD_NA || meta == META_LOOKBEHIND_NA)?
+ ERR98 : ERR28; /* (Atomic) assertion expected */
+ goto FAILED;
+ }
+
+ /* The lookaround alphabetic synonyms can mostly be handled by jumping
+ to the code that handles the traditional symbolic forms. */
+
+ switch(meta)
+ {
+ default:
+ errorcode = ERR89; /* Unknown code; should never occur because */
+ goto FAILED; /* the meta values come from a table above. */
+
+ case META_ATOMIC:
+ goto ATOMIC_GROUP;
+
+ case META_LOOKAHEAD:
+ goto POSITIVE_LOOK_AHEAD;
+
+ case META_LOOKAHEAD_NA:
+ *parsed_pattern++ = meta;
+ ptr++;
+ goto POST_ASSERTION;
+
+ case META_LOOKAHEADNOT:
+ goto NEGATIVE_LOOK_AHEAD;
+
+ case META_LOOKBEHIND:
+ case META_LOOKBEHINDNOT:
+ case META_LOOKBEHIND_NA:
+ *parsed_pattern++ = meta;
+ ptr--;
+ goto POST_LOOKBEHIND;
+
+ /* The script run facilities are handled here. Unicode support is
+ required (give an error if not, as this is a security issue). Always
+ record a META_SCRIPT_RUN item. Then, for the atomic version, insert
+ META_ATOMIC and remember that we need two META_KETs at the end. */
+
+ case META_SCRIPT_RUN:
+ case META_ATOMIC_SCRIPT_RUN:
+#ifdef SUPPORT_UNICODE
+ *parsed_pattern++ = META_SCRIPT_RUN;
+ nest_depth++;
+ ptr++;
+ if (meta == META_ATOMIC_SCRIPT_RUN)
+ {
+ *parsed_pattern++ = META_ATOMIC;
+ if (top_nest == NULL) top_nest = (nest_save *)(cb->start_workspace);
+ else if (++top_nest >= end_nests)
+ {
+ errorcode = ERR84;
+ goto FAILED;
+ }
+ top_nest->nest_depth = nest_depth;
+ top_nest->flags = NSF_ATOMICSR;
+ top_nest->options = options & PARSE_TRACKED_OPTIONS;
+ }
+ break;
+#else /* SUPPORT_UNICODE */
+ errorcode = ERR96;
+ goto FAILED;
+#endif
+ }
+ }
- /* Do nothing for (*) so it gives a "bad quantifier" error rather than
- "(*MARK) must have an argument". */
- else if (ptrend - ptr > 1 && ptr[1] != CHAR_RIGHT_PARENTHESIS)
+ /* ---- Handle (*VERB) and (*VERB:NAME) ---- */
+
+ else
{
vn = verbnames;
- if (!read_name(&ptr, ptrend, 0, &offset, &name, &namelen, &errorcode,
- cb)) goto FAILED;
+ if (!read_name(&ptr, ptrend, utf, 0, &offset, &name, &namelen,
+ &errorcode, cb)) goto FAILED;
if (ptr >= ptrend || (*ptr != CHAR_COLON &&
*ptr != CHAR_RIGHT_PARENTHESIS))
{
@@ -3508,6 +3838,12 @@ while (ptr < ptrend)
goto FAILED;
}
+ /* Remember where this verb, possibly with a preceding (*MARK), starts,
+ for handling quantified (*ACCEPT). */
+
+ verbstartptr = parsed_pattern;
+ okquantifier = (verbs[i].meta == META_ACCEPT);
+
/* It appears that Perl allows any characters whatsoever, other than a
closing parenthesis, to appear in arguments ("names"), so we no longer
insist on letters, digits, and underscores. Perl does not, however, do
@@ -3725,7 +4061,7 @@ while (ptr < ptrend)
errorcode = ERR41;
goto FAILED;
}
- if (!read_name(&ptr, ptrend, CHAR_RIGHT_PARENTHESIS, &offset, &name,
+ if (!read_name(&ptr, ptrend, utf, CHAR_RIGHT_PARENTHESIS, &offset, &name,
&namelen, &errorcode, cb)) goto FAILED;
*parsed_pattern++ = META_BACKREF_BYNAME;
*parsed_pattern++ = namelen;
@@ -3785,7 +4121,7 @@ while (ptr < ptrend)
case CHAR_AMPERSAND:
RECURSE_BY_NAME:
- if (!read_name(&ptr, ptrend, CHAR_RIGHT_PARENTHESIS, &offset, &name,
+ if (!read_name(&ptr, ptrend, utf, CHAR_RIGHT_PARENTHESIS, &offset, &name,
&namelen, &errorcode, cb)) goto FAILED;
*parsed_pattern++ = META_RECURSE_BYNAME;
*parsed_pattern++ = namelen;
@@ -3933,14 +4269,15 @@ while (ptr < ptrend)
if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;
nest_depth++;
- /* If the next character is ? there must be an assertion next (optionally
- preceded by a callout). We do not check this here, but instead we set
- expect_cond_assert to 2. If this is still greater than zero (callouts
- decrement it) when the next assertion is read, it will be marked as a
- condition that must not be repeated. A value greater than zero also
- causes checking that an assertion (possibly with callout) follows. */
+ /* If the next character is ? or * there must be an assertion next
+ (optionally preceded by a callout). We do not check this here, but
+ instead we set expect_cond_assert to 2. If this is still greater than
+ zero (callouts decrement it) when the next assertion is read, it will be
+ marked as a condition that must not be repeated. A value greater than
+ zero also causes checking that an assertion (possibly with callout)
+ follows. */
- if (*ptr == CHAR_QUESTION_MARK)
+ if (*ptr == CHAR_QUESTION_MARK || *ptr == CHAR_ASTERISK)
{
*parsed_pattern++ = META_COND_ASSERT;
ptr--; /* Pull pointer back to the opening parenthesis. */
@@ -4032,7 +4369,7 @@ while (ptr < ptrend)
terminator = CHAR_RIGHT_PARENTHESIS;
ptr--; /* Point to char before name */
}
- if (!read_name(&ptr, ptrend, terminator, &offset, &name, &namelen,
+ if (!read_name(&ptr, ptrend, utf, terminator, &offset, &name, &namelen,
&errorcode, cb)) goto FAILED;
/* Handle (?(R&name) */
@@ -4086,6 +4423,7 @@ while (ptr < ptrend)
/* ---- Atomic group ---- */
case CHAR_GREATER_THAN_SIGN:
+ ATOMIC_GROUP: /* Come from (*atomic: */
*parsed_pattern++ = META_ATOMIC;
nest_depth++;
ptr++;
@@ -4095,11 +4433,13 @@ while (ptr < ptrend)
/* ---- Lookahead assertions ---- */
case CHAR_EQUALS_SIGN:
+ POSITIVE_LOOK_AHEAD: /* Come from (*pla: */
*parsed_pattern++ = META_LOOKAHEAD;
ptr++;
goto POST_ASSERTION;
case CHAR_EXCLAMATION_MARK:
+ NEGATIVE_LOOK_AHEAD: /* Come from (*nla: */
*parsed_pattern++ = META_LOOKAHEADNOT;
ptr++;
goto POST_ASSERTION;
@@ -4119,6 +4459,8 @@ while (ptr < ptrend)
}
*parsed_pattern++ = (ptr[1] == CHAR_EQUALS_SIGN)?
META_LOOKBEHIND : META_LOOKBEHINDNOT;
+
+ POST_LOOKBEHIND: /* Come from (*plb: (*naplb: and (*nlb: */
*has_lookbehind = TRUE;
offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 2);
PUTOFFSET(offset, parsed_pattern);
@@ -4161,12 +4503,17 @@ while (ptr < ptrend)
terminator = CHAR_APOSTROPHE; /* Terminator */
DEFINE_NAME:
- if (!read_name(&ptr, ptrend, terminator, &offset, &name, &namelen,
+ if (!read_name(&ptr, ptrend, utf, terminator, &offset, &name, &namelen,
&errorcode, cb)) goto FAILED;
/* We have a name for this capturing group. It is also assigned a number,
which is its primary means of identification. */
+ if (cb->bracount >= MAX_GROUP_NUMBER)
+ {
+ errorcode = ERR97;
+ goto FAILED;
+ }
cb->bracount++;
*parsed_pattern++ = META_CAPTURE | cb->bracount;
nest_depth++;
@@ -4280,6 +4627,14 @@ while (ptr < ptrend)
cb->bracount = top_nest->max_group;
if ((top_nest->flags & NSF_CONDASSERT) != 0)
okquantifier = FALSE;
+
+ if ((top_nest->flags & NSF_ATOMICSR) != 0)
+ {
+ *parsed_pattern++ = META_KET;
+ }
+
+
+
if (top_nest == (nest_save *)(cb->start_workspace)) top_nest = NULL;
else top_nest--;
}
@@ -4311,12 +4666,12 @@ parsed_pattern = manage_callouts(ptr, &previous_callout, auto_callout,
/* Insert trailing items for word and line matching (features provided for the
benefit of pcre2grep). */
-if ((cb->cx->extra_options & PCRE2_EXTRA_MATCH_LINE) != 0)
+if ((extra_options & PCRE2_EXTRA_MATCH_LINE) != 0)
{
*parsed_pattern++ = META_KET;
*parsed_pattern++ = META_DOLLAR;
}
-else if ((cb->cx->extra_options & PCRE2_EXTRA_MATCH_WORD) != 0)
+else if ((extra_options & PCRE2_EXTRA_MATCH_WORD) != 0)
{
*parsed_pattern++ = META_KET;
*parsed_pattern++ = META_ESCAPE + ESC_b;
@@ -4385,6 +4740,7 @@ for (;;)
case OP_ASSERT_NOT:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
+ case OP_ASSERTBACK_NA:
if (!skipassert) return code;
do code += GET(code, 1); while (*code == OP_ALT);
code += PRIV(OP_lengths)[*code];
@@ -4421,6 +4777,14 @@ for (;;)
code += GET(code, 1) + 1 + LINK_SIZE;
break;
+ case OP_MARK:
+ case OP_COMMIT_ARG:
+ case OP_PRUNE_ARG:
+ case OP_SKIP_ARG:
+ case OP_THEN_ARG:
+ code += code[1] + PRIV(OP_lengths)[*code];
+ break;
+
default:
return code;
}
@@ -4937,8 +5301,10 @@ PCRE2_UCHAR *tempcode;
PCRE2_UCHAR *previous = NULL;
PCRE2_UCHAR op_previous;
BOOL groupsetfirstcu = FALSE;
+BOOL had_accept = FALSE;
BOOL matched_char = FALSE;
BOOL previous_matched_char = FALSE;
+BOOL reset_caseful = FALSE;
const uint8_t *cbits = cb->cbits;
uint8_t classbits[32];
@@ -5071,7 +5437,7 @@ for (;; pptr++)
if (meta < META_ASTERISK || meta > META_MINMAX_QUERY)
{
previous = code;
- if (matched_char) okreturn = 1;
+ if (matched_char && !had_accept) okreturn = 1;
}
previous_matched_char = matched_char;
@@ -5215,7 +5581,45 @@ for (;; pptr++)
} /* End of 1-char optimization */
/* Handle character classes that contain more than just one literal
- character. */
+ character. If there are exactly two characters in a positive class, see if
+ they are case partners. This can be optimized to generate a caseless single
+ character match (which also sets first/required code units if relevant). */
+
+ if (meta == META_CLASS && pptr[1] < META_END && pptr[2] < META_END &&
+ pptr[3] == META_CLASS_END)
+ {
+ uint32_t c = pptr[1];
+
+#ifdef SUPPORT_UNICODE
+ if (UCD_CASESET(c) == 0)
+#endif
+ {
+ uint32_t d;
+
+#ifdef SUPPORT_UNICODE
+ if (utf && c > 127) d = UCD_OTHERCASE(c); else
+#endif
+ {
+#if PCRE2_CODE_UNIT_WIDTH != 8
+ if (c > 255) d = c; else
+#endif
+ d = TABLE_GET(c, cb->fcc, c);
+ }
+
+ if (c != d && pptr[2] == d)
+ {
+ pptr += 3; /* Move on to class end */
+ meta = c;
+ if ((options & PCRE2_CASELESS) == 0)
+ {
+ reset_caseful = TRUE;
+ options |= PCRE2_CASELESS;
+ req_caseopt = REQ_CASELESS;
+ }
+ goto CLASS_CASELESS_CHAR;
+ }
+ }
+ }
/* If a non-extended class contains a negative special such as \S, we need
to flip the negation flag at the end, so that support for characters > 255
@@ -5516,10 +5920,10 @@ for (;; pptr++)
if (range_is_literal &&
(cb->ctypes[c] & ctype_letter) != 0 &&
(cb->ctypes[d] & ctype_letter) != 0 &&
- (d <= CHAR_z) == (d <= CHAR_z))
+ (c <= CHAR_z) == (d <= CHAR_z))
{
uint32_t uc = (d <= CHAR_z)? 0 : 64;
- uint32_t C = d - uc;
+ uint32_t C = c - uc;
uint32_t D = d - uc;
if (C <= CHAR_i)
@@ -5664,7 +6068,10 @@ for (;; pptr++)
(void)memmove(code + (32 / sizeof(PCRE2_UCHAR)), code,
CU2BYTES(class_uchardata - code));
if (negate_class && !xclass_has_prop)
- for (i = 0; i < 32; i++) classbits[i] = ~classbits[i];
+ {
+ /* Using 255 ^ instead of ~ avoids clang sanitize warning. */
+ for (i = 0; i < 32; i++) classbits[i] = 255 ^ classbits[i];
+ }
memcpy(code, classbits, 32);
code = class_uchardata + (32 / sizeof(PCRE2_UCHAR));
}
@@ -5687,7 +6094,10 @@ for (;; pptr++)
if (lengthptr == NULL) /* Save time in the pre-compile phase */
{
if (negate_class)
- for (i = 0; i < 32; i++) classbits[i] = ~classbits[i];
+ {
+ /* Using 255 ^ instead of ~ avoids clang sanitize warning. */
+ for (i = 0; i < 32; i++) classbits[i] = 255 ^ classbits[i];
+ }
memcpy(code, classbits, 32);
}
code += 32 / sizeof(PCRE2_UCHAR);
@@ -5704,7 +6114,7 @@ for (;; pptr++)
workspace overflow. Do not set firstcu after *ACCEPT. */
case META_ACCEPT:
- cb->had_accept = TRUE;
+ cb->had_accept = had_accept = TRUE;
for (oc = cb->open_caps;
oc != NULL && oc->assert_depth >= cb->assert_depth;
oc = oc->next)
@@ -5901,7 +6311,7 @@ for (;; pptr++)
}
goto GROUP_PROCESS_NOTE_EMPTY;
- /* The DEFINE condition is always false. It's internal groups may never
+ /* The DEFINE condition is always false. Its internal groups may never
be called, so matched_char must remain false, hence the jump to
GROUP_PROCESS rather than GROUP_PROCESS_NOTE_EMPTY. */
@@ -5962,6 +6372,11 @@ for (;; pptr++)
cb->assert_depth += 1;
goto GROUP_PROCESS;
+ case META_LOOKAHEAD_NA:
+ bravalue = OP_ASSERT_NA;
+ cb->assert_depth += 1;
+ goto GROUP_PROCESS;
+
/* Optimize (?!) to (*FAIL) unless it is quantified - which is a weird
thing to do, but Perl allows all assertions to be quantified, and when
they contain capturing parentheses there may be a potential use for
@@ -5993,10 +6408,19 @@ for (;; pptr++)
cb->assert_depth += 1;
goto GROUP_PROCESS;
+ case META_LOOKBEHIND_NA:
+ bravalue = OP_ASSERTBACK_NA;
+ cb->assert_depth += 1;
+ goto GROUP_PROCESS;
+
case META_ATOMIC:
bravalue = OP_ONCE;
goto GROUP_PROCESS_NOTE_EMPTY;
+ case META_SCRIPT_RUN:
+ bravalue = OP_SCRIPT_RUN;
+ goto GROUP_PROCESS_NOTE_EMPTY;
+
case META_NOCAPTURE:
bravalue = OP_BRA;
/* Fall through */
@@ -6047,7 +6471,7 @@ for (;; pptr++)
/* If we've just compiled an assertion, pop the assert depth. */
- if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NOT)
+ if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NA)
cb->assert_depth -= 1;
/* At the end of compiling, code is still pointing to the start of the
@@ -6197,8 +6621,8 @@ for (;; pptr++)
we must only take the reqcu when the group also set a firstcu. Otherwise,
in that example, 'X' ends up set for both. */
- else if (bravalue == OP_ASSERT && subreqcuflags >= 0 &&
- subfirstcuflags >= 0)
+ else if ((bravalue == OP_ASSERT || bravalue == OP_ASSERT_NA) &&
+ subreqcuflags >= 0 && subfirstcuflags >= 0)
{
reqcu = subreqcu;
reqcuflags = subreqcuflags;
@@ -6237,8 +6661,8 @@ for (;; pptr++)
groupnumber = ng->number;
/* For a recursion, that's all that is needed. We can now go to
- the code above that handles numerical recursion, applying it to
- the first group with the given name. */
+ the code that handles numerical recursion, applying it to the first
+ group with the given name. */
if (meta == META_RECURSE_BYNAME)
{
@@ -6419,10 +6843,6 @@ for (;; pptr++)
reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY;
op_type = 0;
- /* If the repeat is {1} we can ignore it. */
-
- if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;
-
/* Adjust first and required code units for a zero repeat. */
if (repeat_min == 0)
@@ -6465,7 +6885,10 @@ for (;; pptr++)
tempcode = previous;
op_previous = *previous;
- /* Now handle repetition for the different types of item. */
+ /* Now handle repetition for the different types of item. If the repeat
+ minimum and the repeat maximum are both 1, we can ignore the quantifier for
+ non-parenthesized items, as they have only one alternative. For anything in
+ parentheses, we must not ignore if {1} is possessive. */
switch (op_previous)
{
@@ -6479,6 +6902,7 @@ for (;; pptr++)
case OP_CHARI:
case OP_NOT:
case OP_NOTI:
+ if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;
op_type = chartypeoffset[op_previous - OP_CHAR];
/* Deal with UTF characters that take up more than one code unit. */
@@ -6525,6 +6949,7 @@ for (;; pptr++)
code = previous;
goto END_REPEAT;
}
+ if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;
if (repeat_min == 0 && repeat_max == REPEAT_UNLIMITED)
*code++ = OP_CRSTAR + repeat_type;
@@ -6559,6 +6984,8 @@ for (;; pptr++)
repetition. */
case OP_RECURSE:
+ if (repeat_max == 1 && repeat_min == 1 && !possessive_quantifier)
+ goto END_REPEAT;
/* Generate unwrapped repeats for a non-zero minimum, except when the
minimum is 1 and the maximum unlimited, because that can be handled with
@@ -6629,9 +7056,12 @@ for (;; pptr++)
case OP_ASSERT:
case OP_ASSERT_NOT:
+ case OP_ASSERT_NA:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
+ case OP_ASSERTBACK_NA:
case OP_ONCE:
+ case OP_SCRIPT_RUN:
case OP_BRA:
case OP_CBRA:
case OP_COND:
@@ -6640,6 +7070,9 @@ for (;; pptr++)
PCRE2_UCHAR *bralink = NULL;
PCRE2_UCHAR *brazeroptr = NULL;
+ if (repeat_max == 1 && repeat_min == 1 && !possessive_quantifier)
+ goto END_REPEAT;
+
/* Repeating a DEFINE group (or any group where the condition is always
FALSE and there is only one branch) is pointless, but Perl allows the
syntax, so we just ignore the repeat. */
@@ -6844,23 +7277,24 @@ for (;; pptr++)
}
/* If the maximum is unlimited, set a repeater in the final copy. For
- ONCE brackets, that's all we need to do. However, possessively repeated
- ONCE brackets can be converted into non-capturing brackets, as the
- behaviour of (?:xx)++ is the same as (?>xx)++ and this saves having to
- deal with possessive ONCEs specially.
+ SCRIPT_RUN and ONCE brackets, that's all we need to do. However,
+ possessively repeated ONCE brackets can be converted into non-capturing
+ brackets, as the behaviour of (?:xx)++ is the same as (?>xx)++ and this
+ saves having to deal with possessive ONCEs specially.
Otherwise, when we are doing the actual compile phase, check to see
whether this group is one that could match an empty string. If so,
convert the initial operator to the S form (e.g. OP_BRA -> OP_SBRA) so
that runtime checking can be done. [This check is also applied to ONCE
- groups at runtime, but in a different way.]
+ and SCRIPT_RUN groups at runtime, but in a different way.]
Then, if the quantifier was possessive and the bracket is not a
- conditional, we convert the BRA code to the POS form, and the KET code to
- KETRPOS. (It turns out to be convenient at runtime to detect this kind of
- subpattern at both the start and at the end.) The use of special opcodes
- makes it possible to reduce greatly the stack usage in pcre2_match(). If
- the group is preceded by OP_BRAZERO, convert this to OP_BRAPOSZERO.
+ conditional, we convert the BRA code to the POS form, and the KET code
+ to KETRPOS. (It turns out to be convenient at runtime to detect this
+ kind of subpattern at both the start and at the end.) The use of
+ special opcodes makes it possible to reduce greatly the stack usage in
+ pcre2_match(). If the group is preceded by OP_BRAZERO, convert this to
+ OP_BRAPOSZERO.
Then, if the minimum number of matches is 1 or 0, cancel the possessive
flag so that the default action below, of wrapping everything inside
@@ -6877,13 +7311,14 @@ for (;; pptr++)
if (*bracode == OP_ONCE && possessive_quantifier) *bracode = OP_BRA;
- /* For non-possessive ONCE brackets, all we need to do is to
- set the KET. */
+ /* For non-possessive ONCE and for SCRIPT_RUN brackets, all we need
+ to do is to set the KET. */
- if (*bracode == OP_ONCE) *ketcode = OP_KETRMAX + repeat_type;
+ if (*bracode == OP_ONCE || *bracode == OP_SCRIPT_RUN)
+ *ketcode = OP_KETRMAX + repeat_type;
- /* Handle non-ONCE brackets and possessive ONCEs (which have been
- converted to non-capturing above). */
+ /* Handle non-SCRIPT_RUN and non-ONCE brackets and possessive ONCEs
+ (which have been converted to non-capturing above). */
else
{
@@ -6960,6 +7395,8 @@ for (;; pptr++)
int prop_type, prop_value;
PCRE2_UCHAR *oldcode;
+ if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;
+
op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */
mclength = 0; /* Not a character */
@@ -7267,9 +7704,8 @@ for (;; pptr++)
scanned and these numbers are replaced by offsets within the pattern. It is
done like this to avoid problems with forward references and adjusting
offsets when groups are duplicated and moved (as discovered in previous
- implementations). Note that a recursion does not have a set first character
- (relevant if it is repeated, because it will then be wrapped with ONCE
- brackets). */
+ implementations). Note that a recursion does not have a set first
+ character. */
case META_RECURSE:
GETPLUSOFFSET(offset, pptr);
@@ -7286,6 +7722,8 @@ for (;; pptr++)
groupsetfirstcu = FALSE;
cb->had_recurse = TRUE;
if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
+ zerofirstcu = firstcu;
+ zerofirstcuflags = firstcuflags;
break;
@@ -7340,9 +7778,20 @@ for (;; pptr++)
{
uint32_t ptype = *(++pptr) >> 16;
uint32_t pdata = *pptr & 0xffff;
- *code++ = (meta_arg == ESC_p)? OP_PROP : OP_NOTPROP;
- *code++ = ptype;
- *code++ = pdata;
+
+ /* The special case of \p{Any} is compiled to OP_ALLANY so as to benefit
+ from the auto-anchoring code. */
+
+ if (meta_arg == ESC_p && ptype == PT_ANY)
+ {
+ *code++ = OP_ALLANY;
+ }
+ else
+ {
+ *code++ = (meta_arg == ESC_p)? OP_PROP : OP_NOTPROP;
+ *code++ = ptype;
+ *code++ = pdata;
+ }
break; /* End META_ESCAPE */
}
#endif
@@ -7410,9 +7859,15 @@ for (;; pptr++)
}
#endif
- /* Caseful matches, or not one of the multicase characters. Get the
- character's code units into mcbuffer, with the length in mclength. When not
- in UTF mode, the length is always 1. */
+ /* Caseful matches, or caseless and not one of the multicase characters. We
+ come here by goto in the case of a positive class that contains only
+ case-partners of a character with just two cases; matched_char has already
+ been set TRUE and options fudged if necessary. */
+
+ CLASS_CASELESS_CHAR:
+
+ /* Get the character's code units into mcbuffer, with the length in
+ mclength. When not in UTF mode, the length is always 1. */
#ifdef SUPPORT_UNICODE
if (utf) mclength = PRIV(ord2utf)(meta, mcbuffer); else
@@ -7444,8 +7899,9 @@ for (;; pptr++)
zeroreqcu = reqcu;
zeroreqcuflags = reqcuflags;
- /* If the character is more than one code unit long, we can set firstcu
- only if it is not to be matched caselessly. */
+ /* If the character is more than one code unit long, we can set a single
+ firstcu only if it is not to be matched caselessly. Multiple possible
+ starting code units may be picked up later in the studying code. */
if (mclength == 1 || req_caseopt == 0)
{
@@ -7475,7 +7931,17 @@ for (;; pptr++)
reqcuflags = req_caseopt | cb->req_varyopt;
}
}
- break; /* End default meta handling */
+
+ /* If caselessness was temporarily instated, reset it. */
+
+ if (reset_caseful)
+ {
+ options &= ~PCRE2_CASELESS;
+ req_caseopt = 0;
+ reset_caseful = FALSE;
+ }
+
+ break; /* End literal character handling */
} /* End of big switch */
} /* End of big loop */
@@ -7566,7 +8032,10 @@ length = 2 + 2*LINK_SIZE + skipunits;
/* Remember if this is a lookbehind assertion, and if it is, save its length
and skip over the pattern offset. */
-lookbehind = *code == OP_ASSERTBACK || *code == OP_ASSERTBACK_NOT;
+lookbehind = *code == OP_ASSERTBACK ||
+ *code == OP_ASSERTBACK_NOT ||
+ *code == OP_ASSERTBACK_NA;
+
if (lookbehind)
{
lookbehindlength = META_DATA(pptr[-1]);
@@ -7640,7 +8109,7 @@ for (;;)
/* If this is not the first branch, the first char and reqcu have to
match the values from all the previous branches, except that if the
previous value for reqcu didn't have REQ_VARY set, it can still match,
- and we set REQ_VARY for the regex. */
+ and we set REQ_VARY for the group from this branch's value. */
else
{
@@ -7679,7 +8148,7 @@ for (;;)
else
{
reqcu = branchreqcu;
- reqcuflags |= branchreqcuflags; /* To "or" REQ_VARY */
+ reqcuflags |= branchreqcuflags; /* To "or" REQ_VARY if present */
}
}
}
@@ -7859,7 +8328,7 @@ do {
/* Positive forward assertion */
- else if (op == OP_ASSERT)
+ else if (op == OP_ASSERT || op == OP_ASSERT_NA)
{
if (!is_anchored(scode, bracket_map, cb, atomcount, TRUE)) return FALSE;
}
@@ -7997,7 +8466,7 @@ do {
/* Positive forward assertions */
- else if (op == OP_ASSERT)
+ else if (op == OP_ASSERT || op == OP_ASSERT_NA)
{
if (!is_startline(scode, bracket_map, cb, atomcount, TRUE))
return FALSE;
@@ -8239,8 +8708,11 @@ do {
case OP_CBRAPOS:
case OP_SCBRAPOS:
case OP_ASSERT:
+ case OP_ASSERT_NA:
case OP_ONCE:
- d = find_firstassertedcu(scode, &dflags, inassert + ((op==OP_ASSERT)?1:0));
+ case OP_SCRIPT_RUN:
+ d = find_firstassertedcu(scode, &dflags, inassert +
+ ((op == OP_ASSERT || op == OP_ASSERT_NA)?1:0));
if (dflags < 0)
return 0;
if (cflags < 0) { c = d; cflags = dflags; }
@@ -8269,6 +8741,19 @@ do {
case OP_MINPLUSI:
case OP_POSPLUSI:
if (inassert == 0) return 0;
+
+ /* If the character is more than one code unit long, we cannot set its
+ first code unit when matching caselessly. Later scanning may pick up
+ multiple code units. */
+
+#ifdef SUPPORT_UNICODE
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ if (scode[1] >= 0x80) return 0;
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+ if (scode[1] >= 0xd800 && scode[1] <= 0xdfff) return 0;
+#endif
+#endif
+
if (cflags < 0) { c = scode[1]; cflags = REQ_CASELESS; }
else if (c != scode[1]) return 0;
break;
@@ -8436,9 +8921,12 @@ for (;; pptr++)
case META_COND_VERSION:
case META_LOOKAHEAD:
case META_LOOKAHEADNOT:
+ case META_LOOKAHEAD_NA:
case META_LOOKBEHIND:
case META_LOOKBEHINDNOT:
+ case META_LOOKBEHIND_NA:
case META_NOCAPTURE:
+ case META_SCRIPT_RUN:
nestlevel++;
break;
@@ -8488,7 +8976,7 @@ Returns: the group length or a negative number
static int
get_grouplength(uint32_t **pptrptr, BOOL isinline, int *errcodeptr, int *lcptr,
- int group, parsed_recurse_check *recurses, compile_block *cb)
+ int group, parsed_recurse_check *recurses, compile_block *cb)
{
int branchlength;
int grouplength = -1;
@@ -8537,8 +9025,7 @@ return -1;
*************************************************/
/* Return a fixed length for a branch in a lookbehind, giving an error if the
-length is not fixed. If any lookbehinds are encountered on the way, they get
-their length set. On entry, *pptrptr points to the first element inside the
+length is not fixed. On entry, *pptrptr points to the first element inside the
branch. On exit it is set to point to the ALT or KET.
Arguments:
@@ -8668,15 +9155,16 @@ for (;; pptr++)
}
break;
- /* Lookaheads can be ignored, but we must start the skip inside the group
- so that it isn't treated as a group within the branch. */
+ /* Lookaheads do not contribute to the length of this branch, but they may
+ contain lookbehinds within them whose lengths need to be set. */
case META_LOOKAHEAD:
case META_LOOKAHEADNOT:
- pptr = parsed_skip(pptr + 1, PSKIP_KET);
- if (pptr == NULL) goto PARSED_SKIP_FAILED;
+ case META_LOOKAHEAD_NA:
+ *errcodeptr = check_lookbehinds(pptr + 1, &pptr, recurses, cb);
+ if (*errcodeptr != 0) return -1;
- /* Also ignore any qualifiers that follow a lookahead assertion. */
+ /* Ignore any qualifiers that follow a lookahead assertion. */
switch (pptr[1])
{
@@ -8703,10 +9191,12 @@ for (;; pptr++)
}
break;
- /* Lookbehinds can be ignored, but must themselves be checked. */
+ /* A nested lookbehind does not contribute any length to this lookbehind,
+ but must itself be checked and have its lengths set. */
case META_LOOKBEHIND:
case META_LOOKBEHINDNOT:
+ case META_LOOKBEHIND_NA:
if (!set_lookbehind_lengths(&pptr, errcodeptr, lcptr, recurses, cb))
return -1;
break;
@@ -8851,6 +9341,7 @@ for (;; pptr++)
case META_ATOMIC:
case META_NOCAPTURE:
+ case META_SCRIPT_RUN:
pptr++;
CHECK_GROUP:
grouplength = get_grouplength(&pptr, TRUE, errcodeptr, lcptr, group,
@@ -8867,8 +9358,26 @@ for (;; pptr++)
case META_MINMAX_QUERY:
if (pptr[1] == pptr[2])
{
- if (pptr[1] == 0) branchlength -= lastitemlength;
- else itemlength = (pptr[1] - 1) * lastitemlength;
+ switch(pptr[1])
+ {
+ case 0:
+ branchlength -= lastitemlength;
+ break;
+
+ case 1:
+ itemlength = 0;
+ break;
+
+ default: /* Check for integer overflow */
+ if (lastitemlength != 0 && /* Should not occur, but just in case */
+ INT_MAX/lastitemlength < pptr[1] - 1)
+ {
+ *errcodeptr = ERR87; /* Integer overflow; lookbehind too big */
+ return -1;
+ }
+ itemlength = (pptr[1] - 1) * lastitemlength;
+ break;
+ }
pptr += 2;
break;
}
@@ -8882,24 +9391,23 @@ for (;; pptr++)
return -1;
}
- /* Add the item length to the branchlength, and save it for use if the next
- thing is a quantifier. */
-
- branchlength += itemlength;
- lastitemlength = itemlength;
-
- /* Ensure that the length does not overflow the limit. */
+ /* Add the item length to the branchlength, checking for integer overflow and
+ for the branch length exceeding the limit. */
- if (branchlength > LOOKBEHIND_MAX)
+ if (INT_MAX - branchlength < (int)itemlength ||
+ (branchlength += itemlength) > LOOKBEHIND_MAX)
{
*errcodeptr = ERR87;
return -1;
}
+
+ /* Save this item length for use if the next item is a quantifier. */
+
+ lastitemlength = itemlength;
}
EXIT:
*pptrptr = pptr;
-if (branchlength > cb->max_lookbehind) cb->max_lookbehind = branchlength;
return branchlength;
PARSED_SKIP_FAILED:
@@ -8918,6 +9426,11 @@ branches. An error occurs if any branch does not have a fixed length that is
less than the maximum (65535). On exit, the pointer must be left on the final
ket.
+The function also maintains the max_lookbehind value. Any lookbehind branch
+that contains a nested lookbehind may actually look further back than the
+length of the branch. The additional amount is passed back from
+get_branchlength() as an "extra" value.
+
Arguments:
pptrptr pointer to pointer in the parsed pattern
errcodeptr pointer to error code
@@ -8951,6 +9464,7 @@ do
if (cb->erroroffset == PCRE2_UNSET) cb->erroroffset = offset;
return FALSE;
}
+ if (branchlength > cb->max_lookbehind) cb->max_lookbehind = branchlength;
*bptr |= branchlength; /* branchlength never more than 65535 */
bptr = *pptrptr;
}
@@ -8971,20 +9485,30 @@ set_lookbehind_lengths() for each one. At the start, the errorcode is zero and
the error offset is marked unset. The enables the functions above not to
override settings from deeper nestings.
-Arguments cb points to the compile block
-Returns: 0 on success, or an errorcode (cb->erroroffset will be set)
+This function is called recursively from get_branchlength() for lookaheads in
+order to process any lookbehinds that they may contain. It stops when it hits a
+non-nested closing parenthesis in this case, returning a pointer to it.
+
+Arguments
+ pptr points to where to start (start of pattern or start of lookahead)
+ retptr if not NULL, return the ket pointer here
+ recurses chain of recurse_check to catch mutual recursion
+ cb points to the compile block
+
+Returns: 0 on success, or an errorcode (cb->erroroffset will be set)
*/
static int
-check_lookbehinds(compile_block *cb)
+check_lookbehinds(uint32_t *pptr, uint32_t **retptr,
+ parsed_recurse_check *recurses, compile_block *cb)
{
-uint32_t *pptr;
int errorcode = 0;
int loopcount = 0;
+int nestlevel = 0;
cb->erroroffset = PCRE2_UNSET;
-for (pptr = cb->parsed_pattern; *pptr != META_END; pptr++)
+for (; *pptr != META_END; pptr++)
{
if (*pptr < META_END) continue; /* Literal */
@@ -8998,14 +9522,31 @@ for (pptr = cb->parsed_pattern; *pptr != META_END; pptr++)
pptr += 1;
break;
+ case META_KET:
+ if (--nestlevel < 0)
+ {
+ if (retptr != NULL) *retptr = pptr;
+ return 0;
+ }
+ break;
+
+ case META_ATOMIC:
+ case META_CAPTURE:
+ case META_COND_ASSERT:
+ case META_LOOKAHEAD:
+ case META_LOOKAHEADNOT:
+ case META_LOOKAHEAD_NA:
+ case META_NOCAPTURE:
+ case META_SCRIPT_RUN:
+ nestlevel++;
+ break;
+
case META_ACCEPT:
case META_ALT:
case META_ASTERISK:
case META_ASTERISK_PLUS:
case META_ASTERISK_QUERY:
- case META_ATOMIC:
case META_BACKREF:
- case META_CAPTURE:
case META_CIRCUMFLEX:
case META_CLASS:
case META_CLASS_EMPTY:
@@ -9013,14 +9554,9 @@ for (pptr = cb->parsed_pattern; *pptr != META_END; pptr++)
case META_CLASS_END:
case META_CLASS_NOT:
case META_COMMIT:
- case META_COND_ASSERT:
case META_DOLLAR:
case META_DOT:
case META_FAIL:
- case META_KET:
- case META_LOOKAHEAD:
- case META_LOOKAHEADNOT:
- case META_NOCAPTURE:
case META_PLUS:
case META_PLUS_PLUS:
case META_PLUS_QUERY:
@@ -9039,13 +9575,22 @@ for (pptr = cb->parsed_pattern; *pptr != META_END; pptr++)
break;
case META_BACKREF_BYNAME:
+ case META_RECURSE_BYNAME:
+ pptr += 1 + SIZEOFFSET;
+ break;
+
case META_COND_DEFINE:
case META_COND_NAME:
case META_COND_NUMBER:
case META_COND_RNAME:
case META_COND_RNUMBER:
- case META_RECURSE_BYNAME:
pptr += 1 + SIZEOFFSET;
+ nestlevel++;
+ break;
+
+ case META_COND_VERSION:
+ pptr += 3;
+ nestlevel++;
break;
case META_CALLOUT_STRING:
@@ -9066,7 +9611,6 @@ for (pptr = cb->parsed_pattern; *pptr != META_END; pptr++)
break;
case META_CALLOUT_NUMBER:
- case META_COND_VERSION:
pptr += 3;
break;
@@ -9080,7 +9624,8 @@ for (pptr = cb->parsed_pattern; *pptr != META_END; pptr++)
case META_LOOKBEHIND:
case META_LOOKBEHINDNOT:
- if (!set_lookbehind_lengths(&pptr, &errorcode, &loopcount, NULL, cb))
+ case META_LOOKBEHIND_NA:
+ if (!set_lookbehind_lengths(&pptr, &errorcode, &loopcount, recurses, cb))
return errorcode;
break;
}
@@ -9182,6 +9727,10 @@ if (pattern == NULL)
if (ccontext == NULL)
ccontext = (pcre2_compile_context *)(&PRIV(default_compile_context));
+/* PCRE2_MATCH_INVALID_UTF implies UTF */
+
+if ((options & PCRE2_MATCH_INVALID_UTF) != 0) options |= PCRE2_UTF;
+
/* Check that all undefined public option bits are zero. */
if ((options & ~PUBLIC_COMPILE_OPTIONS) != 0 ||
@@ -9360,7 +9909,7 @@ if ((options & PCRE2_LITERAL) == 0)
ptr += skipatstart;
-/* Can't support UTF or UCP unless PCRE2 has been compiled with UTF support. */
+/* Can't support UTF or UCP if PCRE2 was built without Unicode support. */
#ifndef SUPPORT_UNICODE
if ((cb.external_options & (PCRE2_UTF|PCRE2_UCP)) != 0)
@@ -9530,7 +10079,7 @@ lengths. */
if (has_lookbehind)
{
- errorcode = check_lookbehinds(&cb);
+ errorcode = check_lookbehinds(cb.parsed_pattern, NULL, NULL, &cb);
if (errorcode != 0) goto HAD_CB_ERROR;
}
@@ -9678,8 +10227,9 @@ re->max_lookbehind = cb.max_lookbehind;
if (cb.had_accept)
{
- reqcu = 0; /* Must disable after (*ACCEPT) */
+ reqcu = 0; /* Must disable after (*ACCEPT) */
reqcuflags = REQ_NONE;
+ re->flags |= PCRE2_HASACCEPT; /* Disables minimum length */
}
/* Fill in the final opcode and check for disastrous overflow. If no overflow,
@@ -9800,6 +10350,8 @@ unit. */
if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
{
+ int minminlength = 0; /* For minimal minlength from first/required CU */
+
/* If we do not have a first code unit, see if there is one that is asserted
(these are not saved during the compile because they can cause conflicts with
actual literals that follow). */
@@ -9807,12 +10359,14 @@ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
if (firstcuflags < 0)
firstcu = find_firstassertedcu(codestart, &firstcuflags, 0);
- /* Save the data for a first code unit. */
+ /* Save the data for a first code unit. The existence of one means the
+ minimum length must be at least 1. */
if (firstcuflags >= 0)
{
re->first_codeunit = firstcu;
re->flags |= PCRE2_FIRSTSET;
+ minminlength++;
/* Handle caseless first code units. */
@@ -9846,39 +10400,72 @@ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
is_startline(codestart, 0, &cb, 0, FALSE))
re->flags |= PCRE2_STARTLINE;
- /* Handle the "required code unit", if one is set. In the case of an anchored
- pattern, do this only if it follows a variable length item in the pattern. */
+ /* Handle the "required code unit", if one is set. In the UTF case we can
+ increment the minimum minimum length only if we are sure this really is a
+ different character and not a non-starting code unit of the first character,
+ because the minimum length count is in characters, not code units. */
- if (reqcuflags >= 0 &&
- ((re->overall_options & PCRE2_ANCHORED) == 0 ||
- (reqcuflags & REQ_VARY) != 0))
+ if (reqcuflags >= 0)
{
- re->last_codeunit = reqcu;
- re->flags |= PCRE2_LASTSET;
+#if PCRE2_CODE_UNIT_WIDTH == 16
+ if ((re->overall_options & PCRE2_UTF) == 0 || /* Not UTF */
+ firstcuflags < 0 || /* First not set */
+ (firstcu & 0xf800) != 0xd800 || /* First not surrogate */
+ (reqcu & 0xfc00) != 0xdc00) /* Req not low surrogate */
+#elif PCRE2_CODE_UNIT_WIDTH == 8
+ if ((re->overall_options & PCRE2_UTF) == 0 || /* Not UTF */
+ firstcuflags < 0 || /* First not set */
+ (firstcu & 0x80) == 0 || /* First is ASCII */
+ (reqcu & 0x80) == 0) /* Req is ASCII */
+#endif
+ {
+ minminlength++;
+ }
- /* Handle caseless required code units as for first code units (above). */
+ /* In the case of an anchored pattern, set up the value only if it follows
+ a variable length item in the pattern. */
- if ((reqcuflags & REQ_CASELESS) != 0)
+ if ((re->overall_options & PCRE2_ANCHORED) == 0 ||
+ (reqcuflags & REQ_VARY) != 0)
{
- if (reqcu < 128 || (!utf && reqcu < 255))
+ re->last_codeunit = reqcu;
+ re->flags |= PCRE2_LASTSET;
+
+ /* Handle caseless required code units as for first code units (above). */
+
+ if ((reqcuflags & REQ_CASELESS) != 0)
{
- if (cb.fcc[reqcu] != reqcu) re->flags |= PCRE2_LASTCASELESS;
- }
+ if (reqcu < 128 || (!utf && reqcu < 255))
+ {
+ if (cb.fcc[reqcu] != reqcu) re->flags |= PCRE2_LASTCASELESS;
+ }
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
- else if (reqcu <= MAX_UTF_CODE_POINT && UCD_OTHERCASE(reqcu) != reqcu)
- re->flags |= PCRE2_LASTCASELESS;
+ else if (reqcu <= MAX_UTF_CODE_POINT && UCD_OTHERCASE(reqcu) != reqcu)
+ re->flags |= PCRE2_LASTCASELESS;
#endif
+ }
}
}
- /* Finally, study the compiled pattern to set up information such as a bitmap
- of starting code units and a minimum matching length. */
+ /* Study the compiled pattern to set up information such as a bitmap of
+ starting code units and a minimum matching length. */
if (PRIV(study)(re) != 0)
{
errorcode = ERR31;
goto HAD_CB_ERROR;
}
+
+ /* If study() set a bitmap of starting code units, it implies a minimum
+ length of at least one. */
+
+ if ((re->flags & PCRE2_FIRSTMAPSET) != 0 && minminlength == 0)
+ minminlength = 1;
+
+ /* If the minimum length set (or not set) by study() is less than the minimum
+ implied by required code units, override it. */
+
+ if (re->minlength < minminlength) re->minlength = minminlength;
} /* End of start-of-match optimizations. */
/* Control ends up here in all cases. When running under valgrind, make a
diff --git a/src/pcre2_context.c b/src/pcre2_context.c
index 2c14df0..f904a49 100644
--- a/src/pcre2_context.c
+++ b/src/pcre2_context.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2017 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -163,11 +163,13 @@ when no context is supplied to a match function. */
const pcre2_match_context PRIV(default_match_context) = {
{ default_malloc, default_free, NULL },
#ifdef SUPPORT_JIT
- NULL,
- NULL,
+ NULL, /* JIT callback */
+ NULL, /* JIT callback data */
#endif
- NULL,
- NULL,
+ NULL, /* Callout function */
+ NULL, /* Callout data */
+ NULL, /* Substitute callout function */
+ NULL, /* Substitute callout data */
PCRE2_UNSET, /* Offset limit */
HEAP_LIMIT,
MATCH_LIMIT,
@@ -321,7 +323,7 @@ data. */
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_set_character_tables(pcre2_compile_context *ccontext,
- const unsigned char *tables)
+ const uint8_t *tables)
{
ccontext->tables = tables;
return 0;
@@ -403,6 +405,16 @@ mcontext->callout_data = callout_data;
return 0;
}
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_set_substitute_callout(pcre2_match_context *mcontext,
+ int (*substitute_callout)(pcre2_substitute_callout_block *, void *),
+ void *substitute_callout_data)
+{
+mcontext->substitute_callout = substitute_callout;
+mcontext->substitute_callout_data = substitute_callout_data;
+return 0;
+}
+
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_set_heap_limit(pcre2_match_context *mcontext, uint32_t limit)
{
diff --git a/src/pcre2_convert.c b/src/pcre2_convert.c
index 1dd5c33..d45b6fe 100644
--- a/src/pcre2_convert.c
+++ b/src/pcre2_convert.c
@@ -276,7 +276,7 @@ while (plength > 0)
break;
case CHAR_BACKSLASH:
- if (plength <= 0) return PCRE2_ERROR_END_BACKSLASH;
+ if (plength == 0) return PCRE2_ERROR_END_BACKSLASH;
if (extended) nextisliteral = TRUE; else
{
if (*posix < 127 && strchr(posix_meta_escapes, *posix) != NULL)
diff --git a/src/pcre2_dfa_match.c b/src/pcre2_dfa_match.c
index 9b43237..7d8ffe8 100644
--- a/src/pcre2_dfa_match.c
+++ b/src/pcre2_dfa_match.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -85,7 +85,8 @@ in others, so I abandoned this code. */
#define PUBLIC_DFA_MATCH_OPTIONS \
(PCRE2_ANCHORED|PCRE2_ENDANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \
PCRE2_NOTEMPTY_ATSTART|PCRE2_NO_UTF_CHECK|PCRE2_PARTIAL_HARD| \
- PCRE2_PARTIAL_SOFT|PCRE2_DFA_SHORTEST|PCRE2_DFA_RESTART)
+ PCRE2_PARTIAL_SOFT|PCRE2_DFA_SHORTEST|PCRE2_DFA_RESTART| \
+ PCRE2_COPY_MATCHED_SUBJECT)
/*************************************************
@@ -172,7 +173,10 @@ static const uint8_t coptable[] = {
0, /* Assert not */
0, /* Assert behind */
0, /* Assert behind not */
+ 0, /* NA assert */
+ 0, /* NA assert behind */
0, /* ONCE */
+ 0, /* SCRIPT_RUN */
0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */
0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */
0, 0, /* CREF, DNCREF */
@@ -246,7 +250,10 @@ static const uint8_t poptable[] = {
0, /* Assert not */
0, /* Assert behind */
0, /* Assert behind not */
+ 0, /* NA assert */
+ 0, /* NA assert behind */
0, /* ONCE */
+ 0, /* SCRIPT_RUN */
0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */
0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */
0, 0, /* CREF, DNCREF */
@@ -316,8 +323,8 @@ finding the minimum heap requirement for a match. */
typedef struct RWS_anchor {
struct RWS_anchor *next;
- unsigned int size; /* Number of ints */
- unsigned int free; /* Number of ints */
+ uint32_t size; /* Number of ints */
+ uint32_t free; /* Number of ints */
} RWS_anchor;
#define RWS_ANCHOR_SIZE (sizeof(RWS_anchor)/sizeof(int))
@@ -413,20 +420,24 @@ if (rws->next != NULL)
new = rws->next;
}
-/* All sizes are in units of sizeof(int), except for mb->heaplimit, which is in
-kibibytes. */
+/* Sizes in the RWS_anchor blocks are in units of sizeof(int), but
+mb->heap_limit and mb->heap_used are in kibibytes. Play carefully, to avoid
+overflow. */
else
{
- unsigned int newsize = rws->size * 2;
- unsigned int heapleft = (unsigned int)
- (((1024/sizeof(int))*mb->heap_limit - mb->heap_used));
- if (newsize > heapleft) newsize = heapleft;
+ uint32_t newsize = (rws->size >= UINT32_MAX/2)? UINT32_MAX/2 : rws->size * 2;
+ uint32_t newsizeK = newsize/(1024/sizeof(int));
+
+ if (newsizeK + mb->heap_used > mb->heap_limit)
+ newsizeK = (uint32_t)(mb->heap_limit - mb->heap_used);
+ newsize = newsizeK*(1024/sizeof(int));
+
if (newsize < RWS_RSIZE + ovecsize + RWS_ANCHOR_SIZE)
return PCRE2_ERROR_HEAPLIMIT;
new = mb->memctl.malloc(newsize*sizeof(int), mb->memctl.memory_data);
if (new == NULL) return PCRE2_ERROR_NOMEMORY;
- mb->heap_used += newsize;
+ mb->heap_used += newsizeK;
new->next = NULL;
new->size = newsize;
rws->next = new;
@@ -955,7 +966,7 @@ for (;;)
if (ptr >= end_subject)
{
if ((mb->moptions & PCRE2_PARTIAL_HARD) != 0)
- could_continue = TRUE;
+ return PCRE2_ERROR_PARTIAL;
else { ADD_ACTIVE(state_offset + 1, 0); }
}
break;
@@ -1004,10 +1015,12 @@ for (;;)
/*-----------------------------------------------------------------*/
case OP_EODN:
- if (clen == 0 && (mb->moptions & PCRE2_PARTIAL_HARD) != 0)
- could_continue = TRUE;
- else if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - mb->nllen))
- { ADD_ACTIVE(state_offset + 1, 0); }
+ if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - mb->nllen))
+ {
+ if ((mb->moptions & PCRE2_PARTIAL_HARD) != 0)
+ return PCRE2_ERROR_PARTIAL;
+ ADD_ACTIVE(state_offset + 1, 0);
+ }
break;
/*-----------------------------------------------------------------*/
@@ -2560,7 +2573,7 @@ for (;;)
if (clen > 0)
{
isinclass = (c > 255)? (codevalue == OP_NCLASS) :
- ((((uint8_t *)(code + 1))[c/8] & (1 << (c&7))) != 0);
+ ((((uint8_t *)(code + 1))[c/8] & (1u << (c&7))) != 0);
}
}
@@ -2753,7 +2766,7 @@ for (;;)
/* There is also an always-true condition */
else if (condcode == OP_TRUE)
- { ADD_ACTIVE(state_offset + LINK_SIZE + 2 + IMM2_SIZE, 0); }
+ { ADD_ACTIVE(state_offset + LINK_SIZE + 2, 0); }
/* The only supported version of OP_RREF is for the value RREF_ANY,
which means "test if in any recursion". We can't test for specifically
@@ -3145,8 +3158,8 @@ for (;;)
/* We have finished the processing at the current subject character. If no
new states have been set for the next character, we have found all the
- matches that we are going to find. If we are at the top level and partial
- matching has been requested, check for appropriate conditions.
+ matches that we are going to find. If partial matching has been requested,
+ check for appropriate conditions.
The "forced_ fail" variable counts the number of (*F) encountered for the
character. If it is equal to the original active_count (saved in
@@ -3158,22 +3171,24 @@ for (;;)
if (new_count <= 0)
{
- if (rlevel == 1 && /* Top level, and */
- could_continue && /* Some could go on, and */
+ if (could_continue && /* Some could go on, and */
forced_fail != workspace[1] && /* Not all forced fail & */
( /* either... */
(mb->moptions & PCRE2_PARTIAL_HARD) != 0 /* Hard partial */
|| /* or... */
((mb->moptions & PCRE2_PARTIAL_SOFT) != 0 && /* Soft partial and */
- match_count < 0) /* no matches */
+ match_count < 0) /* no matches */
) && /* And... */
(
- partial_newline || /* Either partial NL */
- ( /* or ... */
- ptr >= end_subject && /* End of subject and */
- ptr > mb->start_used_ptr) /* Inspected non-empty string */
+ partial_newline || /* Either partial NL */
+ ( /* or ... */
+ ptr >= end_subject && /* End of subject and */
+ ( /* either */
+ ptr > mb->start_used_ptr || /* Inspected non-empty string */
+ mb->allowemptypartial /* or pattern has lookbehind */
+ ) /* or could match empty */
)
- )
+ ))
match_count = PCRE2_ERROR_PARTIAL;
break; /* Exit from loop along the subject string */
}
@@ -3226,6 +3241,8 @@ pcre2_dfa_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,
pcre2_match_context *mcontext, int *workspace, PCRE2_SIZE wscount)
{
int rc;
+int was_zero_terminated = 0;
+
const pcre2_real_code *re = (const pcre2_real_code *)code;
PCRE2_SPTR start_match;
@@ -3237,6 +3254,11 @@ BOOL utf, anchored, startline, firstline;
BOOL has_first_cu = FALSE;
BOOL has_req_cu = FALSE;
+#if PCRE2_CODE_UNIT_WIDTH == 8
+BOOL memchr_not_found_first_cu = FALSE;
+BOOL memchr_not_found_first_cu2 = FALSE;
+#endif
+
PCRE2_UCHAR first_cu = 0;
PCRE2_UCHAR first_cu2 = 0;
PCRE2_UCHAR req_cu = 0;
@@ -3265,7 +3287,11 @@ rws->free = RWS_BASE_SIZE - RWS_ANCHOR_SIZE;
/* A length equal to PCRE2_ZERO_TERMINATED implies a zero-terminated
subject string. */
-if (length == PCRE2_ZERO_TERMINATED) length = PRIV(strlen)(subject);
+if (length == PCRE2_ZERO_TERMINATED)
+ {
+ length = PRIV(strlen)(subject);
+ was_zero_terminated = 1;
+ }
/* Plausibility checks */
@@ -3282,6 +3308,11 @@ if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0 &&
((re->overall_options | options) & PCRE2_ENDANCHORED) != 0)
return PCRE2_ERROR_BADOPTION;
+/* Invalid UTF support is not available for DFA matching. */
+
+if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0)
+ return PCRE2_ERROR_DFA_UINVALID_UTF;
+
/* Check that the first field in the block is the magic number. If it is not,
return with PCRE2_ERROR_BADMAGIC. */
@@ -3391,6 +3422,8 @@ mb->tables = re->tables;
mb->start_subject = subject;
mb->end_subject = end_subject;
mb->start_offset = start_offset;
+mb->allowemptypartial = (re->max_lookbehind > 0) ||
+ (re->flags & PCRE2_MATCH_EMPTY) != 0;
mb->moptions = options;
mb->poptions = re->overall_options;
mb->match_call_count = 0;
@@ -3518,10 +3551,20 @@ if ((re->flags & PCRE2_LASTSET) != 0)
}
}
+/* If the match data block was previously used with PCRE2_COPY_MATCHED_SUBJECT,
+free the memory that was obtained. */
+
+if ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0)
+ {
+ match_data->memctl.free((void *)match_data->subject,
+ match_data->memctl.memory_data);
+ match_data->flags &= ~PCRE2_MD_COPIED_SUBJECT;
+ }
+
/* Fill in fields that are always returned in the match data. */
match_data->code = re;
-match_data->subject = subject;
+match_data->subject = NULL; /* Default for no match */
match_data->mark = NULL;
match_data->matchedby = PCRE2_MATCHEDBY_DFA_INTERPRETER;
@@ -3586,7 +3629,7 @@ for (;;)
#if PCRE2_CODE_UNIT_WIDTH != 8
if (c > 255) c = 255;
#endif
- ok = (start_bits[c/8] & (1 << (c&7))) != 0;
+ ok = (start_bits[c/8] & (1u << (c&7))) != 0;
}
}
if (!ok) break;
@@ -3596,7 +3639,10 @@ for (;;)
/* Not anchored. Advance to a unique first code unit if there is one. In
8-bit mode, the use of memchr() gives a big speed up, even though we have
to call it twice in caseless mode, in order to find the earliest occurrence
- of the character in either of its cases. */
+ of the character in either of its cases. If a call to memchr() that
+ searches the rest of the subject fails to find one case, remember that in
+ order not to keep on repeating the search. This can make a huge difference
+ when the strings are very long and only one case is present. */
else
{
@@ -3610,11 +3656,29 @@ for (;;)
(smc = UCHAR21TEST(start_match)) != first_cu &&
smc != first_cu2)
start_match++;
+
#else /* 8-bit code units */
- PCRE2_SPTR pp1 =
- memchr(start_match, first_cu, end_subject-start_match);
- PCRE2_SPTR pp2 =
- memchr(start_match, first_cu2, end_subject-start_match);
+ PCRE2_SPTR pp1 = NULL;
+ PCRE2_SPTR pp2 = NULL;
+ PCRE2_SIZE cu2size = end_subject - start_match;
+
+ if (!memchr_not_found_first_cu)
+ {
+ pp1 = memchr(start_match, first_cu, end_subject - start_match);
+ if (pp1 == NULL) memchr_not_found_first_cu = TRUE;
+ else cu2size = pp1 - start_match;
+ }
+
+ /* If pp1 is not NULL, we have arranged to search only as far as pp1,
+ to see if the other case is earlier, so we can set "not found" only
+ when both searches have returned NULL. */
+
+ if (!memchr_not_found_first_cu2)
+ {
+ pp2 = memchr(start_match, first_cu2, cu2size);
+ memchr_not_found_first_cu2 = (pp2 == NULL && pp1 == NULL);
+ }
+
if (pp1 == NULL)
start_match = (pp2 == NULL)? end_subject : pp2;
else
@@ -3630,7 +3694,7 @@ for (;;)
while (start_match < end_subject && UCHAR21TEST(start_match) !=
first_cu)
start_match++;
-#else
+#else /* 8-bit code units */
start_match = memchr(start_match, first_cu, end_subject - start_match);
if (start_match == NULL) start_match = end_subject;
#endif
@@ -3697,7 +3761,7 @@ for (;;)
#if PCRE2_CODE_UNIT_WIDTH != 8
if (c > 255) c = 255;
#endif
- if ((start_bits[c/8] & (1 << (c&7))) != 0) break;
+ if ((start_bits[c/8] & (1u << (c&7))) != 0) break;
start_match++;
}
@@ -3717,6 +3781,8 @@ for (;;)
if ((mb->moptions & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) == 0)
{
+ PCRE2_SPTR p;
+
/* The minimum matching length is a lower bound; no actual string of that
length may actually match the pattern. Although the value is, strictly,
in characters, we treat it as code units to avoid spending too much time
@@ -3730,37 +3796,63 @@ for (;;)
point. This optimization can save a huge amount of backtracking in
patterns with nested unlimited repeats that aren't going to match.
Writing separate code for cased/caseless versions makes it go faster, as
- does using an autoincrement and backing off on a match.
+ does using an autoincrement and backing off on a match. As in the case of
+ the first code unit, using memchr() in the 8-bit library gives a big
+ speed up. Unlike the first_cu check above, we do not need to call
+ memchr() twice in the caseless case because we only need to check for the
+ presence of the character in either case, not find the first occurrence.
+
+ The search can be skipped if the code unit was found later than the
+ current starting point in a previous iteration of the bumpalong loop.
HOWEVER: when the subject string is very, very long, searching to its end
can take a long time, and give bad performance on quite ordinary
patterns. This showed up when somebody was matching something like
/^\d+C/ on a 32-megabyte string... so we don't do this when the string is
- sufficiently long. */
+ sufficiently long, but it's worth searching a lot more for unanchored
+ patterns. */
- if (has_req_cu && end_subject - start_match < REQ_CU_MAX)
+ p = start_match + (has_first_cu? 1:0);
+ if (has_req_cu && p > req_cu_ptr)
{
- PCRE2_SPTR p = start_match + (has_first_cu? 1:0);
-
- /* We don't need to repeat the search if we haven't yet reached the
- place we found it at last time. */
+ PCRE2_SIZE check_length = end_subject - start_match;
- if (p > req_cu_ptr)
+ if (check_length < REQ_CU_MAX ||
+ (!anchored && check_length < REQ_CU_MAX * 1000))
{
- if (req_cu != req_cu2)
+ if (req_cu != req_cu2) /* Caseless */
{
+#if PCRE2_CODE_UNIT_WIDTH != 8
while (p < end_subject)
{
uint32_t pp = UCHAR21INCTEST(p);
if (pp == req_cu || pp == req_cu2) { p--; break; }
}
+#else /* 8-bit code units */
+ PCRE2_SPTR pp = p;
+ p = memchr(pp, req_cu, end_subject - pp);
+ if (p == NULL)
+ {
+ p = memchr(pp, req_cu2, end_subject - pp);
+ if (p == NULL) p = end_subject;
+ }
+#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */
}
+
+ /* The caseful case */
+
else
{
+#if PCRE2_CODE_UNIT_WIDTH != 8
while (p < end_subject)
{
if (UCHAR21INCTEST(p) == req_cu) { p--; break; }
}
+
+#else /* 8-bit code units */
+ p = memchr(p, req_cu, end_subject - p);
+ if (p == NULL) p = end_subject;
+#endif
}
/* If we can't find the required code unit, break the matching loop,
@@ -3816,6 +3908,20 @@ for (;;)
match_data->rightchar = (PCRE2_SIZE)( mb->last_used_ptr - subject);
match_data->startchar = (PCRE2_SIZE)(start_match - subject);
match_data->rc = rc;
+
+ if (rc >= 0 &&(options & PCRE2_COPY_MATCHED_SUBJECT) != 0)
+ {
+ length = CU2BYTES(length + was_zero_terminated);
+ match_data->subject = match_data->memctl.malloc(length,
+ match_data->memctl.memory_data);
+ if (match_data->subject == NULL) return PCRE2_ERROR_NOMEMORY;
+ memcpy((void *)match_data->subject, subject, length);
+ match_data->flags |= PCRE2_MD_COPIED_SUBJECT;
+ }
+ else
+ {
+ if (rc >= 0 || rc == PCRE2_ERROR_PARTIAL) match_data->subject = subject;
+ }
goto EXIT;
}
diff --git a/src/pcre2_error.c b/src/pcre2_error.c
index 4b3b3f1..c61648c 100644
--- a/src/pcre2_error.c
+++ b/src/pcre2_error.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -71,7 +71,7 @@ static const unsigned char compile_error_texts[] =
/* 5 */
"number too big in {} quantifier\0"
"missing terminating ] for character class\0"
- "invalid escape sequence in character class\0"
+ "escape sequence is invalid in character class\0"
"range out of order in character class\0"
"quantifier does not follow a repeatable item\0"
/* 10 */
@@ -95,7 +95,7 @@ static const unsigned char compile_error_texts[] =
/* 25 */
"lookbehind assertion is not fixed length\0"
"a relative value of zero is not allowed\0"
- "conditional group contains more than two branches\0"
+ "conditional subpattern contains more than two branches\0"
"assertion expected after (?( or (?(?C)\0"
"digit expected after (?+ or (?-\0"
/* 30 */
@@ -113,21 +113,21 @@ static const unsigned char compile_error_texts[] =
/* 40 */
"invalid escape sequence in (*VERB) name\0"
"unrecognized character after (?P\0"
- "syntax error in subpattern name (missing terminator)\0"
+ "syntax error in subpattern name (missing terminator?)\0"
"two named subpatterns have the same name (PCRE2_DUPNAMES not set)\0"
- "group name must start with a non-digit\0"
+ "subpattern name must start with a non-digit\0"
/* 45 */
"this version of PCRE2 does not have support for \\P, \\p, or \\X\0"
"malformed \\P or \\p sequence\0"
"unknown property name after \\P or \\p\0"
- "subpattern name is too long (maximum " XSTRING(MAX_NAME_SIZE) " characters)\0"
+ "subpattern name is too long (maximum " XSTRING(MAX_NAME_SIZE) " code units)\0"
"too many named subpatterns (maximum " XSTRING(MAX_NAME_COUNT) ")\0"
/* 50 */
"invalid range in character class\0"
"octal value is greater than \\377 in 8-bit non-UTF-8 mode\0"
"internal error: overran compiling workspace\0"
"internal error: previously-checked referenced subpattern not found\0"
- "DEFINE group contains more than one branch\0"
+ "DEFINE subpattern contains more than one branch\0"
/* 55 */
"missing opening brace after \\o\0"
"internal error: unknown newline setting\0"
@@ -137,7 +137,7 @@ static const unsigned char compile_error_texts[] =
"obsolete error (should not occur)\0" /* Was the above */
/* 60 */
"(*VERB) not recognized or malformed\0"
- "group number is too big\0"
+ "subpattern number is too big\0"
"subpattern name expected\0"
"internal error: parsed pattern overflow\0"
"non-octal character in \\o{} (closing brace missing?)\0"
@@ -181,6 +181,11 @@ static const unsigned char compile_error_texts[] =
"invalid option bits with PCRE2_LITERAL\0"
"\\N{U+dddd} is supported only in Unicode (UTF) mode\0"
"invalid hyphen in option setting\0"
+ /* 95 */
+ "(*alpha_assertion) not recognized\0"
+ "script runs require Unicode support, which this version of PCRE2 does not have\0"
+ "too many capturing groups (maximum 65535)\0"
+ "atomic assertion expected after (?( or (?(?C)\0"
;
/* Match-time and UTF error texts are in the same format. */
@@ -265,6 +270,7 @@ static const unsigned char match_error_texts[] =
"invalid syntax\0"
/* 65 */
"internal error - duplicate substitution match\0"
+ "PCRE2_MATCH_INVALID_UTF is not supported for DFA matching\0"
;
diff --git a/src/pcre2_extuni.c b/src/pcre2_extuni.c
index 237211a..5a719e9 100644
--- a/src/pcre2_extuni.c
+++ b/src/pcre2_extuni.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -100,7 +100,7 @@ while (eptr < end_subject)
int len = 1;
if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
rgb = UCD_GRAPHBREAK(c);
- if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
+ if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break;
/* Not breaking between Regional Indicators is allowed only if there
are an even number of preceding RIs. */
diff --git a/src/pcre2_internal.h b/src/pcre2_internal.h
index 8750f2f..fe8ffe5 100644
--- a/src/pcre2_internal.h
+++ b/src/pcre2_internal.h
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -148,16 +148,7 @@ pcre2_match() because of the way it backtracks. */
/* When checking for integer overflow in pcre2_compile(), we need to handle
large integers. If a 64-bit integer type is available, we can use that.
Otherwise we have to cast to double, which of course requires floating point
-arithmetic. Handle this by defining a macro for the appropriate type. If
-stdint.h is available, include it; it may define INT64_MAX. Systems that do not
-have stdint.h (e.g. Solaris) may have inttypes.h. The macro int64_t may be set
-by "configure". */
-
-#if defined HAVE_STDINT_H
-#include
-#elif defined HAVE_INTTYPES_H
-#include
-#endif
+arithmetic. Handle this by defining a macro for the appropriate type. */
#if defined INT64_MAX || defined int64_t
#define INT64_OR_DOUBLE int64_t
@@ -526,6 +517,7 @@ bytes in a code unit in that mode. */
#define PCRE2_HASBKPORX 0x00100000 /* contains \P, \p, or \X */
#define PCRE2_DUPCAPUSED 0x00200000 /* contains (?| */
#define PCRE2_HASBKC 0x00400000 /* contains \C */
+#define PCRE2_HASACCEPT 0x00800000 /* contains (*ACCEPT) */
#define PCRE2_MODE_MASK (PCRE2_MODE8 | PCRE2_MODE16 | PCRE2_MODE32)
@@ -535,18 +527,23 @@ enum { PCRE2_MATCHEDBY_INTERPRETER, /* pcre2_match() */
PCRE2_MATCHEDBY_DFA_INTERPRETER, /* pcre2_dfa_match() */
PCRE2_MATCHEDBY_JIT }; /* pcre2_jit_match() */
+/* Values for the flags field in a match data block. */
+
+#define PCRE2_MD_COPIED_SUBJECT 0x01u
+
/* Magic number to provide a small check against being handed junk. */
#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */
/* The maximum remaining length of subject we are prepared to search for a
-req_unit match. In 8-bit mode, memchr() is used and is much faster than the
-search loop that has to be used in 16-bit and 32-bit modes. */
+req_unit match from an anchored pattern. In 8-bit mode, memchr() is used and is
+much faster than the search loop that has to be used in 16-bit and 32-bit
+modes. */
#if PCRE2_CODE_UNIT_WIDTH == 8
-#define REQ_CU_MAX 2000
+#define REQ_CU_MAX 5000
#else
-#define REQ_CU_MAX 1000
+#define REQ_CU_MAX 2000
#endif
/* Offsets for the bitmap tables in the cbits set of tables. Each table
@@ -569,11 +566,11 @@ these tables. */
without checking pcre2_jit_compile.c, which has an assertion to ensure that
ctype_word has the value 16. */
-#define ctype_space 0x01
-#define ctype_letter 0x02
-#define ctype_digit 0x04
-#define ctype_xdigit 0x08 /* not actually used any more */
-#define ctype_word 0x10 /* alphanumeric or '_' */
+#define ctype_space 0x01
+#define ctype_letter 0x02
+#define ctype_lcletter 0x04
+#define ctype_digit 0x08
+#define ctype_word 0x10 /* alphanumeric or '_' */
/* Offsets of the various tables from the base tables pointer, and
total length of the tables. */
@@ -874,34 +871,52 @@ a positive value. */
#define STR_RIGHT_CURLY_BRACKET "}"
#define STR_TILDE "~"
-#define STRING_ACCEPT0 "ACCEPT\0"
-#define STRING_COMMIT0 "COMMIT\0"
-#define STRING_F0 "F\0"
-#define STRING_FAIL0 "FAIL\0"
-#define STRING_MARK0 "MARK\0"
-#define STRING_PRUNE0 "PRUNE\0"
-#define STRING_SKIP0 "SKIP\0"
-#define STRING_THEN "THEN"
-
-#define STRING_alpha0 "alpha\0"
-#define STRING_lower0 "lower\0"
-#define STRING_upper0 "upper\0"
-#define STRING_alnum0 "alnum\0"
-#define STRING_ascii0 "ascii\0"
-#define STRING_blank0 "blank\0"
-#define STRING_cntrl0 "cntrl\0"
-#define STRING_digit0 "digit\0"
-#define STRING_graph0 "graph\0"
-#define STRING_print0 "print\0"
-#define STRING_punct0 "punct\0"
-#define STRING_space0 "space\0"
-#define STRING_word0 "word\0"
-#define STRING_xdigit "xdigit"
-
-#define STRING_DEFINE "DEFINE"
-#define STRING_VERSION "VERSION"
-#define STRING_WEIRD_STARTWORD "[:<:]]"
-#define STRING_WEIRD_ENDWORD "[:>:]]"
+#define STRING_ACCEPT0 "ACCEPT\0"
+#define STRING_COMMIT0 "COMMIT\0"
+#define STRING_F0 "F\0"
+#define STRING_FAIL0 "FAIL\0"
+#define STRING_MARK0 "MARK\0"
+#define STRING_PRUNE0 "PRUNE\0"
+#define STRING_SKIP0 "SKIP\0"
+#define STRING_THEN "THEN"
+
+#define STRING_atomic0 "atomic\0"
+#define STRING_pla0 "pla\0"
+#define STRING_plb0 "plb\0"
+#define STRING_napla0 "napla\0"
+#define STRING_naplb0 "naplb\0"
+#define STRING_nla0 "nla\0"
+#define STRING_nlb0 "nlb\0"
+#define STRING_sr0 "sr\0"
+#define STRING_asr0 "asr\0"
+#define STRING_positive_lookahead0 "positive_lookahead\0"
+#define STRING_positive_lookbehind0 "positive_lookbehind\0"
+#define STRING_non_atomic_positive_lookahead0 "non_atomic_positive_lookahead\0"
+#define STRING_non_atomic_positive_lookbehind0 "non_atomic_positive_lookbehind\0"
+#define STRING_negative_lookahead0 "negative_lookahead\0"
+#define STRING_negative_lookbehind0 "negative_lookbehind\0"
+#define STRING_script_run0 "script_run\0"
+#define STRING_atomic_script_run "atomic_script_run"
+
+#define STRING_alpha0 "alpha\0"
+#define STRING_lower0 "lower\0"
+#define STRING_upper0 "upper\0"
+#define STRING_alnum0 "alnum\0"
+#define STRING_ascii0 "ascii\0"
+#define STRING_blank0 "blank\0"
+#define STRING_cntrl0 "cntrl\0"
+#define STRING_digit0 "digit\0"
+#define STRING_graph0 "graph\0"
+#define STRING_print0 "print\0"
+#define STRING_punct0 "punct\0"
+#define STRING_space0 "space\0"
+#define STRING_word0 "word\0"
+#define STRING_xdigit "xdigit"
+
+#define STRING_DEFINE "DEFINE"
+#define STRING_VERSION "VERSION"
+#define STRING_WEIRD_STARTWORD "[:<:]]"
+#define STRING_WEIRD_ENDWORD "[:>:]]"
#define STRING_CR_RIGHTPAR "CR)"
#define STRING_LF_RIGHTPAR "LF)"
@@ -1150,34 +1165,52 @@ only. */
#define STR_RIGHT_CURLY_BRACKET "\175"
#define STR_TILDE "\176"
-#define STRING_ACCEPT0 STR_A STR_C STR_C STR_E STR_P STR_T "\0"
-#define STRING_COMMIT0 STR_C STR_O STR_M STR_M STR_I STR_T "\0"
-#define STRING_F0 STR_F "\0"
-#define STRING_FAIL0 STR_F STR_A STR_I STR_L "\0"
-#define STRING_MARK0 STR_M STR_A STR_R STR_K "\0"
-#define STRING_PRUNE0 STR_P STR_R STR_U STR_N STR_E "\0"
-#define STRING_SKIP0 STR_S STR_K STR_I STR_P "\0"
-#define STRING_THEN STR_T STR_H STR_E STR_N
-
-#define STRING_alpha0 STR_a STR_l STR_p STR_h STR_a "\0"
-#define STRING_lower0 STR_l STR_o STR_w STR_e STR_r "\0"
-#define STRING_upper0 STR_u STR_p STR_p STR_e STR_r "\0"
-#define STRING_alnum0 STR_a STR_l STR_n STR_u STR_m "\0"
-#define STRING_ascii0 STR_a STR_s STR_c STR_i STR_i "\0"
-#define STRING_blank0 STR_b STR_l STR_a STR_n STR_k "\0"
-#define STRING_cntrl0 STR_c STR_n STR_t STR_r STR_l "\0"
-#define STRING_digit0 STR_d STR_i STR_g STR_i STR_t "\0"
-#define STRING_graph0 STR_g STR_r STR_a STR_p STR_h "\0"
-#define STRING_print0 STR_p STR_r STR_i STR_n STR_t "\0"
-#define STRING_punct0 STR_p STR_u STR_n STR_c STR_t "\0"
-#define STRING_space0 STR_s STR_p STR_a STR_c STR_e "\0"
-#define STRING_word0 STR_w STR_o STR_r STR_d "\0"
-#define STRING_xdigit STR_x STR_d STR_i STR_g STR_i STR_t
-
-#define STRING_DEFINE STR_D STR_E STR_F STR_I STR_N STR_E
-#define STRING_VERSION STR_V STR_E STR_R STR_S STR_I STR_O STR_N
-#define STRING_WEIRD_STARTWORD STR_LEFT_SQUARE_BRACKET STR_COLON STR_LESS_THAN_SIGN STR_COLON STR_RIGHT_SQUARE_BRACKET STR_RIGHT_SQUARE_BRACKET
-#define STRING_WEIRD_ENDWORD STR_LEFT_SQUARE_BRACKET STR_COLON STR_GREATER_THAN_SIGN STR_COLON STR_RIGHT_SQUARE_BRACKET STR_RIGHT_SQUARE_BRACKET
+#define STRING_ACCEPT0 STR_A STR_C STR_C STR_E STR_P STR_T "\0"
+#define STRING_COMMIT0 STR_C STR_O STR_M STR_M STR_I STR_T "\0"
+#define STRING_F0 STR_F "\0"
+#define STRING_FAIL0 STR_F STR_A STR_I STR_L "\0"
+#define STRING_MARK0 STR_M STR_A STR_R STR_K "\0"
+#define STRING_PRUNE0 STR_P STR_R STR_U STR_N STR_E "\0"
+#define STRING_SKIP0 STR_S STR_K STR_I STR_P "\0"
+#define STRING_THEN STR_T STR_H STR_E STR_N
+
+#define STRING_atomic0 STR_a STR_t STR_o STR_m STR_i STR_c "\0"
+#define STRING_pla0 STR_p STR_l STR_a "\0"
+#define STRING_plb0 STR_p STR_l STR_b "\0"
+#define STRING_napla0 STR_n STR_a STR_p STR_l STR_a "\0"
+#define STRING_naplb0 STR_n STR_a STR_p STR_l STR_b "\0"
+#define STRING_nla0 STR_n STR_l STR_a "\0"
+#define STRING_nlb0 STR_n STR_l STR_b "\0"
+#define STRING_sr0 STR_s STR_r "\0"
+#define STRING_asr0 STR_a STR_s STR_r "\0"
+#define STRING_positive_lookahead0 STR_p STR_o STR_s STR_i STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_a STR_h STR_e STR_a STR_d "\0"
+#define STRING_positive_lookbehind0 STR_p STR_o STR_s STR_i STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_b STR_e STR_h STR_i STR_n STR_d "\0"
+#define STRING_non_atomic_positive_lookahead0 STR_n STR_o STR_n STR_UNDERSCORE STR_a STR_t STR_o STR_m STR_i STR_c STR_UNDERSCORE STR_p STR_o STR_s STR_i STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_a STR_h STR_e STR_a STR_d "\0"
+#define STRING_non_atomic_positive_lookbehind0 STR_n STR_o STR_n STR_UNDERSCORE STR_a STR_t STR_o STR_m STR_i STR_c STR_UNDERSCORE STR_p STR_o STR_s STR_i STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_b STR_e STR_h STR_i STR_n STR_d "\0"
+#define STRING_negative_lookahead0 STR_n STR_e STR_g STR_a STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_a STR_h STR_e STR_a STR_d "\0"
+#define STRING_negative_lookbehind0 STR_n STR_e STR_g STR_a STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_b STR_e STR_h STR_i STR_n STR_d "\0"
+#define STRING_script_run0 STR_s STR_c STR_r STR_i STR_p STR_t STR_UNDERSCORE STR_r STR_u STR_n "\0"
+#define STRING_atomic_script_run STR_a STR_t STR_o STR_m STR_i STR_c STR_UNDERSCORE STR_s STR_c STR_r STR_i STR_p STR_t STR_UNDERSCORE STR_r STR_u STR_n
+
+#define STRING_alpha0 STR_a STR_l STR_p STR_h STR_a "\0"
+#define STRING_lower0 STR_l STR_o STR_w STR_e STR_r "\0"
+#define STRING_upper0 STR_u STR_p STR_p STR_e STR_r "\0"
+#define STRING_alnum0 STR_a STR_l STR_n STR_u STR_m "\0"
+#define STRING_ascii0 STR_a STR_s STR_c STR_i STR_i "\0"
+#define STRING_blank0 STR_b STR_l STR_a STR_n STR_k "\0"
+#define STRING_cntrl0 STR_c STR_n STR_t STR_r STR_l "\0"
+#define STRING_digit0 STR_d STR_i STR_g STR_i STR_t "\0"
+#define STRING_graph0 STR_g STR_r STR_a STR_p STR_h "\0"
+#define STRING_print0 STR_p STR_r STR_i STR_n STR_t "\0"
+#define STRING_punct0 STR_p STR_u STR_n STR_c STR_t "\0"
+#define STRING_space0 STR_s STR_p STR_a STR_c STR_e "\0"
+#define STRING_word0 STR_w STR_o STR_r STR_d "\0"
+#define STRING_xdigit STR_x STR_d STR_i STR_g STR_i STR_t
+
+#define STRING_DEFINE STR_D STR_E STR_F STR_I STR_N STR_E
+#define STRING_VERSION STR_V STR_E STR_R STR_S STR_I STR_O STR_N
+#define STRING_WEIRD_STARTWORD STR_LEFT_SQUARE_BRACKET STR_COLON STR_LESS_THAN_SIGN STR_COLON STR_RIGHT_SQUARE_BRACKET STR_RIGHT_SQUARE_BRACKET
+#define STRING_WEIRD_ENDWORD STR_LEFT_SQUARE_BRACKET STR_COLON STR_GREATER_THAN_SIGN STR_COLON STR_RIGHT_SQUARE_BRACKET STR_RIGHT_SQUARE_BRACKET
#define STRING_CR_RIGHTPAR STR_C STR_R STR_RIGHT_PARENTHESIS
#define STRING_LF_RIGHTPAR STR_L STR_F STR_RIGHT_PARENTHESIS
@@ -1278,7 +1311,7 @@ enum { ESC_A = 1, ESC_G, ESC_K, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s,
Starting from 1 (i.e. after OP_END), the values up to OP_EOD must correspond in
order to the list of escapes immediately above. Furthermore, values up to
OP_DOLLM must not be changed without adjusting the table called autoposstab in
-pcre2_auto_possess.c
+pcre2_auto_possess.c.
Whenever this list is updated, the two macro definitions that follow must be
updated to match. The possessification table called "opcode_possessify" in
@@ -1476,79 +1509,81 @@ enum {
OP_KETRMIN, /* 123 order. They are for groups the repeat for ever. */
OP_KETRPOS, /* 124 Possessive unlimited repeat. */
- /* The assertions must come before BRA, CBRA, ONCE, and COND, and the four
- asserts must remain in order. */
+ /* The assertions must come before BRA, CBRA, ONCE, and COND. */
OP_REVERSE, /* 125 Move pointer back - used in lookbehind assertions */
OP_ASSERT, /* 126 Positive lookahead */
OP_ASSERT_NOT, /* 127 Negative lookahead */
OP_ASSERTBACK, /* 128 Positive lookbehind */
OP_ASSERTBACK_NOT, /* 129 Negative lookbehind */
-
- /* ONCE, BRA, BRAPOS, CBRA, CBRAPOS, and COND must come immediately after the
- assertions, with ONCE first, as there's a test for >= ONCE for a subpattern
- that isn't an assertion. The POS versions must immediately follow the non-POS
- versions in each case. */
-
- OP_ONCE, /* 130 Atomic group, contains captures */
- OP_BRA, /* 131 Start of non-capturing bracket */
- OP_BRAPOS, /* 132 Ditto, with unlimited, possessive repeat */
- OP_CBRA, /* 133 Start of capturing bracket */
- OP_CBRAPOS, /* 134 Ditto, with unlimited, possessive repeat */
- OP_COND, /* 135 Conditional group */
+ OP_ASSERT_NA, /* 130 Positive non-atomic lookahead */
+ OP_ASSERTBACK_NA, /* 131 Positive non-atomic lookbehind */
+
+ /* ONCE, SCRIPT_RUN, BRA, BRAPOS, CBRA, CBRAPOS, and COND must come
+ immediately after the assertions, with ONCE first, as there's a test for >=
+ ONCE for a subpattern that isn't an assertion. The POS versions must
+ immediately follow the non-POS versions in each case. */
+
+ OP_ONCE, /* 132 Atomic group, contains captures */
+ OP_SCRIPT_RUN, /* 133 Non-capture, but check characters' scripts */
+ OP_BRA, /* 134 Start of non-capturing bracket */
+ OP_BRAPOS, /* 135 Ditto, with unlimited, possessive repeat */
+ OP_CBRA, /* 136 Start of capturing bracket */
+ OP_CBRAPOS, /* 137 Ditto, with unlimited, possessive repeat */
+ OP_COND, /* 138 Conditional group */
/* These five must follow the previous five, in the same order. There's a
check for >= SBRA to distinguish the two sets. */
- OP_SBRA, /* 136 Start of non-capturing bracket, check empty */
- OP_SBRAPOS, /* 137 Ditto, with unlimited, possessive repeat */
- OP_SCBRA, /* 138 Start of capturing bracket, check empty */
- OP_SCBRAPOS, /* 139 Ditto, with unlimited, possessive repeat */
- OP_SCOND, /* 140 Conditional group, check empty */
+ OP_SBRA, /* 139 Start of non-capturing bracket, check empty */
+ OP_SBRAPOS, /* 149 Ditto, with unlimited, possessive repeat */
+ OP_SCBRA, /* 141 Start of capturing bracket, check empty */
+ OP_SCBRAPOS, /* 142 Ditto, with unlimited, possessive repeat */
+ OP_SCOND, /* 143 Conditional group, check empty */
/* The next two pairs must (respectively) be kept together. */
- OP_CREF, /* 141 Used to hold a capture number as condition */
- OP_DNCREF, /* 142 Used to point to duplicate names as a condition */
- OP_RREF, /* 143 Used to hold a recursion number as condition */
- OP_DNRREF, /* 144 Used to point to duplicate names as a condition */
- OP_FALSE, /* 145 Always false (used by DEFINE and VERSION) */
- OP_TRUE, /* 146 Always true (used by VERSION) */
+ OP_CREF, /* 144 Used to hold a capture number as condition */
+ OP_DNCREF, /* 145 Used to point to duplicate names as a condition */
+ OP_RREF, /* 146 Used to hold a recursion number as condition */
+ OP_DNRREF, /* 147 Used to point to duplicate names as a condition */
+ OP_FALSE, /* 148 Always false (used by DEFINE and VERSION) */
+ OP_TRUE, /* 149 Always true (used by VERSION) */
- OP_BRAZERO, /* 147 These two must remain together and in this */
- OP_BRAMINZERO, /* 148 order. */
- OP_BRAPOSZERO, /* 149 */
+ OP_BRAZERO, /* 150 These two must remain together and in this */
+ OP_BRAMINZERO, /* 151 order. */
+ OP_BRAPOSZERO, /* 152 */
/* These are backtracking control verbs */
- OP_MARK, /* 150 always has an argument */
- OP_PRUNE, /* 151 */
- OP_PRUNE_ARG, /* 152 same, but with argument */
- OP_SKIP, /* 153 */
- OP_SKIP_ARG, /* 154 same, but with argument */
- OP_THEN, /* 155 */
- OP_THEN_ARG, /* 156 same, but with argument */
- OP_COMMIT, /* 157 */
- OP_COMMIT_ARG, /* 158 same, but with argument */
+ OP_MARK, /* 153 always has an argument */
+ OP_PRUNE, /* 154 */
+ OP_PRUNE_ARG, /* 155 same, but with argument */
+ OP_SKIP, /* 156 */
+ OP_SKIP_ARG, /* 157 same, but with argument */
+ OP_THEN, /* 158 */
+ OP_THEN_ARG, /* 159 same, but with argument */
+ OP_COMMIT, /* 160 */
+ OP_COMMIT_ARG, /* 161 same, but with argument */
/* These are forced failure and success verbs. FAIL and ACCEPT do accept an
argument, but these cases can be compiled as, for example, (*MARK:X)(*FAIL)
without the need for a special opcode. */
- OP_FAIL, /* 159 */
- OP_ACCEPT, /* 160 */
- OP_ASSERT_ACCEPT, /* 161 Used inside assertions */
- OP_CLOSE, /* 162 Used before OP_ACCEPT to close open captures */
+ OP_FAIL, /* 162 */
+ OP_ACCEPT, /* 163 */
+ OP_ASSERT_ACCEPT, /* 164 Used inside assertions */
+ OP_CLOSE, /* 165 Used before OP_ACCEPT to close open captures */
/* This is used to skip a subpattern with a {0} quantifier */
- OP_SKIPZERO, /* 163 */
+ OP_SKIPZERO, /* 166 */
/* This is used to identify a DEFINE group during compilation so that it can
be checked for having only one branch. It is changed to OP_FALSE before
compilation finishes. */
- OP_DEFINE, /* 164 */
+ OP_DEFINE, /* 167 */
/* This is not an opcode, but is used to check that tables indexed by opcode
are the correct length, in order to catch updating errors - there have been
@@ -1561,7 +1596,7 @@ enum {
/* *** NOTE NOTE NOTE *** Whenever the list above is updated, the two macro
definitions that follow must also be updated to match. There are also tables
called "opcode_possessify" in pcre2_compile.c and "coptable" and "poptable" in
-pcre2_dfa_exec.c that must be updated. */
+pcre2_dfa_match.c that must be updated. */
/* This macro defines textual names for all the opcodes. These are used only
@@ -1594,8 +1629,11 @@ some cases doesn't actually use these names at all). */
"class", "nclass", "xclass", "Ref", "Refi", "DnRef", "DnRefi", \
"Recurse", "Callout", "CalloutStr", \
"Alt", "Ket", "KetRmax", "KetRmin", "KetRpos", \
- "Reverse", "Assert", "Assert not", "AssertB", "AssertB not", \
+ "Reverse", "Assert", "Assert not", \
+ "Assert back", "Assert back not", \
+ "Non-atomic assert", "Non-atomic assert back", \
"Once", \
+ "Script run", \
"Bra", "BraPos", "CBra", "CBraPos", \
"Cond", \
"SBra", "SBraPos", "SCBra", "SCBraPos", \
@@ -1678,7 +1716,10 @@ in UTF-8 mode. The code that uses this table must know about such things. */
1+LINK_SIZE, /* Assert not */ \
1+LINK_SIZE, /* Assert behind */ \
1+LINK_SIZE, /* Assert behind not */ \
+ 1+LINK_SIZE, /* NA Assert */ \
+ 1+LINK_SIZE, /* NA Assert behind */ \
1+LINK_SIZE, /* ONCE */ \
+ 1+LINK_SIZE, /* SCRIPT_RUN */ \
1+LINK_SIZE, /* BRA */ \
1+LINK_SIZE, /* BRAPOS */ \
1+LINK_SIZE+IMM2_SIZE, /* CBRA */ \
@@ -1747,6 +1788,8 @@ typedef struct {
uint8_t gbprop; /* ucp_gbControl, etc. (grapheme break property) */
uint8_t caseset; /* offset to multichar other cases or zero */
int32_t other_case; /* offset to other case, or zero if none */
+ int16_t scriptx; /* script extension value */
+ int16_t dummy; /* spare - to round to multiple of 4 bytes */
} ucd_record;
/* UCD access macros */
@@ -1769,6 +1812,7 @@ typedef struct {
#define UCD_GRAPHBREAK(ch) GET_UCD(ch)->gbprop
#define UCD_CASESET(ch) GET_UCD(ch)->caseset
#define UCD_OTHERCASE(ch) ((uint32_t)((int)ch + (int)(GET_UCD(ch)->other_case)))
+#define UCD_SCRIPTX(ch) GET_UCD(ch)->scriptx
/* Header for serialized pcre2 codes. */
@@ -1826,6 +1870,8 @@ extern const uint8_t PRIV(utf8_table4)[];
#define _pcre2_hspace_list PCRE2_SUFFIX(_pcre2_hspace_list_)
#define _pcre2_vspace_list PCRE2_SUFFIX(_pcre2_vspace_list_)
#define _pcre2_ucd_caseless_sets PCRE2_SUFFIX(_pcre2_ucd_caseless_sets_)
+#define _pcre2_ucd_digit_sets PCRE2_SUFFIX(_pcre2_ucd_digit_sets_)
+#define _pcre2_ucd_script_sets PCRE2_SUFFIX(_pcre2_ucd_script_sets_)
#define _pcre2_ucd_records PCRE2_SUFFIX(_pcre2_ucd_records_)
#define _pcre2_ucd_stage1 PCRE2_SUFFIX(_pcre2_ucd_stage1_)
#define _pcre2_ucd_stage2 PCRE2_SUFFIX(_pcre2_ucd_stage2_)
@@ -1847,6 +1893,8 @@ extern const uint8_t PRIV(default_tables)[];
extern const uint32_t PRIV(hspace_list)[];
extern const uint32_t PRIV(vspace_list)[];
extern const uint32_t PRIV(ucd_caseless_sets)[];
+extern const uint32_t PRIV(ucd_digit_sets)[];
+extern const uint8_t PRIV(ucd_script_sets)[];
extern const ucd_record PRIV(ucd_records)[];
#if PCRE2_CODE_UNIT_WIDTH == 32
extern const ucd_record PRIV(dummy_ucd_record)[];
@@ -1894,6 +1942,7 @@ is available. */
#define _pcre2_jit_get_target PCRE2_SUFFIX(_pcre2_jit_get_target_)
#define _pcre2_memctl_malloc PCRE2_SUFFIX(_pcre2_memctl_malloc_)
#define _pcre2_ord2utf PCRE2_SUFFIX(_pcre2_ord2utf_)
+#define _pcre2_script_run PCRE2_SUFFIX(_pcre2_script_run_)
#define _pcre2_strcmp PCRE2_SUFFIX(_pcre2_strcmp_)
#define _pcre2_strcmp_c8 PCRE2_SUFFIX(_pcre2_strcmp_c8_)
#define _pcre2_strcpy_c8 PCRE2_SUFFIX(_pcre2_strcpy_c8_)
@@ -1908,7 +1957,7 @@ is available. */
extern int _pcre2_auto_possessify(PCRE2_UCHAR *, BOOL,
const compile_block *);
extern int _pcre2_check_escape(PCRE2_SPTR *, PCRE2_SPTR, uint32_t *,
- int *, uint32_t, BOOL, compile_block *);
+ int *, uint32_t, uint32_t, BOOL, compile_block *);
extern PCRE2_SPTR _pcre2_extuni(uint32_t, PCRE2_SPTR, PCRE2_SPTR, PCRE2_SPTR,
BOOL, int *);
extern PCRE2_SPTR _pcre2_find_bracket(PCRE2_SPTR, BOOL, int);
@@ -1920,6 +1969,7 @@ extern size_t _pcre2_jit_get_size(void *);
const char * _pcre2_jit_get_target(void);
extern void * _pcre2_memctl_malloc(size_t, pcre2_memctl *);
extern unsigned int _pcre2_ord2utf(uint32_t, PCRE2_UCHAR *);
+extern BOOL _pcre2_script_run(PCRE2_SPTR, PCRE2_SPTR, BOOL);
extern int _pcre2_strcmp(PCRE2_SPTR, PCRE2_SPTR);
extern int _pcre2_strcmp_c8(PCRE2_SPTR, const char *);
extern PCRE2_SIZE _pcre2_strcpy_c8(PCRE2_UCHAR *, const char *);
diff --git a/src/pcre2_intmodedep.h b/src/pcre2_intmodedep.h
index 62626d0..ea3b3ec 100644
--- a/src/pcre2_intmodedep.h
+++ b/src/pcre2_intmodedep.h
@@ -205,19 +205,19 @@ whether its argument, which is assumed to be one code unit, is less than 256.
The CHMAX_255 macro does not assume one code unit. The maximum length of a MARK
name must fit in one code unit; currently it is set to 255 or 65535. The
TABLE_GET macro is used to access elements of tables containing exactly 256
-items. When code points can be greater than 255, a check is needed before
-accessing these tables. */
+items. Its argument is a code unit. When code points can be greater than 255, a
+check is needed before accessing these tables. */
#if PCRE2_CODE_UNIT_WIDTH == 8
#define MAX_255(c) TRUE
#define MAX_MARK ((1u << 8) - 1)
+#define TABLE_GET(c, table, default) ((table)[c])
#ifdef SUPPORT_UNICODE
#define SUPPORT_WIDE_CHARS
#define CHMAX_255(c) ((c) <= 255u)
#else
#define CHMAX_255(c) TRUE
#endif /* SUPPORT_UNICODE */
-#define TABLE_GET(c, table, default) ((table)[c])
#else /* Code units are 16 or 32 bits */
#define CHMAX_255(c) ((c) <= 255u)
@@ -228,7 +228,6 @@ accessing these tables. */
#endif
-
/* ----------------- Character-handling macros ----------------- */
/* There is a proposed future special "UTF-21" mode, in which only the lowest
@@ -585,6 +584,8 @@ typedef struct pcre2_real_match_context {
#endif
int (*callout)(pcre2_callout_block *, void *);
void *callout_data;
+ int (*substitute_callout)(pcre2_substitute_callout_block *, void *);
+ void *substitute_callout_data;
PCRE2_SIZE offset_limit;
uint32_t heap_limit;
uint32_t match_limit;
@@ -656,7 +657,8 @@ typedef struct pcre2_real_match_data {
PCRE2_SIZE leftchar; /* Offset to leftmost code unit */
PCRE2_SIZE rightchar; /* Offset to rightmost code unit */
PCRE2_SIZE startchar; /* Offset to starting code unit */
- uint16_t matchedby; /* Type of match (normal, JIT, DFA) */
+ uint8_t matchedby; /* Type of match (normal, JIT, DFA) */
+ uint8_t flags; /* Various flags */
uint16_t oveccount; /* Number of pairs */
int rc; /* The return code from the match */
PCRE2_SIZE ovector[131072]; /* Must be last in the structure */
@@ -851,6 +853,7 @@ typedef struct match_block {
uint32_t match_call_count; /* Number of times a new frame is created */
BOOL hitend; /* Hit the end of the subject at some point */
BOOL hasthen; /* Pattern contains (*THEN) */
+ BOOL allowemptypartial; /* Allow empty hard partial */
const uint8_t *lcc; /* Points to lower casing table */
const uint8_t *fcc; /* Points to case-flipping table */
const uint8_t *ctypes; /* Points to table of type maps */
@@ -863,6 +866,7 @@ typedef struct match_block {
PCRE2_SPTR name_table; /* Table of group names */
PCRE2_SPTR start_code; /* For use when recursing */
PCRE2_SPTR start_subject; /* Start of the subject string */
+ PCRE2_SPTR check_subject; /* Where UTF-checked from */
PCRE2_SPTR end_subject; /* End of the subject string */
PCRE2_SPTR end_match_ptr; /* Subject position at end match */
PCRE2_SPTR start_used_ptr; /* Earliest consulted character */
@@ -905,6 +909,7 @@ typedef struct dfa_match_block {
uint32_t poptions; /* Pattern options */
uint32_t nltype; /* Newline type */
uint32_t nllen; /* Newline string length */
+ BOOL allowemptypartial; /* Allow empty hard partial */
PCRE2_UCHAR nl[4]; /* Newline string when fixed */
uint16_t bsr_convention; /* \R interpretation */
pcre2_callout_block *cb; /* Points to a callout block */
diff --git a/src/pcre2_jit_compile.c b/src/pcre2_jit_compile.c
index 32e985b..f564127 100644
--- a/src/pcre2_jit_compile.c
+++ b/src/pcre2_jit_compile.c
@@ -6,8 +6,9 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
+ This module by Zoltan Herczeg
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -212,12 +213,6 @@ typedef struct stub_list {
struct stub_list *next;
} stub_list;
-typedef struct label_addr_list {
- struct sljit_label *label;
- sljit_uw *update_addr;
- struct label_addr_list *next;
-} label_addr_list;
-
enum frame_types {
no_frame = -1,
no_stack = -2
@@ -271,6 +266,8 @@ typedef struct bracket_backtrack {
assert_backtrack *assert;
/* For OP_ONCE. Less than 0 if not needed. */
int framesize;
+ /* For brackets with >3 alternatives. */
+ struct sljit_put_label *matching_put_label;
} u;
/* Points to our private memory word on the stack. */
int private_data_ptr;
@@ -416,6 +413,8 @@ typedef struct compiler_common {
sljit_sw lcc;
/* Mode can be PCRE2_JIT_COMPLETE and others. */
int mode;
+ /* TRUE, when empty match is accepted for partial matching. */
+ BOOL allow_empty_partial;
/* TRUE, when minlength is greater than 0. */
BOOL might_be_empty;
/* \K is found in the pattern. */
@@ -454,7 +453,6 @@ typedef struct compiler_common {
struct sljit_label *accept_label;
struct sljit_label *ff_newline_shortcut;
stub_list *stubs;
- label_addr_list *label_addrs;
recurse_entry *entries;
recurse_entry *currententry;
jump_list *partialmatch;
@@ -477,12 +475,22 @@ typedef struct compiler_common {
BOOL alt_circumflex;
#ifdef SUPPORT_UNICODE
BOOL utf;
+ BOOL invalid_utf;
BOOL use_ucp;
+ /* Points to saving area for iref. */
+ sljit_s32 iref_ptr;
jump_list *getucd;
+ jump_list *getucdtype;
#if PCRE2_CODE_UNIT_WIDTH == 8
jump_list *utfreadchar;
- jump_list *utfreadchar16;
jump_list *utfreadtype8;
+ jump_list *utfpeakcharback;
+#endif
+#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16
+ jump_list *utfreadchar_invalid;
+ jump_list *utfreadnewline_invalid;
+ jump_list *utfmoveback_invalid;
+ jump_list *utfpeakcharback_invalid;
#endif
#endif /* SUPPORT_UNICODE */
} compiler_common;
@@ -553,6 +561,12 @@ typedef struct compare_context {
#define ARGUMENTS SLJIT_S4
#define RETURN_ADDR SLJIT_R4
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+#define HAS_VIRTUAL_REGISTERS 1
+#else
+#define HAS_VIRTUAL_REGISTERS 0
+#endif
+
/* Local space layout. */
/* These two locals can be used by the current opcode. */
#define LOCALS0 (0 * sizeof(sljit_sw))
@@ -616,7 +630,196 @@ the start pointers when the end of the capturing group has not yet reached. */
#define READ_CHAR_MAX 0x7fffffff
-#define INVALID_UTF_CHAR 888
+#define INVALID_UTF_CHAR -1
+#define UNASSIGNED_UTF_CHAR 888
+
+#if defined SUPPORT_UNICODE
+#if PCRE2_CODE_UNIT_WIDTH == 8
+
+#define GETCHARINC_INVALID(c, ptr, end, invalid_action) \
+ { \
+ if (ptr[0] <= 0x7f) \
+ c = *ptr++; \
+ else if (ptr + 1 < end && ptr[1] >= 0x80 && ptr[1] < 0xc0) \
+ { \
+ c = ptr[1] - 0x80; \
+ \
+ if (ptr[0] >= 0xc2 && ptr[0] <= 0xdf) \
+ { \
+ c |= (ptr[0] - 0xc0) << 6; \
+ ptr += 2; \
+ } \
+ else if (ptr + 2 < end && ptr[2] >= 0x80 && ptr[2] < 0xc0) \
+ { \
+ c = c << 6 | (ptr[2] - 0x80); \
+ \
+ if (ptr[0] >= 0xe0 && ptr[0] <= 0xef) \
+ { \
+ c |= (ptr[0] - 0xe0) << 12; \
+ ptr += 3; \
+ \
+ if (c < 0x800 || (c >= 0xd800 && c < 0xe000)) \
+ { \
+ invalid_action; \
+ } \
+ } \
+ else if (ptr + 3 < end && ptr[3] >= 0x80 && ptr[3] < 0xc0) \
+ { \
+ c = c << 6 | (ptr[3] - 0x80); \
+ \
+ if (ptr[0] >= 0xf0 && ptr[0] <= 0xf4) \
+ { \
+ c |= (ptr[0] - 0xf0) << 18; \
+ ptr += 4; \
+ \
+ if (c >= 0x110000 || c < 0x10000) \
+ { \
+ invalid_action; \
+ } \
+ } \
+ else \
+ { \
+ invalid_action; \
+ } \
+ } \
+ else \
+ { \
+ invalid_action; \
+ } \
+ } \
+ else \
+ { \
+ invalid_action; \
+ } \
+ } \
+ else \
+ { \
+ invalid_action; \
+ } \
+ }
+
+#define GETCHARBACK_INVALID(c, ptr, start, invalid_action) \
+ { \
+ c = ptr[-1]; \
+ if (c <= 0x7f) \
+ ptr--; \
+ else if (ptr - 1 > start && ptr[-1] >= 0x80 && ptr[-1] < 0xc0) \
+ { \
+ c -= 0x80; \
+ \
+ if (ptr[-2] >= 0xc2 && ptr[-2] <= 0xdf) \
+ { \
+ c |= (ptr[-2] - 0xc0) << 6; \
+ ptr -= 2; \
+ } \
+ else if (ptr - 2 > start && ptr[-2] >= 0x80 && ptr[-2] < 0xc0) \
+ { \
+ c = c << 6 | (ptr[-2] - 0x80); \
+ \
+ if (ptr[-3] >= 0xe0 && ptr[-3] <= 0xef) \
+ { \
+ c |= (ptr[-3] - 0xe0) << 12; \
+ ptr -= 3; \
+ \
+ if (c < 0x800 || (c >= 0xd800 && c < 0xe000)) \
+ { \
+ invalid_action; \
+ } \
+ } \
+ else if (ptr - 3 > start && ptr[-3] >= 0x80 && ptr[-3] < 0xc0) \
+ { \
+ c = c << 6 | (ptr[-3] - 0x80); \
+ \
+ if (ptr[-4] >= 0xf0 && ptr[-4] <= 0xf4) \
+ { \
+ c |= (ptr[-4] - 0xf0) << 18; \
+ ptr -= 4; \
+ \
+ if (c >= 0x110000 || c < 0x10000) \
+ { \
+ invalid_action; \
+ } \
+ } \
+ else \
+ { \
+ invalid_action; \
+ } \
+ } \
+ else \
+ { \
+ invalid_action; \
+ } \
+ } \
+ else \
+ { \
+ invalid_action; \
+ } \
+ } \
+ else \
+ { \
+ invalid_action; \
+ } \
+ }
+
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+
+#define GETCHARINC_INVALID(c, ptr, end, invalid_action) \
+ { \
+ if (ptr[0] < 0xd800 || ptr[0] >= 0xe000) \
+ c = *ptr++; \
+ else if (ptr[0] < 0xdc00 && ptr + 1 < end && ptr[1] >= 0xdc00 && ptr[1] < 0xe000) \
+ { \
+ c = (((ptr[0] - 0xd800) << 10) | (ptr[1] - 0xdc00)) + 0x10000; \
+ ptr += 2; \
+ } \
+ else \
+ { \
+ invalid_action; \
+ } \
+ }
+
+#define GETCHARBACK_INVALID(c, ptr, start, invalid_action) \
+ { \
+ c = ptr[-1]; \
+ if (c < 0xd800 || c >= 0xe000) \
+ ptr--; \
+ else if (c >= 0xdc00 && ptr - 1 > start && ptr[-2] >= 0xd800 && ptr[-2] < 0xdc00) \
+ { \
+ c = (((ptr[-2] - 0xd800) << 10) | (c - 0xdc00)) + 0x10000; \
+ ptr -= 2; \
+ } \
+ else \
+ { \
+ invalid_action; \
+ } \
+ }
+
+
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+
+#define GETCHARINC_INVALID(c, ptr, end, invalid_action) \
+ { \
+ if (ptr[0] < 0xd800 || (ptr[0] >= 0xe000 && ptr[0] < 0x110000)) \
+ c = *ptr++; \
+ else \
+ { \
+ invalid_action; \
+ } \
+ }
+
+#define GETCHARBACK_INVALID(c, ptr, start, invalid_action) \
+ { \
+ c = ptr[-1]; \
+ if (ptr[-1] < 0xd800 || (ptr[-1] >= 0xe000 && ptr[-1] < 0x110000)) \
+ ptr--; \
+ else \
+ { \
+ invalid_action; \
+ } \
+ }
+
+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */
+#endif /* SUPPORT_UNICODE */
static PCRE2_SPTR bracketend(PCRE2_SPTR cc)
{
@@ -716,6 +919,7 @@ switch(*cc)
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
case OP_ONCE:
+ case OP_SCRIPT_RUN:
case OP_BRA:
case OP_BRAPOS:
case OP_CBRA:
@@ -846,8 +1050,8 @@ switch(*cc)
return cc + 1 + 2 + cc[1];
default:
- /* All opcodes are supported now! */
- SLJIT_UNREACHABLE();
+ /* Unsupported opcodes: OP_ASSERT_NA and OP_ASSERTBACK_NA */
+ /* SLJIT_UNREACHABLE(); */
return NULL;
}
}
@@ -869,8 +1073,16 @@ while (cc < ccend)
cc += 1;
break;
- case OP_REF:
case OP_REFI:
+#ifdef SUPPORT_UNICODE
+ if (common->iref_ptr == 0)
+ {
+ common->iref_ptr = common->ovector_start;
+ common->ovector_start += 3 * sizeof(sljit_sw);
+ }
+#endif /* SUPPORT_UNICODE */
+ /* Fall through. */
+ case OP_REF:
common->optimized_cbracket[GET2(cc, 1)] = 0;
cc += 1 + IMM2_SIZE;
break;
@@ -1375,6 +1587,7 @@ while (cc < ccend)
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
case OP_ONCE:
+ case OP_SCRIPT_RUN:
case OP_BRAPOS:
case OP_SBRA:
case OP_SBRAPOS:
@@ -1951,6 +2164,7 @@ while (cc < ccend)
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
case OP_ONCE:
+ case OP_SCRIPT_RUN:
case OP_BRAPOS:
case OP_SBRA:
case OP_SBRAPOS:
@@ -2174,14 +2388,14 @@ if (base_reg != TMP2)
else
{
status.saved_tmp_regs[1] = RETURN_ADDR;
- if (sljit_get_register_index (RETURN_ADDR) == -1)
+ if (HAS_VIRTUAL_REGISTERS)
status.tmp_regs[1] = STR_PTR;
else
status.tmp_regs[1] = RETURN_ADDR;
}
status.saved_tmp_regs[2] = TMP3;
-if (sljit_get_register_index (TMP3) == -1)
+if (HAS_VIRTUAL_REGISTERS)
status.tmp_regs[2] = STR_END;
else
status.tmp_regs[2] = TMP3;
@@ -2274,6 +2488,7 @@ while (cc < ccend)
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
case OP_ONCE:
+ case OP_SCRIPT_RUN:
case OP_BRAPOS:
case OP_SBRA:
case OP_SBRAPOS:
@@ -2631,20 +2846,6 @@ while (list_item)
common->stubs = NULL;
}
-static void add_label_addr(compiler_common *common, sljit_uw *update_addr)
-{
-DEFINE_COMPILER;
-label_addr_list *label_addr;
-
-label_addr = sljit_alloc_memory(compiler, sizeof(label_addr_list));
-if (label_addr == NULL)
- return;
-label_addr->label = LABEL();
-label_addr->update_addr = update_addr;
-label_addr->next = common->label_addrs;
-common->label_addrs = label_addr;
-}
-
static SLJIT_INLINE void count_match(compiler_common *common)
{
DEFINE_COMPILER;
@@ -2787,12 +2988,18 @@ else
}
}
-OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0);
+if (!HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, stack));
+else
+ OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0);
+
if (common->mark_ptr != 0)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0);
if (common->control_head_ptr != 0)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
-OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack));
+if (HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack));
+
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, end));
}
@@ -2831,21 +3038,36 @@ BOOL has_pre;
OP1(SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(1), STR_PTR, 0);
-OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);
-OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);
-if (common->mark_ptr != 0)
- OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
-OP1(SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, oveccount));
-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_S0, 0);
-if (common->mark_ptr != 0)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R2, 0);
-OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, match_data),
- SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE));
+if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);
+ if (common->mark_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
+ OP1(SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, oveccount));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_S0, 0);
+ if (common->mark_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R2, 0);
+ OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, match_data),
+ SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE));
+ }
+else
+ {
+ OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);
+ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, match_data));
+ if (common->mark_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
+ OP1(SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, oveccount));
+ OP1(SLJIT_MOV, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_S0, 0);
+ if (common->mark_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R0, 0);
+ OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE));
+ }
has_pre = sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)) == SLJIT_SUCCESS;
GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START - (has_pre ? sizeof(sljit_sw) : 0));
-OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, begin));
+OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? SLJIT_R0 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
loop = LABEL();
@@ -2907,20 +3129,22 @@ static SLJIT_INLINE void return_with_partial_match(compiler_common *common, stru
{
DEFINE_COMPILER;
sljit_s32 mov_opcode;
+sljit_s32 arguments_reg = !HAS_VIRTUAL_REGISTERS ? ARGUMENTS : SLJIT_R1;
SLJIT_COMPILE_ASSERT(STR_END == SLJIT_S0, str_end_must_be_saved_reg0);
SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0
&& (common->mode == PCRE2_JIT_PARTIAL_SOFT ? common->hit_start != 0 : common->hit_start == 0));
-OP1(SLJIT_MOV, SLJIT_R1, 0, ARGUMENTS, 0);
+if (arguments_reg != ARGUMENTS)
+ OP1(SLJIT_MOV, arguments_reg, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP),
common->mode == PCRE2_JIT_PARTIAL_SOFT ? common->hit_start : common->start_ptr);
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_PARTIAL);
/* Store match begin and end. */
-OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, begin));
-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_R2, 0);
-OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, match_data));
+OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(arguments_reg), SLJIT_OFFSETOF(jit_arguments, begin));
+OP1(SLJIT_MOV, SLJIT_MEM1(arguments_reg), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_R2, 0);
+OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(arguments_reg), SLJIT_OFFSETOF(jit_arguments, match_data));
mov_opcode = (sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV;
@@ -3059,13 +3283,13 @@ return (0 << 8) | bit;
#ifdef SUPPORT_UNICODE
if (common->utf && c > 65535)
{
- if (bit >= (1 << 10))
+ if (bit >= (1u << 10))
bit >>= 10;
else
return (bit < 256) ? ((2 << 8) | bit) : ((3 << 8) | (bit >> 8));
}
#endif /* SUPPORT_UNICODE */
-return (bit < 256) ? ((0 << 8) | bit) : ((1 << 8) | (bit >> 8));
+return (bit < 256) ? ((0u << 8) | bit) : ((1u << 8) | (bit >> 8));
#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */
}
@@ -3081,7 +3305,7 @@ SLJIT_ASSERT(!force || common->mode != PCRE2_JIT_COMPLETE);
if (common->mode == PCRE2_JIT_COMPLETE)
return;
-if (!force)
+if (!force && !common->allow_empty_partial)
jump = CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
else if (common->mode == PCRE2_JIT_PARTIAL_SOFT)
jump = CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1);
@@ -3143,7 +3367,11 @@ if (common->mode == PCRE2_JIT_COMPLETE)
/* Partial matching mode. */
jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
-add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));
+if (!common->allow_empty_partial)
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));
+else if (common->mode == PCRE2_JIT_PARTIAL_SOFT)
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1));
+
if (common->mode == PCRE2_JIT_PARTIAL_SOFT)
{
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);
@@ -3159,95 +3387,194 @@ else
JUMPHERE(jump);
}
-static void peek_char(compiler_common *common, sljit_u32 max)
+static void process_partial_match(compiler_common *common)
+{
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+
+/* Partial matching mode. */
+if (common->mode == PCRE2_JIT_PARTIAL_SOFT)
+ {
+ jump = CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);
+ JUMPHERE(jump);
+ }
+else if (common->mode == PCRE2_JIT_PARTIAL_HARD)
+ {
+ if (common->partialmatchlabel != NULL)
+ CMPTO(SLJIT_LESS, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0, common->partialmatchlabel);
+ else
+ add_jump(compiler, &common->partialmatch, CMP(SLJIT_LESS, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));
+ }
+}
+
+static void detect_partial_match_to(compiler_common *common, struct sljit_label *label)
+{
+DEFINE_COMPILER;
+
+CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, label);
+process_partial_match(common);
+}
+
+static void peek_char(compiler_common *common, sljit_u32 max, sljit_s32 dst, sljit_sw dstw, jump_list **backtracks)
{
/* Reads the character into TMP1, keeps STR_PTR.
-Does not check STR_END. TMP2 Destroyed. */
+Does not check STR_END. TMP2, dst, RETURN_ADDR Destroyed. */
DEFINE_COMPILER;
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
struct sljit_jump *jump;
-#endif
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */
SLJIT_UNUSED_ARG(max);
+SLJIT_UNUSED_ARG(dst);
+SLJIT_UNUSED_ARG(dstw);
+SLJIT_UNUSED_ARG(backtracks);
-OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+
+#ifdef SUPPORT_UNICODE
+#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
{
if (max < 128) return;
- jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);
+ OP1(SLJIT_MOV, dst, dstw, STR_PTR, 0);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+ add_jump(compiler, common->invalid_utf ? &common->utfreadchar_invalid : &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
+ OP1(SLJIT_MOV, STR_PTR, 0, dst, dstw);
+ if (backtracks && common->invalid_utf)
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));
JUMPHERE(jump);
}
-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */
-
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16
+#elif PCRE2_CODE_UNIT_WIDTH == 16
if (common->utf)
{
if (max < 0xd800) return;
OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
- jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1);
- /* TMP2 contains the high surrogate. */
- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x40);
- OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);
- OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff);
- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
- JUMPHERE(jump);
- }
-#endif
-}
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
-
-static BOOL is_char7_bitset(const sljit_u8 *bitset, BOOL nclass)
-{
-/* Tells whether the character codes below 128 are enough
-to determine a match. */
-const sljit_u8 value = nclass ? 0xff : 0;
-const sljit_u8 *end = bitset + 32;
+ if (common->invalid_utf)
+ {
+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);
+ OP1(SLJIT_MOV, dst, dstw, STR_PTR, 0);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));
+ OP1(SLJIT_MOV, STR_PTR, 0, dst, dstw);
+ if (backtracks && common->invalid_utf)
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));
+ }
+ else
+ {
+ /* TMP2 contains the high surrogate. */
+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800);
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000 - 0xdc00);
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+ }
-bitset += 16;
-do
+ JUMPHERE(jump);
+ }
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+if (common->invalid_utf)
{
- if (*bitset++ != value)
- return FALSE;
+ if (max < 0xd800) return;
+
+ if (backtracks != NULL)
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));
+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800));
+ }
+ else
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x110000);
+ CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);
+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
+ }
}
-while (bitset < end);
-return TRUE;
+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */
+#endif /* SUPPORT_UNICODE */
}
-static void read_char7_type(compiler_common *common, BOOL full_read)
+static void peek_char_back(compiler_common *common, sljit_u32 max, jump_list **backtracks)
{
-/* Reads the precise character type of a character into TMP1, if the character
-is less than 128. Otherwise it returns with zero. Does not check STR_END. The
-full_read argument tells whether characters above max are accepted or not. */
+/* Reads one character back without moving STR_PTR. TMP2 must
+contain the start of the subject buffer. Affects TMP1, TMP2, and RETURN_ADDR. */
DEFINE_COMPILER;
-struct sljit_jump *jump;
-SLJIT_ASSERT(common->utf);
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+struct sljit_jump *jump;
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */
-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+SLJIT_UNUSED_ARG(max);
+SLJIT_UNUSED_ARG(backtracks);
-OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
-if (full_read)
+#ifdef SUPPORT_UNICODE
+#if PCRE2_CODE_UNIT_WIDTH == 8
+if (common->utf)
{
- jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xc0);
- OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0);
- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+ if (max < 128) return;
+
+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);
+ if (common->invalid_utf)
+ {
+ add_jump(compiler, &common->utfpeakcharback_invalid, JUMP(SLJIT_FAST_CALL));
+ if (backtracks != NULL)
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));
+ }
+ else
+ add_jump(compiler, &common->utfpeakcharback, JUMP(SLJIT_FAST_CALL));
JUMPHERE(jump);
}
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+if (common->utf)
+ {
+ if (max < 0xd800) return;
+
+ if (common->invalid_utf)
+ {
+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
+ add_jump(compiler, &common->utfpeakcharback_invalid, JUMP(SLJIT_FAST_CALL));
+ if (backtracks != NULL)
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));
+ }
+ else
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xdc00);
+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xdc00);
+ /* TMP2 contains the low surrogate. */
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x10000);
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 10);
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+ }
+ JUMPHERE(jump);
+ }
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+if (common->invalid_utf)
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));
+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800));
+ }
+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */
+#endif /* SUPPORT_UNICODE */
}
-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */
+#define READ_CHAR_UPDATE_STR_PTR 0x1
+#define READ_CHAR_UTF8_NEWLINE 0x2
+#define READ_CHAR_NEWLINE (READ_CHAR_UPDATE_STR_PTR | READ_CHAR_UTF8_NEWLINE)
+#define READ_CHAR_VALID_UTF 0x4
-static void read_char_range(compiler_common *common, sljit_u32 min, sljit_u32 max, BOOL update_str_ptr)
+static void read_char(compiler_common *common, sljit_u32 min, sljit_u32 max,
+ jump_list **backtracks, sljit_u32 options)
{
/* Reads the precise value of a character into TMP1, if the character is
between min and max (c >= min && c <= max). Otherwise it returns with a value
@@ -3260,24 +3587,41 @@ struct sljit_jump *jump;
struct sljit_jump *jump2;
#endif
-SLJIT_UNUSED_ARG(update_str_ptr);
SLJIT_UNUSED_ARG(min);
SLJIT_UNUSED_ARG(max);
+SLJIT_UNUSED_ARG(backtracks);
+SLJIT_UNUSED_ARG(options);
SLJIT_ASSERT(min <= max);
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
+#ifdef SUPPORT_UNICODE
+#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
{
- if (max < 128 && !update_str_ptr) return;
+ if (max < 128 && !(options & READ_CHAR_UPDATE_STR_PTR)) return;
+
+ if (common->invalid_utf && !(options & READ_CHAR_VALID_UTF))
+ {
+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);
+
+ if (options & READ_CHAR_UTF8_NEWLINE)
+ add_jump(compiler, &common->utfreadnewline_invalid, JUMP(SLJIT_FAST_CALL));
+ else
+ add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));
+
+ if (backtracks != NULL)
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));
+ JUMPHERE(jump);
+ return;
+ }
jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
if (min >= 0x10000)
{
OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xf0);
- if (update_str_ptr)
+ if (options & READ_CHAR_UPDATE_STR_PTR)
OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0x7);
@@ -3289,19 +3633,19 @@ if (common->utf)
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
- if (!update_str_ptr)
+ if (!(options & READ_CHAR_UPDATE_STR_PTR))
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
JUMPHERE(jump2);
- if (update_str_ptr)
+ if (options & READ_CHAR_UPDATE_STR_PTR)
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);
}
else if (min >= 0x800 && max <= 0xffff)
{
OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xe0);
- if (update_str_ptr)
+ if (options & READ_CHAR_UPDATE_STR_PTR)
OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xf);
@@ -3309,17 +3653,19 @@ if (common->utf)
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
- if (!update_str_ptr)
+ if (!(options & READ_CHAR_UPDATE_STR_PTR))
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
JUMPHERE(jump2);
- if (update_str_ptr)
+ if (options & READ_CHAR_UPDATE_STR_PTR)
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);
}
else if (max >= 0x800)
- add_jump(compiler, (max < 0x10000) ? &common->utfreadchar16 : &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
+ {
+ add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
+ }
else if (max < 128)
{
OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
@@ -3328,7 +3674,7 @@ if (common->utf)
else
{
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
- if (!update_str_ptr)
+ if (!(options & READ_CHAR_UPDATE_STR_PTR))
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
else
OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
@@ -3336,54 +3682,151 @@ if (common->utf)
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
- if (update_str_ptr)
+ if (options & READ_CHAR_UPDATE_STR_PTR)
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);
}
JUMPHERE(jump);
}
-#endif
-
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16
+#elif PCRE2_CODE_UNIT_WIDTH == 16
if (common->utf)
{
+ if (max < 0xd800 && !(options & READ_CHAR_UPDATE_STR_PTR)) return;
+
+ if (common->invalid_utf && !(options & READ_CHAR_VALID_UTF))
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);
+
+ if (options & READ_CHAR_UTF8_NEWLINE)
+ add_jump(compiler, &common->utfreadnewline_invalid, JUMP(SLJIT_FAST_CALL));
+ else
+ add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));
+
+ if (backtracks != NULL)
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));
+ JUMPHERE(jump);
+ return;
+ }
+
if (max >= 0x10000)
{
OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
- jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1);
+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800);
/* TMP2 contains the high surrogate. */
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x40);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff);
- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000 - 0xdc00);
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
JUMPHERE(jump);
return;
}
- if (max < 0xd800 && !update_str_ptr) return;
-
/* Skip low surrogate if necessary. */
OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
- jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1);
- if (update_str_ptr)
- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- if (max >= 0xd800)
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x10000);
- JUMPHERE(jump);
+
+ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV) && !HAS_VIRTUAL_REGISTERS)
+ {
+ if (options & READ_CHAR_UPDATE_STR_PTR)
+ OP2(SLJIT_ADD, RETURN_ADDR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x400);
+ if (options & READ_CHAR_UPDATE_STR_PTR)
+ CMOV(SLJIT_LESS, STR_PTR, RETURN_ADDR, 0);
+ if (max >= 0xd800)
+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, 0x10000);
+ }
+ else
+ {
+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400);
+ if (options & READ_CHAR_UPDATE_STR_PTR)
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ if (max >= 0xd800)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x10000);
+ JUMPHERE(jump);
+ }
}
-#endif
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+if (common->invalid_utf)
+ {
+ if (backtracks != NULL)
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));
+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800));
+ }
+ else
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x110000);
+ CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);
+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
+ }
+ }
+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */
+#endif /* SUPPORT_UNICODE */
}
-static SLJIT_INLINE void read_char(compiler_common *common)
-{
-read_char_range(common, 0, READ_CHAR_MAX, TRUE);
-}
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
-static void read_char8_type(compiler_common *common, BOOL update_str_ptr)
+static BOOL is_char7_bitset(const sljit_u8 *bitset, BOOL nclass)
{
-/* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
-DEFINE_COMPILER;
+/* Tells whether the character codes below 128 are enough
+to determine a match. */
+const sljit_u8 value = nclass ? 0xff : 0;
+const sljit_u8 *end = bitset + 32;
+
+bitset += 16;
+do
+ {
+ if (*bitset++ != value)
+ return FALSE;
+ }
+while (bitset < end);
+return TRUE;
+}
+
+static void read_char7_type(compiler_common *common, jump_list **backtracks, BOOL negated)
+{
+/* Reads the precise character type of a character into TMP1, if the character
+is less than 128. Otherwise it returns with zero. Does not check STR_END. The
+full_read argument tells whether characters above max are accepted or not. */
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+
+SLJIT_ASSERT(common->utf);
+
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+/* All values > 127 are zero in ctypes. */
+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+
+if (negated)
+ {
+ jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x80);
+
+ if (common->invalid_utf)
+ {
+ add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
+ }
+ else
+ {
+ OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+ }
+ JUMPHERE(jump);
+ }
+}
+
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */
+
+static void read_char8_type(compiler_common *common, jump_list **backtracks, BOOL negated)
+{
+/* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
+DEFINE_COMPILER;
#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
struct sljit_jump *jump;
#endif
@@ -3391,7 +3834,8 @@ struct sljit_jump *jump;
struct sljit_jump *jump2;
#endif
-SLJIT_UNUSED_ARG(update_str_ptr);
+SLJIT_UNUSED_ARG(backtracks);
+SLJIT_UNUSED_ARG(negated);
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
@@ -3399,18 +3843,38 @@ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
{
- /* This can be an extra read in some situations, but hopefully
- it is needed in most cases. */
+ /* The result of this read may be unused, but saves an "else" part. */
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
- jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xc0);
- if (!update_str_ptr)
+ jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x80);
+
+ if (!negated)
{
+ if (common->invalid_utf)
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
+ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);
+ if (common->invalid_utf)
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe0 - 0xc2));
+
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
- OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
- OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0);
+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);
+ if (common->invalid_utf)
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40));
+
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
+ jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);
+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+ JUMPHERE(jump2);
+ }
+ else if (common->invalid_utf)
+ {
+ add_jump(compiler, &common->utfreadchar_invalid, JUMP(SLJIT_FAST_CALL));
+ OP1(SLJIT_MOV, TMP2, 0, TMP1, 0);
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR));
+
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
@@ -3418,43 +3882,98 @@ if (common->utf)
}
else
add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL));
+
JUMPHERE(jump);
return;
}
#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 32
+if (common->invalid_utf && negated)
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x110000));
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 32 */
+
#if PCRE2_CODE_UNIT_WIDTH != 8
/* The ctypes array contains only 256 values. */
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);
-#endif
+#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
#if PCRE2_CODE_UNIT_WIDTH != 8
JUMPHERE(jump);
-#endif
+#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16
-if (common->utf && update_str_ptr)
+if (common->utf && negated)
{
/* Skip low surrogate if necessary. */
+ if (!common->invalid_utf)
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);
+
+ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV) && !HAS_VIRTUAL_REGISTERS)
+ {
+ OP2(SLJIT_ADD, RETURN_ADDR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x400);
+ CMOV(SLJIT_LESS, STR_PTR, RETURN_ADDR, 0);
+ }
+ else
+ {
+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ JUMPHERE(jump);
+ }
+ return;
+ }
+
OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);
- jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1);
+ jump = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400));
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xdc00);
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400));
+
JUMPHERE(jump);
+ return;
}
#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16 */
}
-static void skip_char_back(compiler_common *common)
+static void move_back(compiler_common *common, jump_list **backtracks, BOOL must_be_valid)
{
-/* Goes one character back. Affects STR_PTR and TMP1. Does not check begin. */
+/* Goes one character back. Affects STR_PTR and TMP1. If must_be_valid is TRUE,
+TMP2 is not used. Otherwise TMP2 must contain the start of the subject buffer,
+and it is destroyed. Does not modify STR_PTR for invalid character sequences. */
DEFINE_COMPILER;
+
+SLJIT_UNUSED_ARG(backtracks);
+SLJIT_UNUSED_ARG(must_be_valid);
+
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+struct sljit_jump *jump;
+#endif
+
+#ifdef SUPPORT_UNICODE
#if PCRE2_CODE_UNIT_WIDTH == 8
struct sljit_label *label;
if (common->utf)
{
+ if (!must_be_valid && common->invalid_utf)
+ {
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));
+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x80);
+ add_jump(compiler, &common->utfmoveback_invalid, JUMP(SLJIT_FAST_CALL));
+ if (backtracks != NULL)
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0));
+ JUMPHERE(jump);
+ return;
+ }
+
label = LABEL();
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
@@ -3467,16 +3986,45 @@ if (common->utf)
{
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+ if (!must_be_valid && common->invalid_utf)
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xe000 - 0xd800);
+ add_jump(compiler, &common->utfmoveback_invalid, JUMP(SLJIT_FAST_CALL));
+ if (backtracks != NULL)
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0));
+ JUMPHERE(jump);
+ return;
+ }
+
/* Skip low surrogate if necessary. */
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00);
OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
- OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
return;
}
-#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16] */
-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+if (common->invalid_utf && !must_be_valid)
+ {
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));
+ if (backtracks != NULL)
+ {
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));
+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ return;
+ }
+
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x110000);
+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_LESS);
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+ return;
+ }
+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */
+#endif /* SUPPORT_UNICODE */
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
}
@@ -3519,13 +4067,12 @@ else
static void do_utfreadchar(compiler_common *common)
{
/* Fast decoding a UTF-8 character. TMP1 contains the first byte
-of the character (>= 0xc0). Return char value in TMP1, length in TMP2. */
+of the character (>= 0xc0). Return char value in TMP1. */
DEFINE_COMPILER;
struct sljit_jump *jump;
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
-OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
@@ -3534,13 +4081,12 @@ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
jump = JUMP(SLJIT_NOT_ZERO);
/* Two byte sequence. */
+OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3000);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(2));
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
JUMPHERE(jump);
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
-OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x800);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
@@ -3548,55 +4094,18 @@ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000);
jump = JUMP(SLJIT_NOT_ZERO);
/* Three byte sequence. */
+OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0000);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
-OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(3));
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
/* Four byte sequence. */
JUMPHERE(jump);
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
-OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);
-OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
+OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xf0000);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));
-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
-OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(4));
-sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
-}
-
-static void do_utfreadchar16(compiler_common *common)
-{
-/* Fast decoding a UTF-8 character. TMP1 contains the first byte
-of the character (>= 0xc0). Return value in TMP1. */
-DEFINE_COMPILER;
-struct sljit_jump *jump;
-
-sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
-OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
-OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
-OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
-
-/* Searching for the first zero. */
-OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
-jump = JUMP(SLJIT_NOT_ZERO);
-/* Two byte sequence. */
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
-
-JUMPHERE(jump);
-OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400);
-OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO);
-/* This code runs only in 8 bit mode. No need to shift the value. */
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
-OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
-OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x800);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
-/* Three byte sequence. */
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}
@@ -3636,129 +4145,821 @@ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}
-#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
-
-/* UCD_BLOCK_SIZE must be 128 (see the assert below). */
-#define UCD_BLOCK_MASK 127
-#define UCD_BLOCK_SHIFT 7
-
-static void do_getucd(compiler_common *common)
+static void do_utfreadchar_invalid(compiler_common *common)
{
-/* Search the UCD record for the character comes in TMP1.
-Returns chartype in TMP1 and UCD offset in TMP2. */
+/* Slow decoding a UTF-8 character. TMP1 contains the first byte
+of the character (>= 0xc0). Return char value in TMP1. STR_PTR is
+undefined for invalid characters. */
DEFINE_COMPILER;
-#if PCRE2_CODE_UNIT_WIDTH == 32
+sljit_s32 i;
+sljit_s32 has_cmov = sljit_has_cpu_feature(SLJIT_HAS_CMOV);
struct sljit_jump *jump;
-#endif
+struct sljit_jump *buffer_end_close;
+struct sljit_label *three_byte_entry;
+struct sljit_label *exit_invalid_label;
+struct sljit_jump *exit_invalid[11];
-#if defined SLJIT_DEBUG && SLJIT_DEBUG
-/* dummy_ucd_record */
-const ucd_record *record = GET_UCD(INVALID_UTF_CHAR);
-SLJIT_ASSERT(record->script == ucp_Common && record->chartype == ucp_Cn && record->gbprop == ucp_gbOther);
-SLJIT_ASSERT(record->caseset == 0 && record->other_case == 0);
-#endif
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
-SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8);
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc2);
-sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+/* Usually more than 3 characters remained in the subject buffer. */
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));
-#if PCRE2_CODE_UNIT_WIDTH == 32
-if (!common->utf)
- {
- jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1);
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
- JUMPHERE(jump);
- }
-#endif
+/* Not a valid start of a multi-byte sequence, no more bytes read. */
+exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xf5 - 0xc2);
-OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
-OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
-OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
-OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));
-OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
-OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
-sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
-}
+buffer_end_close = CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0);
-#endif /* SUPPORT_UNICODE */
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
+/* If TMP2 is in 0x80-0xbf range, TMP1 is also increased by (0x2 << 6). */
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);
+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);
-static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common)
-{
-DEFINE_COMPILER;
-struct sljit_label *mainloop;
-struct sljit_label *newlinelabel = NULL;
-struct sljit_jump *start;
-struct sljit_jump *end = NULL;
-struct sljit_jump *end2 = NULL;
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-struct sljit_jump *singlechar;
-#endif
-jump_list *newline = NULL;
-sljit_u32 overall_options = common->re->overall_options;
-BOOL hascrorlf = (common->re->flags & PCRE2_HASCRORLF) != 0;
-BOOL newlinecheck = FALSE;
-BOOL readuchar = FALSE;
+OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+jump = JUMP(SLJIT_NOT_ZERO);
-if (!(hascrorlf || (overall_options & PCRE2_FIRSTLINE) != 0)
- && (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF || common->newline > 255))
- newlinecheck = TRUE;
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
-SLJIT_ASSERT(common->abort_label == NULL);
+JUMPHERE(jump);
-if ((overall_options & PCRE2_FIRSTLINE) != 0)
+/* Three-byte sequence. */
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+if (has_cmov)
{
- /* Search for the end of the first line. */
- SLJIT_ASSERT(common->match_end_ptr != 0);
- OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x40);
+ CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, 0x20000);
+ exit_invalid[2] = NULL;
+ }
+else
+ exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);
- if (common->nltype == NLTYPE_FIXED && common->newline > 255)
- {
- mainloop = LABEL();
- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
- OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
- CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop);
- CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop);
- JUMPHERE(end);
- OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- }
- else
- {
- end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
- mainloop = LABEL();
- /* Continual stores does not cause data dependency. */
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0);
- read_char_range(common, common->nlmin, common->nlmax, TRUE);
- check_newlinechar(common, common->nltype, &newline, TRUE);
- CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, mainloop);
- JUMPHERE(end);
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0);
- set_jumps(newline, LABEL());
- }
+OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000);
+jump = JUMP(SLJIT_NOT_ZERO);
- OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
+three_byte_entry = LABEL();
+
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2d800);
+if (has_cmov)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR - 0xd800);
+ exit_invalid[3] = NULL;
}
-else if ((overall_options & PCRE2_USE_OFFSET_LIMIT) != 0)
+else
+ exit_invalid[3] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+if (has_cmov)
{
- /* Check whether offset limit is set and valid. */
- SLJIT_ASSERT(common->match_end_ptr != 0);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
+ exit_invalid[4] = NULL;
+ }
+else
+ exit_invalid[4] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(jump);
+
+/* Four-byte sequence. */
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+if (has_cmov)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x40);
+ CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, 0);
+ exit_invalid[5] = NULL;
+ }
+else
+ exit_invalid[5] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);
+
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc10000);
+if (has_cmov)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x100000);
+ CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR - 0x10000);
+ exit_invalid[6] = NULL;
+ }
+else
+ exit_invalid[6] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000);
+
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(buffer_end_close);
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+exit_invalid[7] = CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0);
+
+/* Two-byte sequence. */
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
+/* If TMP2 is in 0x80-0xbf range, TMP1 is also increased by (0x2 << 6). */
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);
+exit_invalid[8] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);
+
+OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+jump = JUMP(SLJIT_NOT_ZERO);
+
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+/* Three-byte sequence. */
+JUMPHERE(jump);
+exit_invalid[9] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+if (has_cmov)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x40);
+ CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
+ exit_invalid[10] = NULL;
+ }
+else
+ exit_invalid[10] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);
+
+/* One will be substracted from STR_PTR later. */
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+
+/* Four byte sequences are not possible. */
+CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x30000, three_byte_entry);
+
+exit_invalid_label = LABEL();
+for (i = 0; i < 11; i++)
+ sljit_set_label(exit_invalid[i], exit_invalid_label);
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+static void do_utfreadnewline_invalid(compiler_common *common)
+{
+/* Slow decoding a UTF-8 character, specialized for newlines.
+TMP1 contains the first byte of the character (>= 0xc0). Return
+char value in TMP1. */
+DEFINE_COMPILER;
+struct sljit_label *loop;
+struct sljit_label *skip_start;
+struct sljit_label *three_byte_exit;
+struct sljit_jump *jump[5];
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+if (common->nltype != NLTYPE_ANY)
+ {
+ SLJIT_ASSERT(common->nltype != NLTYPE_FIXED || common->newline < 128);
+
+ /* All newlines are ascii, just skip intermediate octets. */
+ jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+ loop = LABEL();
+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc0);
+ CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80, loop);
+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+ JUMPHERE(jump[0]);
+
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
+ sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+ return;
+ }
+
+jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+jump[1] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xc2);
+jump[2] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xe2);
+
+skip_start = LABEL();
+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc0);
+jump[3] = CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80);
+
+/* Skip intermediate octets. */
+loop = LABEL();
+jump[4] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc0);
+CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80, loop);
+
+JUMPHERE(jump[3]);
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+three_byte_exit = LABEL();
+JUMPHERE(jump[0]);
+JUMPHERE(jump[4]);
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+/* Two byte long newline: 0x85. */
+JUMPHERE(jump[1]);
+CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0x85, skip_start);
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x85);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+/* Three byte long newlines: 0x2028 and 0x2029. */
+JUMPHERE(jump[2]);
+CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80, skip_start);
+CMPTO(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0, three_byte_exit);
+
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+OP2(SLJIT_SUB, TMP1, 0, TMP2, 0, SLJIT_IMM, 0x80);
+CMPTO(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x40, skip_start);
+
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0x2000);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+static void do_utfmoveback_invalid(compiler_common *common)
+{
+/* Goes one character back. */
+DEFINE_COMPILER;
+sljit_s32 i;
+struct sljit_jump *jump;
+struct sljit_jump *buffer_start_close;
+struct sljit_label *exit_ok_label;
+struct sljit_label *exit_invalid_label;
+struct sljit_jump *exit_invalid[7];
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));
+exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xc0);
+
+/* Two-byte sequence. */
+buffer_start_close = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);
+
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
+
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
+jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x20);
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+/* Three-byte sequence. */
+JUMPHERE(jump);
+exit_invalid[1] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, -0x40);
+
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0);
+jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x10);
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+/* Four-byte sequence. */
+JUMPHERE(jump);
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0 - 0x80);
+exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x40);
+
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xf0);
+exit_invalid[3] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x05);
+
+exit_ok_label = LABEL();
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+/* Two-byte sequence. */
+JUMPHERE(buffer_start_close);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+
+exit_invalid[4] = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);
+
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
+CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x20, exit_ok_label);
+
+/* Three-byte sequence. */
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+exit_invalid[5] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, -0x40);
+exit_invalid[6] = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);
+
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0);
+CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10, exit_ok_label);
+
+/* Four-byte sequences are not possible. */
+
+exit_invalid_label = LABEL();
+sljit_set_label(exit_invalid[5], exit_invalid_label);
+sljit_set_label(exit_invalid[6], exit_invalid_label);
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3));
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(exit_invalid[4]);
+/* -2 + 4 = 2 */
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+
+exit_invalid_label = LABEL();
+for (i = 0; i < 4; i++)
+ sljit_set_label(exit_invalid[i], exit_invalid_label);
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(4));
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+static void do_utfpeakcharback(compiler_common *common)
+{
+/* Peak a character back. Does not modify STR_PTR. */
+DEFINE_COMPILER;
+struct sljit_jump *jump[2];
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
+jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x20);
+
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0);
+jump[1] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10);
+
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-4));
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0 - 0x80);
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf0);
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+
+JUMPHERE(jump[1]);
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+
+JUMPHERE(jump[0]);
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+static void do_utfpeakcharback_invalid(compiler_common *common)
+{
+/* Peak a character back. Does not modify STR_PTR. */
+DEFINE_COMPILER;
+sljit_s32 i;
+sljit_s32 has_cmov = sljit_has_cpu_feature(SLJIT_HAS_CMOV);
+struct sljit_jump *jump[2];
+struct sljit_label *two_byte_entry;
+struct sljit_label *three_byte_entry;
+struct sljit_label *exit_invalid_label;
+struct sljit_jump *exit_invalid[8];
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(3));
+exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xc0);
+jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);
+
+/* Two-byte sequence. */
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);
+jump[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x1e);
+
+two_byte_entry = LABEL();
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
+/* If TMP1 is in 0x80-0xbf range, TMP1 is also increased by (0x2 << 6). */
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(jump[1]);
+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2 - 0x80);
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);
+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+
+/* Three-byte sequence. */
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xe0);
+jump[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x10);
+
+three_byte_entry = LABEL();
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+if (has_cmov)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, -0xd800);
+ exit_invalid[2] = NULL;
+ }
+else
+ exit_invalid[2] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);
+
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+if (has_cmov)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
+ exit_invalid[3] = NULL;
+ }
+else
+ exit_invalid[3] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800);
+
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(jump[1]);
+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xe0 - 0x80);
+exit_invalid[4] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+
+/* Four-byte sequence. */
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-4));
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf0);
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 18);
+/* ADD is used instead of OR because of the SUB 0x10000 above. */
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+
+if (has_cmov)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x100000);
+ CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR - 0x10000);
+ exit_invalid[5] = NULL;
+ }
+else
+ exit_invalid[5] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000);
+
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(jump[0]);
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
+jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);
+
+/* Two-byte sequence. */
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);
+CMPTO(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x1e, two_byte_entry);
+
+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2 - 0x80);
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);
+exit_invalid[6] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+
+/* Three-byte sequence. */
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-3));
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xe0);
+CMPTO(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x10, three_byte_entry);
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(jump[0]);
+exit_invalid[7] = CMP(SLJIT_GREATER, TMP2, 0, STR_PTR, 0);
+
+/* Two-byte sequence. */
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2);
+CMPTO(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x1e, two_byte_entry);
+
+exit_invalid_label = LABEL();
+for (i = 0; i < 8; i++)
+ sljit_set_label(exit_invalid[i], exit_invalid_label);
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, offset_limit));
- OP1(SLJIT_MOV, TMP2, 0, STR_END, 0);
- end = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw) PCRE2_UNSET);
- OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
#if PCRE2_CODE_UNIT_WIDTH == 16
- OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
-#elif PCRE2_CODE_UNIT_WIDTH == 32
- OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);
+
+static void do_utfreadchar_invalid(compiler_common *common)
+{
+/* Slow decoding a UTF-16 character. TMP1 contains the first half
+of the character (>= 0xd800). Return char value in TMP1. STR_PTR is
+undefined for invalid characters. */
+DEFINE_COMPILER;
+struct sljit_jump *exit_invalid[3];
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+/* TMP2 contains the high surrogate. */
+exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00);
+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xdc00);
+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x10000);
+exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x400);
+
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(exit_invalid[0]);
+JUMPHERE(exit_invalid[1]);
+JUMPHERE(exit_invalid[2]);
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+static void do_utfreadnewline_invalid(compiler_common *common)
+{
+/* Slow decoding a UTF-16 character, specialized for newlines.
+TMP1 contains the first half of the character (>= 0xd800). Return
+char value in TMP1. */
+
+DEFINE_COMPILER;
+struct sljit_jump *exit_invalid[2];
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+/* TMP2 contains the high surrogate. */
+exit_invalid[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00);
+
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xdc00);
+OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x400);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS);
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x10000);
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(exit_invalid[0]);
+JUMPHERE(exit_invalid[1]);
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+static void do_utfmoveback_invalid(compiler_common *common)
+{
+/* Goes one character back. */
+DEFINE_COMPILER;
+struct sljit_jump *exit_invalid[3];
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+exit_invalid[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x400);
+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);
+
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x400);
+
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(exit_invalid[0]);
+JUMPHERE(exit_invalid[1]);
+JUMPHERE(exit_invalid[2]);
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+static void do_utfpeakcharback_invalid(compiler_common *common)
+{
+/* Peak a character back. Does not modify STR_PTR. */
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+struct sljit_jump *exit_invalid[3];
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xe000);
+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
+exit_invalid[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xdc00);
+exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, STR_PTR, 0);
+
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000 - 0xdc00);
+OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);
+exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x400);
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10);
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+
+JUMPHERE(jump);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(exit_invalid[0]);
+JUMPHERE(exit_invalid[1]);
+JUMPHERE(exit_invalid[2]);
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+#endif /* PCRE2_CODE_UNIT_WIDTH == 16 */
+
+/* UCD_BLOCK_SIZE must be 128 (see the assert below). */
+#define UCD_BLOCK_MASK 127
+#define UCD_BLOCK_SHIFT 7
+
+static void do_getucd(compiler_common *common)
+{
+/* Search the UCD record for the character comes in TMP1.
+Returns chartype in TMP1 and UCD offset in TMP2. */
+DEFINE_COMPILER;
+#if PCRE2_CODE_UNIT_WIDTH == 32
+struct sljit_jump *jump;
+#endif
+
+#if defined SLJIT_DEBUG && SLJIT_DEBUG
+/* dummy_ucd_record */
+const ucd_record *record = GET_UCD(UNASSIGNED_UTF_CHAR);
+SLJIT_ASSERT(record->script == ucp_Unknown && record->chartype == ucp_Cn && record->gbprop == ucp_gbOther);
+SLJIT_ASSERT(record->caseset == 0 && record->other_case == 0);
+#endif
+
+SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 12);
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+#if PCRE2_CODE_UNIT_WIDTH == 32
+if (!common->utf)
+ {
+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, UNASSIGNED_UTF_CHAR);
+ JUMPHERE(jump);
+ }
#endif
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
+
+OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
+OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
+OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));
+OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+static void do_getucdtype(compiler_common *common)
+{
+/* Search the UCD record for the character comes in TMP1.
+Returns chartype in TMP1 and UCD offset in TMP2. */
+DEFINE_COMPILER;
+#if PCRE2_CODE_UNIT_WIDTH == 32
+struct sljit_jump *jump;
+#endif
+
+#if defined SLJIT_DEBUG && SLJIT_DEBUG
+/* dummy_ucd_record */
+const ucd_record *record = GET_UCD(UNASSIGNED_UTF_CHAR);
+SLJIT_ASSERT(record->script == ucp_Unknown && record->chartype == ucp_Cn && record->gbprop == ucp_gbOther);
+SLJIT_ASSERT(record->caseset == 0 && record->other_case == 0);
+#endif
+
+SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 12);
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+#if PCRE2_CODE_UNIT_WIDTH == 32
+if (!common->utf)
+ {
+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, UNASSIGNED_UTF_CHAR);
+ JUMPHERE(jump);
+ }
+#endif
+
+OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
+OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
+OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));
+OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
+
+/* TMP2 is multiplied by 12. Same as (TMP2 << 2) + ((TMP2 << 2) << 1). */
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 1);
+
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+#endif /* SUPPORT_UNICODE */
+
+static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common)
+{
+DEFINE_COMPILER;
+struct sljit_label *mainloop;
+struct sljit_label *newlinelabel = NULL;
+struct sljit_jump *start;
+struct sljit_jump *end = NULL;
+struct sljit_jump *end2 = NULL;
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+struct sljit_label *loop;
+struct sljit_jump *jump;
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */
+jump_list *newline = NULL;
+sljit_u32 overall_options = common->re->overall_options;
+BOOL hascrorlf = (common->re->flags & PCRE2_HASCRORLF) != 0;
+BOOL newlinecheck = FALSE;
+BOOL readuchar = FALSE;
+
+if (!(hascrorlf || (overall_options & PCRE2_FIRSTLINE) != 0)
+ && (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF || common->newline > 255))
+ newlinecheck = TRUE;
+
+SLJIT_ASSERT(common->abort_label == NULL);
+
+if ((overall_options & PCRE2_FIRSTLINE) != 0)
+ {
+ /* Search for the end of the first line. */
+ SLJIT_ASSERT(common->match_end_ptr != 0);
+ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
+
+ if (common->nltype == NLTYPE_FIXED && common->newline > 255)
+ {
+ mainloop = LABEL();
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop);
+ CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop);
+ JUMPHERE(end);
+ OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ }
+ else
+ {
+ end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+ mainloop = LABEL();
+ /* Continual stores does not cause data dependency. */
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0);
+ read_char(common, common->nlmin, common->nlmax, NULL, READ_CHAR_NEWLINE);
+ check_newlinechar(common, common->nltype, &newline, TRUE);
+ CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, mainloop);
+ JUMPHERE(end);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0);
+ set_jumps(newline, LABEL());
+ }
+
+ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
+ }
+else if ((overall_options & PCRE2_USE_OFFSET_LIMIT) != 0)
+ {
+ /* Check whether offset limit is set and valid. */
+ SLJIT_ASSERT(common->match_end_ptr != 0);
+
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, offset_limit));
+ }
+ else
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, offset_limit));
+
+ OP1(SLJIT_MOV, TMP2, 0, STR_END, 0);
+ end = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw) PCRE2_UNSET);
+ if (HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+ else
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
+
+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
+#endif /* PCRE2_CODE_UNIT_WIDTH == [16|32] */
+ if (HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
+
OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
end2 = CMP(SLJIT_LESS_EQUAL, TMP2, 0, STR_END, 0);
OP1(SLJIT_MOV, TMP2, 0, STR_END, 0);
@@ -3781,7 +4982,7 @@ if (newlinecheck)
OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
-#endif
+#endif /* PCRE2_CODE_UNIT_WIDTH == [16|32] */
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
end2 = JUMP(SLJIT_JUMP);
}
@@ -3789,9 +4990,9 @@ if (newlinecheck)
mainloop = LABEL();
/* Increasing the STR_PTR here requires one less jump in the most common case. */
-#ifdef SUPPORT_UNICODE
-if (common->utf) readuchar = TRUE;
-#endif
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+if (common->utf && !common->invalid_utf) readuchar = TRUE;
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */
if (newlinecheck) readuchar = TRUE;
if (readuchar)
@@ -3803,23 +5004,55 @@ if (newlinecheck)
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
#if PCRE2_CODE_UNIT_WIDTH == 8
-if (common->utf)
+if (common->invalid_utf)
{
- singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
+ /* Skip continuation code units. */
+ loop = LABEL();
+ jump = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x80);
+ CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x40, loop);
+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ JUMPHERE(jump);
+ }
+else if (common->utf)
+ {
+ jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
- JUMPHERE(singlechar);
+ JUMPHERE(jump);
}
#elif PCRE2_CODE_UNIT_WIDTH == 16
-if (common->utf)
+if (common->invalid_utf)
{
- singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
- OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
- OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
- OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
- JUMPHERE(singlechar);
+ /* Skip continuation code units. */
+ loop = LABEL();
+ jump = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xdc00);
+ CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x400, loop);
+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ JUMPHERE(jump);
+ }
+else if (common->utf)
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+
+ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV))
+ {
+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400);
+ CMOV(SLJIT_LESS, STR_PTR, TMP2, 0);
+ }
+ else
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400);
+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_LESS);
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+ }
}
#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16] */
#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */
@@ -4265,720 +5498,77 @@ while (TRUE)
cc = cc_save;
}
- repeat = 1;
- if (last)
- return consumed;
- }
-}
-
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-static void jumpto_if_not_utf_char_start(struct sljit_compiler *compiler, sljit_s32 reg, struct sljit_label *label)
-{
-#if PCRE2_CODE_UNIT_WIDTH == 8
-OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xc0);
-CMPTO(SLJIT_EQUAL, reg, 0, SLJIT_IMM, 0x80, label);
-#elif PCRE2_CODE_UNIT_WIDTH == 16
-OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xfc00);
-CMPTO(SLJIT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00, label);
-#else
-#error "Unknown code width"
-#endif
-}
-#endif
-
-#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND)
-
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-static struct sljit_jump *jump_if_utf_char_start(struct sljit_compiler *compiler, sljit_s32 reg)
-{
-#if PCRE2_CODE_UNIT_WIDTH == 8
-OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xc0);
-return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0x80);
-#elif PCRE2_CODE_UNIT_WIDTH == 16
-OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xfc00);
-return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00);
-#else
-#error "Unknown code width"
-#endif
-}
-#endif
-
-static sljit_s32 character_to_int32(PCRE2_UCHAR chr)
-{
-sljit_s32 value = (sljit_s32)chr;
-#if PCRE2_CODE_UNIT_WIDTH == 8
-#define SSE2_COMPARE_TYPE_INDEX 0
-return (value << 24) | (value << 16) | (value << 8) | value;
-#elif PCRE2_CODE_UNIT_WIDTH == 16
-#define SSE2_COMPARE_TYPE_INDEX 1
-return (value << 16) | value;
-#elif PCRE2_CODE_UNIT_WIDTH == 32
-#define SSE2_COMPARE_TYPE_INDEX 2
-return value;
-#else
-#error "Unsupported unit width"
-#endif
-}
-
-static void load_from_mem_sse2(struct sljit_compiler *compiler, sljit_s32 dst_xmm_reg, sljit_s32 src_general_reg)
-{
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-sljit_u8 instruction[5];
-#else
-sljit_u8 instruction[4];
-#endif
-
-SLJIT_ASSERT(dst_xmm_reg < 8);
-
-/* MOVDQA xmm1, xmm2/m128 */
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-if (src_general_reg < 8)
- {
- instruction[0] = 0x66;
- instruction[1] = 0x0f;
- instruction[2] = 0x6f;
- instruction[3] = (dst_xmm_reg << 3) | src_general_reg;
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-else
- {
- instruction[0] = 0x66;
- instruction[1] = 0x41;
- instruction[2] = 0x0f;
- instruction[3] = 0x6f;
- instruction[4] = (dst_xmm_reg << 3) | (src_general_reg & 0x7);
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-#else
-instruction[0] = 0x66;
-instruction[1] = 0x0f;
-instruction[2] = 0x6f;
-instruction[3] = (dst_xmm_reg << 3) | src_general_reg;
-sljit_emit_op_custom(compiler, instruction, 4);
-#endif
-}
-
-static void fast_forward_char_pair_sse2_compare(struct sljit_compiler *compiler, PCRE2_UCHAR char1, PCRE2_UCHAR char2,
- sljit_u32 bit, sljit_s32 dst_ind, sljit_s32 cmp1_ind, sljit_s32 cmp2_ind, sljit_s32 tmp_ind)
-{
-sljit_u8 instruction[4];
-instruction[0] = 0x66;
-instruction[1] = 0x0f;
-
-if (char1 == char2 || bit != 0)
- {
- if (bit != 0)
- {
- /* POR xmm1, xmm2/m128 */
- /* instruction[0] = 0x66; */
- /* instruction[1] = 0x0f; */
- instruction[2] = 0xeb;
- instruction[3] = 0xc0 | (dst_ind << 3) | cmp2_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-
- /* PCMPEQB/W/D xmm1, xmm2/m128 */
- /* instruction[0] = 0x66; */
- /* instruction[1] = 0x0f; */
- instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
- instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-else
- {
- /* MOVDQA xmm1, xmm2/m128 */
- /* instruction[0] = 0x66; */
- /* instruction[1] = 0x0f; */
- instruction[2] = 0x6f;
- instruction[3] = 0xc0 | (tmp_ind << 3) | dst_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
-
- /* PCMPEQB/W/D xmm1, xmm2/m128 */
- /* instruction[0] = 0x66; */
- /* instruction[1] = 0x0f; */
- instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
- instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
-
- instruction[3] = 0xc0 | (tmp_ind << 3) | cmp2_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
-
- /* POR xmm1, xmm2/m128 */
- /* instruction[0] = 0x66; */
- /* instruction[1] = 0x0f; */
- instruction[2] = 0xeb;
- instruction[3] = 0xc0 | (dst_ind << 3) | tmp_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-}
-
-static void fast_forward_first_char2_sse2(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)
-{
-DEFINE_COMPILER;
-struct sljit_label *start;
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-struct sljit_label *restart;
-#endif
-struct sljit_jump *quit;
-struct sljit_jump *partial_quit[2];
-sljit_u8 instruction[8];
-sljit_s32 tmp1_ind = sljit_get_register_index(TMP1);
-sljit_s32 str_ptr_ind = sljit_get_register_index(STR_PTR);
-sljit_s32 data_ind = 0;
-sljit_s32 tmp_ind = 1;
-sljit_s32 cmp1_ind = 2;
-sljit_s32 cmp2_ind = 3;
-sljit_u32 bit = 0;
-
-SLJIT_UNUSED_ARG(offset);
-
-if (char1 != char2)
- {
- bit = char1 ^ char2;
- if (!is_powerof2(bit))
- bit = 0;
- }
-
-partial_quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
-if (common->mode == PCRE2_JIT_COMPLETE)
- add_jump(compiler, &common->failed_match, partial_quit[0]);
-
-/* First part (unaligned start) */
-
-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit));
-
-SLJIT_ASSERT(tmp1_ind < 8);
-
-/* MOVD xmm, r/m32 */
-instruction[0] = 0x66;
-instruction[1] = 0x0f;
-instruction[2] = 0x6e;
-instruction[3] = 0xc0 | (cmp1_ind << 3) | tmp1_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-if (char1 != char2)
- {
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));
-
- /* MOVD xmm, r/m32 */
- instruction[3] = 0xc0 | (cmp2_ind << 3) | tmp1_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-
-OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
-
-/* PSHUFD xmm1, xmm2/m128, imm8 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x70;
-instruction[3] = 0xc0 | (cmp1_ind << 3) | 2;
-instruction[4] = 0;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-if (char1 != char2)
- {
- /* PSHUFD xmm1, xmm2/m128, imm8 */
- instruction[3] = 0xc0 | (cmp2_ind << 3) | 3;
- sljit_emit_op_custom(compiler, instruction, 5);
- }
-
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-restart = LABEL();
-#endif
-OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);
-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);
-
-load_from_mem_sse2(compiler, data_ind, str_ptr_ind);
-fast_forward_char_pair_sse2_compare(compiler, char1, char2, bit, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
-
-/* PMOVMSKB reg, xmm */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0xd7;
-instruction[3] = 0xc0 | (tmp1_ind << 3) | 0;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
-OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);
-
-/* BSF r32, r/m32 */
-instruction[0] = 0x0f;
-instruction[1] = 0xbc;
-instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
-sljit_emit_op_custom(compiler, instruction, 3);
-sljit_set_current_flags(compiler, SLJIT_SET_Z);
-
-quit = JUMP(SLJIT_NOT_ZERO);
-
-OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
-
-start = LABEL();
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
-
-partial_quit[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
-if (common->mode == PCRE2_JIT_COMPLETE)
- add_jump(compiler, &common->failed_match, partial_quit[1]);
-
-/* Second part (aligned) */
-
-load_from_mem_sse2(compiler, 0, str_ptr_ind);
-fast_forward_char_pair_sse2_compare(compiler, char1, char2, bit, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
-
-/* PMOVMSKB reg, xmm */
-instruction[0] = 0x66;
-instruction[1] = 0x0f;
-instruction[2] = 0xd7;
-instruction[3] = 0xc0 | (tmp1_ind << 3) | 0;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* BSF r32, r/m32 */
-instruction[0] = 0x0f;
-instruction[1] = 0xbc;
-instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
-sljit_emit_op_custom(compiler, instruction, 3);
-sljit_set_current_flags(compiler, SLJIT_SET_Z);
-
-JUMPTO(SLJIT_ZERO, start);
-
-JUMPHERE(quit);
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
-
-if (common->mode != PCRE2_JIT_COMPLETE)
- {
- JUMPHERE(partial_quit[0]);
- JUMPHERE(partial_quit[1]);
- OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
- CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);
- }
-else
- add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
-
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-if (common->utf && offset > 0)
- {
- SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);
-
- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));
-
- quit = jump_if_utf_char_start(compiler, TMP1);
-
- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
- OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
- JUMPTO(SLJIT_JUMP, restart);
-
- JUMPHERE(quit);
- }
-#endif
-}
-
-#ifndef _WIN64
-
-static SLJIT_INLINE sljit_u32 max_fast_forward_char_pair_sse2_offset(void)
-{
-#if PCRE2_CODE_UNIT_WIDTH == 8
-return 15;
-#elif PCRE2_CODE_UNIT_WIDTH == 16
-return 7;
-#elif PCRE2_CODE_UNIT_WIDTH == 32
-return 3;
-#else
-#error "Unsupported unit width"
-#endif
-}
-
-static void fast_forward_char_pair_sse2(compiler_common *common, sljit_s32 offs1,
- PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)
-{
-DEFINE_COMPILER;
-sljit_u32 bit1 = 0;
-sljit_u32 bit2 = 0;
-sljit_u32 diff = IN_UCHARS(offs1 - offs2);
-sljit_s32 tmp1_ind = sljit_get_register_index(TMP1);
-sljit_s32 tmp2_ind = sljit_get_register_index(TMP2);
-sljit_s32 str_ptr_ind = sljit_get_register_index(STR_PTR);
-sljit_s32 data1_ind = 0;
-sljit_s32 data2_ind = 1;
-sljit_s32 tmp_ind = 2;
-sljit_s32 cmp1a_ind = 3;
-sljit_s32 cmp1b_ind = 4;
-sljit_s32 cmp2a_ind = 5;
-sljit_s32 cmp2b_ind = 6;
-struct sljit_label *start;
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-struct sljit_label *restart;
-#endif
-struct sljit_jump *jump[2];
-
-sljit_u8 instruction[8];
-
-SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);
-SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_sse2_offset()));
-SLJIT_ASSERT(tmp1_ind < 8 && tmp2_ind == 1);
-
-/* Initialize. */
-if (common->match_end_ptr != 0)
- {
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
- OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));
-
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);
- CMOV(SLJIT_LESS, STR_END, TMP1, 0);
- }
-
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));
-add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
-
-/* MOVD xmm, r/m32 */
-instruction[0] = 0x66;
-instruction[1] = 0x0f;
-instruction[2] = 0x6e;
-
-if (char1a == char1b)
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a));
-else
- {
- bit1 = char1a ^ char1b;
- if (is_powerof2(bit1))
- {
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a | bit1));
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit1));
- }
- else
- {
- bit1 = 0;
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a));
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char1b));
- }
- }
-
-instruction[3] = 0xc0 | (cmp1a_ind << 3) | tmp1_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-if (char1a != char1b)
- {
- instruction[3] = 0xc0 | (cmp1b_ind << 3) | tmp2_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-
-if (char2a == char2b)
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));
-else
- {
- bit2 = char2a ^ char2b;
- if (is_powerof2(bit2))
- {
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a | bit2));
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit2));
- }
- else
- {
- bit2 = 0;
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char2b));
- }
- }
-
-instruction[3] = 0xc0 | (cmp2a_ind << 3) | tmp1_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-if (char2a != char2b)
- {
- instruction[3] = 0xc0 | (cmp2b_ind << 3) | tmp2_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-
-/* PSHUFD xmm1, xmm2/m128, imm8 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x70;
-instruction[4] = 0;
-
-instruction[3] = 0xc0 | (cmp1a_ind << 3) | cmp1a_ind;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-if (char1a != char1b)
- {
- instruction[3] = 0xc0 | (cmp1b_ind << 3) | cmp1b_ind;
- sljit_emit_op_custom(compiler, instruction, 5);
- }
-
-instruction[3] = 0xc0 | (cmp2a_ind << 3) | cmp2a_ind;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-if (char2a != char2b)
- {
- instruction[3] = 0xc0 | (cmp2b_ind << 3) | cmp2b_ind;
- sljit_emit_op_custom(compiler, instruction, 5);
- }
-
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-restart = LABEL();
-#endif
-
-OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1 - offs2));
-OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
-OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);
-OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, ~0xf);
-
-load_from_mem_sse2(compiler, data1_ind, str_ptr_ind);
-
-jump[0] = CMP(SLJIT_EQUAL, STR_PTR, 0, TMP1, 0);
-
-load_from_mem_sse2(compiler, data2_ind, tmp1_ind);
-
-/* MOVDQA xmm1, xmm2/m128 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x6f;
-instruction[3] = 0xc0 | (tmp_ind << 3) | data1_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* PSLLDQ xmm1, xmm2/m128, imm8 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x73;
-instruction[3] = 0xc0 | (7 << 3) | tmp_ind;
-instruction[4] = diff;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-/* PSRLDQ xmm1, xmm2/m128, imm8 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-/* instruction[2] = 0x73; */
-instruction[3] = 0xc0 | (3 << 3) | data2_ind;
-instruction[4] = 16 - diff;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-/* POR xmm1, xmm2/m128 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0xeb;
-instruction[3] = 0xc0 | (data2_ind << 3) | tmp_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-jump[1] = JUMP(SLJIT_JUMP);
-
-JUMPHERE(jump[0]);
-
-/* MOVDQA xmm1, xmm2/m128 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x6f;
-instruction[3] = 0xc0 | (data2_ind << 3) | data1_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* PSLLDQ xmm1, xmm2/m128, imm8 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x73;
-instruction[3] = 0xc0 | (7 << 3) | data2_ind;
-instruction[4] = diff;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-JUMPHERE(jump[1]);
-
-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);
-
-fast_forward_char_pair_sse2_compare(compiler, char2a, char2b, bit2, data2_ind, cmp2a_ind, cmp2b_ind, tmp_ind);
-fast_forward_char_pair_sse2_compare(compiler, char1a, char1b, bit1, data1_ind, cmp1a_ind, cmp1b_ind, tmp_ind);
-
-/* PAND xmm1, xmm2/m128 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0xdb;
-instruction[3] = 0xc0 | (data1_ind << 3) | data2_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* PMOVMSKB reg, xmm */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0xd7;
-instruction[3] = 0xc0 | (tmp1_ind << 3) | 0;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* Ignore matches before the first STR_PTR. */
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
-OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);
-
-/* BSF r32, r/m32 */
-instruction[0] = 0x0f;
-instruction[1] = 0xbc;
-instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
-sljit_emit_op_custom(compiler, instruction, 3);
-sljit_set_current_flags(compiler, SLJIT_SET_Z);
-
-jump[0] = JUMP(SLJIT_NOT_ZERO);
-
-OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
-
-/* Main loop. */
-instruction[0] = 0x66;
-instruction[1] = 0x0f;
-
-start = LABEL();
-
-load_from_mem_sse2(compiler, data2_ind, str_ptr_ind);
-
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
-add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
-
-load_from_mem_sse2(compiler, data1_ind, str_ptr_ind);
-
-/* PSRLDQ xmm1, xmm2/m128, imm8 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x73;
-instruction[3] = 0xc0 | (3 << 3) | data2_ind;
-instruction[4] = 16 - diff;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-/* MOVDQA xmm1, xmm2/m128 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x6f;
-instruction[3] = 0xc0 | (tmp_ind << 3) | data1_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* PSLLDQ xmm1, xmm2/m128, imm8 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x73;
-instruction[3] = 0xc0 | (7 << 3) | tmp_ind;
-instruction[4] = diff;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-/* POR xmm1, xmm2/m128 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0xeb;
-instruction[3] = 0xc0 | (data2_ind << 3) | tmp_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-fast_forward_char_pair_sse2_compare(compiler, char1a, char1b, bit1, data1_ind, cmp1a_ind, cmp1b_ind, tmp_ind);
-fast_forward_char_pair_sse2_compare(compiler, char2a, char2b, bit2, data2_ind, cmp2a_ind, cmp2b_ind, tmp_ind);
-
-/* PAND xmm1, xmm2/m128 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0xdb;
-instruction[3] = 0xc0 | (data1_ind << 3) | data2_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* PMOVMSKB reg, xmm */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0xd7;
-instruction[3] = 0xc0 | (tmp1_ind << 3) | 0;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* BSF r32, r/m32 */
-instruction[0] = 0x0f;
-instruction[1] = 0xbc;
-instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
-sljit_emit_op_custom(compiler, instruction, 3);
-sljit_set_current_flags(compiler, SLJIT_SET_Z);
-
-JUMPTO(SLJIT_ZERO, start);
-
-JUMPHERE(jump[0]);
-
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
-
-add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
-
-if (common->match_end_ptr != 0)
- OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
-
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-if (common->utf)
- {
- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offs1));
-
- jump[0] = jump_if_utf_char_start(compiler, TMP1);
-
- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, restart);
-
- add_jump(compiler, &common->failed_match, JUMP(SLJIT_JUMP));
-
- JUMPHERE(jump[0]);
- }
-#endif
-
-OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));
-
-if (common->match_end_ptr != 0)
- OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
+ repeat = 1;
+ if (last)
+ return consumed;
+ }
}
-static BOOL check_fast_forward_char_pair_sse2(compiler_common *common, fast_forward_char_data *chars, int max)
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+static void jumpto_if_not_utf_char_start(struct sljit_compiler *compiler, sljit_s32 reg, struct sljit_label *label)
{
-sljit_s32 i, j, priority, count;
-sljit_u32 priorities;
-PCRE2_UCHAR a1, a2, b1, b2;
-
-priorities = 0;
-
-count = 0;
-for (i = 0; i < max; i++)
- {
- if (chars[i].last_count > 2)
- {
- SLJIT_ASSERT(chars[i].last_count <= 7);
+#if PCRE2_CODE_UNIT_WIDTH == 8
+OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xc0);
+CMPTO(SLJIT_EQUAL, reg, 0, SLJIT_IMM, 0x80, label);
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xfc00);
+CMPTO(SLJIT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00, label);
+#else
+#error "Unknown code width"
+#endif
+}
+#endif
- priorities |= (1 << chars[i].last_count);
- count++;
- }
- }
+#include "pcre2_jit_simd_inc.h"
-if (count < 2)
- return FALSE;
+#ifdef JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD
-for (priority = 7; priority > 2; priority--)
- {
- if ((priorities & (1 << priority)) == 0)
- continue;
+static BOOL check_fast_forward_char_pair_simd(compiler_common *common, fast_forward_char_data *chars, int max)
+{
+ sljit_s32 i, j, max_i = 0, max_j = 0;
+ sljit_u32 max_pri = 0;
+ PCRE2_UCHAR a1, a2, a_pri, b1, b2, b_pri;
for (i = max - 1; i >= 1; i--)
- if (chars[i].last_count >= priority)
+ {
+ if (chars[i].last_count > 2)
{
- SLJIT_ASSERT(chars[i].count <= 2 && chars[i].count >= 1);
-
a1 = chars[i].chars[0];
a2 = chars[i].chars[1];
+ a_pri = chars[i].last_count;
- j = i - max_fast_forward_char_pair_sse2_offset();
+ j = i - max_fast_forward_char_pair_offset();
if (j < 0)
j = 0;
while (j < i)
{
- if (chars[j].last_count >= priority)
+ b_pri = chars[j].last_count;
+ if (b_pri > 2 && a_pri + b_pri >= max_pri)
{
b1 = chars[j].chars[0];
b2 = chars[j].chars[1];
if (a1 != b1 && a1 != b2 && a2 != b1 && a2 != b2)
{
- fast_forward_char_pair_sse2(common, i, a1, a2, j, b1, b2);
- return TRUE;
+ max_pri = a_pri + b_pri;
+ max_i = i;
+ max_j = j;
}
}
j++;
}
}
- }
-
-return FALSE;
-}
+ }
-#endif
+if (max_pri == 0)
+ return FALSE;
-#undef SSE2_COMPARE_TYPE_INDEX
+fast_forward_char_pair_simd(common, max_i, chars[max_i].chars[0], chars[max_i].chars[1], max_j, chars[max_j].chars[0], chars[max_j].chars[1]);
+return TRUE;
+}
-#endif
+#endif /* JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD */
static void fast_forward_first_char2(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)
{
@@ -5006,13 +5596,11 @@ if (has_match_end)
CMOV(SLJIT_GREATER, STR_END, TMP1, 0);
}
-#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND)
+#ifdef JIT_HAS_FAST_FORWARD_CHAR_SIMD
-/* SSE2 accelerated first character search. */
-
-if (sljit_has_cpu_feature(SLJIT_HAS_SSE2))
+if (JIT_HAS_FAST_FORWARD_CHAR_SIMD)
{
- fast_forward_first_char2_sse2(common, char1, char2, offset);
+ fast_forward_char_simd(common, char1, char2, offset);
if (offset > 0)
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
@@ -5119,8 +5707,8 @@ for (i = 0; i < max; i++)
chars[i].last_count = (chars[i].count == 255) ? 0 : 1;
}
-#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND) && !(defined _WIN64)
-if (check_fast_forward_char_pair_sse2(common, chars, max))
+#ifdef JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD
+if (JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD && check_fast_forward_char_pair_simd(common, chars, max))
return TRUE;
#endif
@@ -5205,18 +5793,21 @@ if (common->match_end_ptr != 0)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
- OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
+ add_jump(compiler, &common->failed_match, JUMP(SLJIT_LESS));
OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP1, 0);
CMOV(SLJIT_GREATER, STR_END, TMP1, 0);
}
else
- OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
+ add_jump(compiler, &common->failed_match, JUMP(SLJIT_LESS));
+ }
SLJIT_ASSERT(range_right >= 0);
-#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table);
-#endif
+if (!HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table);
start = LABEL();
add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));
@@ -5227,11 +5818,11 @@ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right));
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right + 1) - 1);
#endif
-#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0);
-#else
-OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table);
-#endif
+if (!HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0);
+else
+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table);
+
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, start);
@@ -5325,9 +5916,17 @@ if (common->match_end_ptr != 0)
if (common->nltype == NLTYPE_FIXED && common->newline > 255)
{
lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+ }
+ else
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
+ }
firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2));
@@ -5355,15 +5954,22 @@ if (common->nltype == NLTYPE_FIXED && common->newline > 255)
return;
}
-OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
-OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+ }
+else
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));
+
+/* Example: match /^/ to \r\n from offset 1. */
firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
-skip_char_back(common);
+move_back(common, NULL, FALSE);
loop = LABEL();
common->ff_newline_shortcut = loop;
-read_char_range(common, common->nlmin, common->nlmax, TRUE);
+read_char(common, common->nlmin, common->nlmax, NULL, READ_CHAR_NEWLINE);
lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
foundcr = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
@@ -5437,7 +6043,7 @@ if (!optimize_class(common, start_bits, (start_bits[31] & 0x80) != 0, FALSE, &ma
OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits);
- if (sljit_get_register_index(TMP3) >= 0)
+ if (!HAS_VIRTUAL_REGISTERS)
{
OP2(SLJIT_SHL, TMP3, 0, SLJIT_IMM, 1, TMP2, 0);
OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP3, 0);
@@ -5544,7 +6150,7 @@ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), -sizeof(sljit_sw));
jump = CMP(SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0);
OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
-if (sljit_get_register_index (TMP3) < 0)
+if (HAS_VIRTUAL_REGISTERS)
{
OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw)));
OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(STACK_TOP), -(3 * sizeof(sljit_sw)));
@@ -5569,7 +6175,7 @@ sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
JUMPHERE(jump);
OP1(SLJIT_NEG, TMP2, 0, TMP2, 0);
OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
-if (sljit_get_register_index (TMP3) < 0)
+if (HAS_VIRTUAL_REGISTERS)
{
OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw)));
OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));
@@ -5588,21 +6194,49 @@ static void check_wordboundary(compiler_common *common)
DEFINE_COMPILER;
struct sljit_jump *skipread;
jump_list *skipread_list = NULL;
+#ifdef SUPPORT_UNICODE
+struct sljit_label *valid_utf;
+jump_list *invalid_utf1 = NULL;
+#endif /* SUPPORT_UNICODE */
+jump_list *invalid_utf2 = NULL;
#if PCRE2_CODE_UNIT_WIDTH != 8 || defined SUPPORT_UNICODE
struct sljit_jump *jump;
-#endif
+#endif /* PCRE2_CODE_UNIT_WIDTH != 8 || SUPPORT_UNICODE */
SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16);
sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
-/* Get type of the previous char, and put it to LOCALS1. */
+/* Get type of the previous char, and put it to TMP3. */
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
-OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, SLJIT_IMM, 0);
-skipread = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP1, 0);
-skip_char_back(common);
-check_start_used_ptr(common);
-read_char(common);
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);
+skipread = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
+
+#ifdef SUPPORT_UNICODE
+if (common->invalid_utf)
+ {
+ peek_char_back(common, READ_CHAR_MAX, &invalid_utf1);
+
+ if (common->mode != PCRE2_JIT_COMPLETE)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
+ move_back(common, NULL, TRUE);
+ check_start_used_ptr(common);
+ OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0);
+ }
+ }
+else
+#endif /* SUPPORT_UNICODE */
+ {
+ if (common->mode == PCRE2_JIT_COMPLETE)
+ peek_char_back(common, READ_CHAR_MAX, NULL);
+ else
+ {
+ move_back(common, NULL, TRUE);
+ check_start_used_ptr(common);
+ read_char(common, 0, READ_CHAR_MAX, NULL, READ_CHAR_UPDATE_STR_PTR);
+ }
+ }
/* Testing char type. */
#ifdef SUPPORT_UNICODE
@@ -5610,7 +6244,7 @@ if (common->use_ucp)
{
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
- add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
+ add_jump(compiler, &common->getucdtype, JUMP(SLJIT_FAST_CALL));
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
@@ -5618,23 +6252,22 @@ if (common->use_ucp)
OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
JUMPHERE(jump);
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP2, 0);
+ OP1(SLJIT_MOV, TMP3, 0, TMP2, 0);
}
else
-#endif
+#endif /* SUPPORT_UNICODE */
{
#if PCRE2_CODE_UNIT_WIDTH != 8
jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
#elif defined SUPPORT_UNICODE
- /* Here LOCALS1 has already been zeroed. */
+ /* Here TMP3 has already been zeroed. */
jump = NULL;
if (common->utf)
jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes);
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */);
- OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0);
+ OP2(SLJIT_AND, TMP3, 0, TMP1, 0, SLJIT_IMM, 1);
#if PCRE2_CODE_UNIT_WIDTH != 8
JUMPHERE(jump);
#elif defined SUPPORT_UNICODE
@@ -5646,15 +6279,18 @@ JUMPHERE(skipread);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
check_str_end(common, &skipread_list);
-peek_char(common, READ_CHAR_MAX);
+peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCALS1, &invalid_utf2);
/* Testing char type. This is a code duplication. */
#ifdef SUPPORT_UNICODE
+
+valid_utf = LABEL();
+
if (common->use_ucp)
{
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
- add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
+ add_jump(compiler, &common->getucdtype, JUMP(SLJIT_FAST_CALL));
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
@@ -5664,7 +6300,7 @@ if (common->use_ucp)
JUMPHERE(jump);
}
else
-#endif
+#endif /* SUPPORT_UNICODE */
{
#if PCRE2_CODE_UNIT_WIDTH != 8
/* TMP2 may be destroyed by peek_char. */
@@ -5688,8 +6324,28 @@ else
}
set_jumps(skipread_list, LABEL());
-OP2(SLJIT_XOR | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
-sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
+OP2(SLJIT_XOR | SLJIT_SET_Z, TMP2, 0, TMP2, 0, TMP3, 0);
+sljit_emit_fast_return(compiler, TMP1, 0);
+
+#ifdef SUPPORT_UNICODE
+if (common->invalid_utf)
+ {
+ set_jumps(invalid_utf1, LABEL());
+
+ peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCALS1, NULL);
+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR, valid_utf);
+
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, -1);
+ sljit_emit_fast_return(compiler, TMP1, 0);
+
+ set_jumps(invalid_utf2, LABEL());
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
+ OP1(SLJIT_MOV, TMP2, 0, TMP3, 0);
+ sljit_emit_fast_return(compiler, TMP1, 0);
+ }
+#endif /* SUPPORT_UNICODE */
}
static BOOL optimize_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks)
@@ -5856,9 +6512,6 @@ int i, j, k, len, c;
if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV))
return FALSE;
-if (invert)
- nclass = !nclass;
-
len = 0;
for (i = 0; i < 32; i++)
@@ -5940,6 +6593,9 @@ if (j != 0)
}
}
+if (invert)
+ nclass = !nclass;
+
type = nclass ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;
add_jump(compiler, backtracks, CMP(type, TMP2, 0, SLJIT_IMM, 0));
return TRUE;
@@ -6055,7 +6711,7 @@ struct sljit_label *label;
int char1_reg;
int char2_reg;
-if (sljit_get_register_index(TMP3) < 0)
+if (HAS_VIRTUAL_REGISTERS)
{
char1_reg = STR_END;
char2_reg = STACK_TOP;
@@ -6137,7 +6793,7 @@ int char2_reg;
int lcc_table;
int opt_type = 0;
-if (sljit_get_register_index(TMP3) < 0)
+if (HAS_VIRTUAL_REGISTERS)
{
char2_reg = STACK_TOP;
lcc_table = STACK_LIMIT;
@@ -6225,37 +6881,6 @@ OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
sljit_emit_fast_return(compiler, TMP1, 0);
}
-#if defined SUPPORT_UNICODE
-
-static PCRE2_SPTR SLJIT_FUNC do_utf_caselesscmp(PCRE2_SPTR src1, PCRE2_SPTR src2, PCRE2_SPTR end1, PCRE2_SPTR end2)
-{
-/* This function would be ineffective to do in JIT level. */
-sljit_u32 c1, c2;
-const ucd_record *ur;
-const sljit_u32 *pp;
-
-while (src1 < end1)
- {
- if (src2 >= end2)
- return (PCRE2_SPTR)1;
- GETCHARINC(c1, src1);
- GETCHARINC(c2, src2);
- ur = GET_UCD(c2);
- if (c1 != c2 && c1 != c2 + ur->other_case)
- {
- pp = PRIV(ucd_caseless_sets) + ur->caseset;
- for (;;)
- {
- if (c1 < *pp) return NULL;
- if (c1 == *pp++) break;
- }
- }
- }
-return src2;
-}
-
-#endif /* SUPPORT_UNICODE */
-
static PCRE2_SPTR byte_sequence_compare(compiler_common *common, BOOL caseless, PCRE2_SPTR cc,
compare_context *context, jump_list **backtracks)
{
@@ -6297,7 +6922,7 @@ if (context->sourcereg == -1)
OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
else
#endif
- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
#elif PCRE2_CODE_UNIT_WIDTH == 16
#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
if (context->length >= 4)
@@ -6444,7 +7069,7 @@ PCRE2_SPTR ccbegin;
int compares, invertcmp, numberofcmps;
#if defined SUPPORT_UNICODE && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16)
BOOL utf = common->utf;
-#endif
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == [8|16] */
#ifdef SUPPORT_UNICODE
BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;
@@ -6452,7 +7077,7 @@ BOOL charsaved = FALSE;
int typereg = TMP1;
const sljit_u32 *other_cases;
sljit_uw typeoffset;
-#endif
+#endif /* SUPPORT_UNICODE */
/* Scanning the necessary info. */
cc++;
@@ -6476,7 +7101,7 @@ while (*cc != XCL_END)
if (c < min) min = c;
#ifdef SUPPORT_UNICODE
needschar = TRUE;
-#endif
+#endif /* SUPPORT_UNICODE */
}
else if (*cc == XCL_RANGE)
{
@@ -6487,7 +7112,7 @@ while (*cc != XCL_END)
if (c > max) max = c;
#ifdef SUPPORT_UNICODE
needschar = TRUE;
-#endif
+#endif /* SUPPORT_UNICODE */
}
#ifdef SUPPORT_UNICODE
else
@@ -6555,13 +7180,16 @@ while (*cc != XCL_END)
}
cc += 2;
}
-#endif
+#endif /* SUPPORT_UNICODE */
}
SLJIT_ASSERT(compares > 0);
/* We are not necessary in utf mode even in 8 bit mode. */
cc = ccbegin;
-read_char_range(common, min, max, (cc[-1] & XCL_NOT) != 0);
+if ((cc[-1] & XCL_NOT) != 0)
+ read_char(common, min, max, backtracks, READ_CHAR_UPDATE_STR_PTR);
+else
+ read_char(common, min, max, NULL, 0);
if ((cc[-1] & XCL_HASPROP) == 0)
{
@@ -6594,13 +7222,13 @@ else if ((cc[-1] & XCL_MAP) != 0)
OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
#ifdef SUPPORT_UNICODE
charsaved = TRUE;
-#endif
+#endif /* SUPPORT_UNICODE */
if (!optimize_class(common, (const sljit_u8 *)cc, FALSE, TRUE, list))
{
#if PCRE2_CODE_UNIT_WIDTH == 8
jump = NULL;
if (common->utf)
-#endif
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
@@ -6612,7 +7240,7 @@ else if ((cc[-1] & XCL_MAP) != 0)
#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
-#endif
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
JUMPHERE(jump);
}
@@ -6630,10 +7258,10 @@ if (needstype || needsscript)
if (!common->utf)
{
jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1);
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, UNASSIGNED_UTF_CHAR);
JUMPHERE(jump);
}
-#endif
+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */
OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
@@ -6647,8 +7275,16 @@ if (needstype || needsscript)
/* Before anything else, we deal with scripts. */
if (needsscript)
{
+// PH hacking
+ OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2);
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
+
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
+
+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 0);
+
+ // OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
ccbegin = cc;
@@ -6686,33 +7322,47 @@ if (needstype || needsscript)
}
if (needschar)
- {
OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);
- }
if (needstype)
{
if (!needschar)
{
+// PH hacking
+ OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2);
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
+ OP2(SLJIT_ADD, TMP1, 0, TMP2, 0, TMP1, 0);
+
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
+
+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 0);
+
+// OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
}
else
{
+// PH hacking
+ OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2);
+
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
+
+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
+ OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);
+
OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
typereg = RETURN_ADDR;
}
}
}
-#endif
+#endif /* SUPPORT_UNICODE */
/* Generating code. */
charoffset = 0;
numberofcmps = 0;
#ifdef SUPPORT_UNICODE
typeoffset = 0;
-#endif
+#endif /* SUPPORT_UNICODE */
while (*cc != XCL_END)
{
@@ -6979,7 +7629,7 @@ while (*cc != XCL_END)
}
cc += 2;
}
-#endif
+#endif /* SUPPORT_UNICODE */
if (jump != NULL)
add_jump(compiler, compares > 0 ? list : backtracks, jump);
@@ -7006,20 +7656,37 @@ struct sljit_label *label;
switch(type)
{
case OP_SOD:
- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+ }
+ else
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
return cc;
case OP_SOM:
- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+ }
+ else
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));
add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
return cc;
case OP_NOT_WORD_BOUNDARY:
case OP_WORD_BOUNDARY:
add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL));
+#ifdef SUPPORT_UNICODE
+ if (common->invalid_utf)
+ {
+ add_jump(compiler, backtracks, CMP((type == OP_NOT_WORD_BOUNDARY) ? SLJIT_NOT_EQUAL : SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+ return cc;
+ }
+#endif /* SUPPORT_UNICODE */
sljit_set_current_flags(compiler, SLJIT_SET_Z);
add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_NOT_ZERO : SLJIT_ZERO));
return cc;
@@ -7078,29 +7745,36 @@ switch(type)
}
else
{
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, STR_PTR, 0);
- read_char_range(common, common->nlmin, common->nlmax, TRUE);
+ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
+ read_char(common, common->nlmin, common->nlmax, backtracks, READ_CHAR_UPDATE_STR_PTR);
add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
sljit_set_current_flags(compiler, SLJIT_SET_Z);
add_jump(compiler, backtracks, JUMP(SLJIT_ZERO));
- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
+ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
}
JUMPHERE(jump[2]);
JUMPHERE(jump[3]);
}
JUMPHERE(jump[0]);
- check_partial(common, FALSE);
+ if (common->mode != PCRE2_JIT_COMPLETE)
+ check_partial(common, TRUE);
return cc;
case OP_EOD:
add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0));
- check_partial(common, FALSE);
+ if (common->mode != PCRE2_JIT_COMPLETE)
+ check_partial(common, TRUE);
return cc;
case OP_DOLL:
- OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
+ }
+ else
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
if (!common->endonly)
@@ -7114,8 +7788,13 @@ switch(type)
case OP_DOLLM:
jump[1] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
- OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
+ }
+ else
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
check_partial(common, FALSE);
jump[0] = JUMP(SLJIT_JUMP);
@@ -7143,25 +7822,45 @@ switch(type)
}
else
{
- peek_char(common, common->nlmax);
+ peek_char(common, common->nlmax, TMP3, 0, NULL);
check_newlinechar(common, common->nltype, backtracks, FALSE);
}
JUMPHERE(jump[0]);
return cc;
case OP_CIRC:
- OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
- add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
- add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
+ }
+ else
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
+ }
return cc;
case OP_CIRCM:
- OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
- jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0);
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ /* TMP2 might be used by peek_char_back. */
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+ jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0);
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ }
+ else
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
+ jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0);
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ }
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
jump[0] = JUMP(SLJIT_JUMP);
JUMPHERE(jump[1]);
@@ -7171,8 +7870,8 @@ switch(type)
if (common->nltype == NLTYPE_FIXED && common->newline > 255)
{
- OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
- add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, TMP1, 0));
+ OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, TMP2, 0));
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2));
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
@@ -7180,8 +7879,7 @@ switch(type)
}
else
{
- skip_char_back(common);
- read_char_range(common, common->nlmin, common->nlmax, TRUE);
+ peek_char_back(common, common->nlmax, backtracks);
check_newlinechar(common, common->nltype, backtracks, FALSE);
}
JUMPHERE(jump[0]);
@@ -7191,55 +7889,134 @@ switch(type)
length = GET(cc, 0);
if (length == 0)
return cc + LINK_SIZE;
- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+ }
+ else
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
#ifdef SUPPORT_UNICODE
if (common->utf)
{
- OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length);
+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, length);
label = LABEL();
- add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP3, 0));
- skip_char_back(common);
- OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
+ add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0));
+ move_back(common, backtracks, FALSE);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, TMP3, 0, TMP3, 0, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, label);
}
else
#endif
{
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
- add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, TMP1, 0));
+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0));
+ }
+ check_start_used_ptr(common);
+ return cc + LINK_SIZE;
+ }
+SLJIT_UNREACHABLE();
+return cc;
+}
+
+#ifdef SUPPORT_UNICODE
+
+#if PCRE2_CODE_UNIT_WIDTH != 32
+
+static PCRE2_SPTR SLJIT_FUNC do_extuni_utf(jit_arguments *args, PCRE2_SPTR cc)
+{
+PCRE2_SPTR start_subject = args->begin;
+PCRE2_SPTR end_subject = args->end;
+int lgb, rgb, ricount;
+PCRE2_SPTR prevcc, endcc, bptr;
+BOOL first = TRUE;
+uint32_t c;
+
+prevcc = cc;
+endcc = NULL;
+do
+ {
+ GETCHARINC(c, cc);
+ rgb = UCD_GRAPHBREAK(c);
+
+ if (first)
+ {
+ lgb = rgb;
+ endcc = cc;
+ first = FALSE;
+ continue;
+ }
+
+ if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0)
+ break;
+
+ /* Not breaking between Regional Indicators is allowed only if there
+ are an even number of preceding RIs. */
+
+ if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator)
+ {
+ ricount = 0;
+ bptr = prevcc;
+
+ /* bptr is pointing to the left-hand character */
+ while (bptr > start_subject)
+ {
+ bptr--;
+ BACKCHAR(bptr);
+ GETCHAR(c, bptr);
+
+ if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator)
+ break;
+
+ ricount++;
+ }
+
+ if ((ricount & 1) != 0) break; /* Grapheme break required */
}
- check_start_used_ptr(common);
- return cc + LINK_SIZE;
+
+ /* If Extend or ZWJ follows Extended_Pictographic, do not update lgb; this
+ allows any number of them before a following Extended_Pictographic. */
+
+ if ((rgb != ucp_gbExtend && rgb != ucp_gbZWJ) ||
+ lgb != ucp_gbExtended_Pictographic)
+ lgb = rgb;
+
+ prevcc = endcc;
+ endcc = cc;
}
-SLJIT_UNREACHABLE();
-return cc;
-}
+while (cc < end_subject);
-#ifdef SUPPORT_UNICODE
+return endcc;
+}
-#if PCRE2_CODE_UNIT_WIDTH != 32
+#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */
-static PCRE2_SPTR SLJIT_FUNC do_extuni_utf(jit_arguments *args, PCRE2_SPTR cc)
+static PCRE2_SPTR SLJIT_FUNC do_extuni_utf_invalid(jit_arguments *args, PCRE2_SPTR cc)
{
PCRE2_SPTR start_subject = args->begin;
PCRE2_SPTR end_subject = args->end;
-int lgb, rgb, len, ricount;
-PCRE2_SPTR prevcc, bptr;
+int lgb, rgb, ricount;
+PCRE2_SPTR prevcc, endcc, bptr;
+BOOL first = TRUE;
uint32_t c;
prevcc = cc;
-GETCHARINC(c, cc);
-lgb = UCD_GRAPHBREAK(c);
-
-while (cc < end_subject)
+endcc = NULL;
+do
{
- len = 1;
- GETCHARLEN(c, cc, len);
+ GETCHARINC_INVALID(c, cc, end_subject, break);
rgb = UCD_GRAPHBREAK(c);
- if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
+ if (first)
+ {
+ lgb = rgb;
+ endcc = cc;
+ first = FALSE;
+ continue;
+ }
+
+ if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0)
+ break;
/* Not breaking between Regional Indicators is allowed only if there
are an even number of preceding RIs. */
@@ -7252,16 +8029,16 @@ while (cc < end_subject)
/* bptr is pointing to the left-hand character */
while (bptr > start_subject)
{
- bptr--;
- BACKCHAR(bptr);
- GETCHAR(c, bptr);
+ GETCHARBACK_INVALID(c, bptr, start_subject, break);
- if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator) break;
+ if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator)
+ break;
ricount++;
}
- if ((ricount & 1) != 0) break; /* Grapheme break required */
+ if ((ricount & 1) != 0)
+ break; /* Grapheme break required */
}
/* If Extend or ZWJ follows Extended_Pictographic, do not update lgb; this
@@ -7271,15 +8048,14 @@ while (cc < end_subject)
lgb != ucp_gbExtended_Pictographic)
lgb = rgb;
- prevcc = cc;
- cc += len;
+ prevcc = endcc;
+ endcc = cc;
}
+while (cc < end_subject);
-return cc;
+return endcc;
}
-#endif
-
static PCRE2_SPTR SLJIT_FUNC do_extuni_no_utf(jit_arguments *args, PCRE2_SPTR cc)
{
PCRE2_SPTR start_subject = args->begin;
@@ -7288,15 +8064,27 @@ int lgb, rgb, ricount;
PCRE2_SPTR bptr;
uint32_t c;
-GETCHARINC(c, cc);
+/* Patch by PH */
+/* GETCHARINC(c, cc); */
+c = *cc++;
+
+#if PCRE2_CODE_UNIT_WIDTH == 32
+if (c >= 0x110000)
+ return NULL;
+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */
lgb = UCD_GRAPHBREAK(c);
while (cc < end_subject)
{
c = *cc;
+#if PCRE2_CODE_UNIT_WIDTH == 32
+ if (c >= 0x110000)
+ break;
+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */
rgb = UCD_GRAPHBREAK(c);
- if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
+ if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0)
+ break;
/* Not breaking between Regional Indicators is allowed only if there
are an even number of preceding RIs. */
@@ -7311,13 +8099,18 @@ while (cc < end_subject)
{
bptr--;
c = *bptr;
+#if PCRE2_CODE_UNIT_WIDTH == 32
+ if (c >= 0x110000)
+ break;
+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */
if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator) break;
ricount++;
}
- if ((ricount & 1) != 0) break; /* Grapheme break required */
+ if ((ricount & 1) != 0)
+ break; /* Grapheme break required */
}
/* If Extend or ZWJ follows Extended_Pictographic, do not update lgb; this
@@ -7333,7 +8126,7 @@ while (cc < end_subject)
return cc;
}
-#endif
+#endif /* SUPPORT_UNICODE */
static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr)
{
@@ -7356,10 +8149,10 @@ switch(type)
detect_partial_match(common, backtracks);
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_digit, FALSE))
- read_char7_type(common, type == OP_NOT_DIGIT);
+ read_char7_type(common, backtracks, type == OP_NOT_DIGIT);
else
#endif
- read_char8_type(common, type == OP_NOT_DIGIT);
+ read_char8_type(common, backtracks, type == OP_NOT_DIGIT);
/* Flip the starting bit in the negative case. */
OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_ZERO : SLJIT_NOT_ZERO));
@@ -7371,10 +8164,10 @@ switch(type)
detect_partial_match(common, backtracks);
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_space, FALSE))
- read_char7_type(common, type == OP_NOT_WHITESPACE);
+ read_char7_type(common, backtracks, type == OP_NOT_WHITESPACE);
else
#endif
- read_char8_type(common, type == OP_NOT_WHITESPACE);
+ read_char8_type(common, backtracks, type == OP_NOT_WHITESPACE);
OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_ZERO : SLJIT_NOT_ZERO));
return cc;
@@ -7385,10 +8178,10 @@ switch(type)
detect_partial_match(common, backtracks);
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_word, FALSE))
- read_char7_type(common, type == OP_NOT_WORDCHAR);
+ read_char7_type(common, backtracks, type == OP_NOT_WORDCHAR);
else
#endif
- read_char8_type(common, type == OP_NOT_WORDCHAR);
+ read_char8_type(common, backtracks, type == OP_NOT_WORDCHAR);
OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_ZERO : SLJIT_NOT_ZERO));
return cc;
@@ -7396,7 +8189,7 @@ switch(type)
case OP_ANY:
if (check_str_ptr)
detect_partial_match(common, backtracks);
- read_char_range(common, common->nlmin, common->nlmax, TRUE);
+ read_char(common, common->nlmin, common->nlmax, backtracks, READ_CHAR_UPDATE_STR_PTR);
if (common->nltype == NLTYPE_FIXED && common->newline > 255)
{
jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
@@ -7418,12 +8211,18 @@ switch(type)
case OP_ALLANY:
if (check_str_ptr)
detect_partial_match(common, backtracks);
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+#ifdef SUPPORT_UNICODE
if (common->utf)
{
+ if (common->invalid_utf)
+ {
+ read_char(common, 0, READ_CHAR_MAX, backtracks, READ_CHAR_UPDATE_STR_PTR);
+ return cc;
+ }
+
+#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16
#if PCRE2_CODE_UNIT_WIDTH == 8
jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
@@ -7435,12 +8234,12 @@ switch(type)
OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
-#endif
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
JUMPHERE(jump[0]);
-#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16] */
return cc;
+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16] */
}
-#endif
+#endif /* SUPPORT_UNICODE */
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
return cc;
@@ -7467,7 +8266,7 @@ switch(type)
case OP_ANYNL:
if (check_str_ptr)
detect_partial_match(common, backtracks);
- read_char_range(common, common->bsr_nlmin, common->bsr_nlmax, FALSE);
+ read_char(common, common->bsr_nlmin, common->bsr_nlmax, NULL, 0);
jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
/* We don't need to handle soft partial matching case. */
end_list = NULL;
@@ -7490,7 +8289,12 @@ switch(type)
case OP_HSPACE:
if (check_str_ptr)
detect_partial_match(common, backtracks);
- read_char_range(common, 0x9, 0x3000, type == OP_NOT_HSPACE);
+
+ if (type == OP_NOT_HSPACE)
+ read_char(common, 0x9, 0x3000, backtracks, READ_CHAR_UPDATE_STR_PTR);
+ else
+ read_char(common, 0x9, 0x3000, NULL, 0);
+
add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
sljit_set_current_flags(compiler, SLJIT_SET_Z);
add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO));
@@ -7500,7 +8304,12 @@ switch(type)
case OP_VSPACE:
if (check_str_ptr)
detect_partial_match(common, backtracks);
- read_char_range(common, 0xa, 0x2029, type == OP_NOT_VSPACE);
+
+ if (type == OP_NOT_VSPACE)
+ read_char(common, 0xa, 0x2029, backtracks, READ_CHAR_UPDATE_STR_PTR);
+ else
+ read_char(common, 0xa, 0x2029, NULL, 0);
+
add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
sljit_set_current_flags(compiler, SLJIT_SET_Z);
add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO));
@@ -7516,9 +8325,14 @@ switch(type)
#if PCRE2_CODE_UNIT_WIDTH != 32
sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM,
- common->utf ? SLJIT_FUNC_OFFSET(do_extuni_utf) : SLJIT_FUNC_OFFSET(do_extuni_no_utf));
+ common->utf ? (common->invalid_utf ? SLJIT_FUNC_OFFSET(do_extuni_utf_invalid) : SLJIT_FUNC_OFFSET(do_extuni_utf)) : SLJIT_FUNC_OFFSET(do_extuni_no_utf));
+ if (common->invalid_utf)
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
#else
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_extuni_no_utf));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM,
+ common->invalid_utf ? SLJIT_FUNC_OFFSET(do_extuni_utf_invalid) : SLJIT_FUNC_OFFSET(do_extuni_no_utf));
+ if (!common->utf || common->invalid_utf)
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
#endif
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
@@ -7539,11 +8353,15 @@ switch(type)
#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc);
#endif
- if (common->mode == PCRE2_JIT_COMPLETE && check_str_ptr
- && (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0))
+
+ if (check_str_ptr && common->mode != PCRE2_JIT_COMPLETE)
+ detect_partial_match(common, backtracks);
+
+ if (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0)
{
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
- add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));
+ if (length > 1 || (check_str_ptr && common->mode == PCRE2_JIT_COMPLETE))
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));
context.length = IN_UCHARS(length);
context.sourcereg = -1;
@@ -7553,8 +8371,6 @@ switch(type)
return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks);
}
- if (check_str_ptr)
- detect_partial_match(common, backtracks);
#ifdef SUPPORT_UNICODE
if (common->utf)
{
@@ -7564,24 +8380,28 @@ switch(type)
#endif
c = *cc;
- if (type == OP_CHAR || !char_has_othercase(common, cc))
+ SLJIT_ASSERT(type == OP_CHARI && char_has_othercase(common, cc));
+
+ if (check_str_ptr && common->mode == PCRE2_JIT_COMPLETE)
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
+ oc = char_othercase(common, c);
+ read_char(common, c < oc ? c : oc, c > oc ? c : oc, NULL, 0);
+
+ SLJIT_ASSERT(!is_powerof2(c ^ oc));
+
+ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV))
{
- read_char_range(common, c, c, FALSE);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc);
+ CMOV(SLJIT_EQUAL, TMP1, SLJIT_IMM, c);
add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c));
- return cc + length;
}
- oc = char_othercase(common, c);
- read_char_range(common, c < oc ? c : oc, c > oc ? c : oc, FALSE);
- bit = c ^ oc;
- if (is_powerof2(bit))
+ else
{
- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
- return cc + length;
+ jump[0] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c);
+ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, oc));
+ JUMPHERE(jump[0]);
}
- jump[0] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c);
- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, oc));
- JUMPHERE(jump[0]);
return cc + length;
case OP_NOT:
@@ -7595,7 +8415,7 @@ switch(type)
{
#if PCRE2_CODE_UNIT_WIDTH == 8
c = *cc;
- if (c < 128)
+ if (c < 128 && !common->invalid_utf)
{
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
if (type == OP_NOT || !char_has_othercase(common, cc))
@@ -7626,13 +8446,13 @@ switch(type)
if (type == OP_NOT || !char_has_othercase(common, cc))
{
- read_char_range(common, c, c, TRUE);
+ read_char(common, c, c, backtracks, READ_CHAR_UPDATE_STR_PTR);
add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c));
}
else
{
oc = char_othercase(common, c);
- read_char_range(common, c < oc ? c : oc, c > oc ? c : oc, TRUE);
+ read_char(common, c < oc ? c : oc, c > oc ? c : oc, backtracks, READ_CHAR_UPDATE_STR_PTR);
bit = c ^ oc;
if (is_powerof2(bit))
{
@@ -7654,9 +8474,15 @@ switch(type)
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
bit = (common->utf && is_char7_bitset((const sljit_u8 *)cc, type == OP_NCLASS)) ? 127 : 255;
- read_char_range(common, 0, bit, type == OP_NCLASS);
+ if (type == OP_NCLASS)
+ read_char(common, 0, bit, backtracks, READ_CHAR_UPDATE_STR_PTR);
+ else
+ read_char(common, 0, bit, NULL, 0);
#else
- read_char_range(common, 0, 255, type == OP_NCLASS);
+ if (type == OP_NCLASS)
+ read_char(common, 0, 255, backtracks, READ_CHAR_UPDATE_STR_PTR);
+ else
+ read_char(common, 0, 255, NULL, 0);
#endif
if (optimize_class(common, (const sljit_u8 *)cc, type == OP_NCLASS, FALSE, backtracks))
@@ -7843,6 +8669,14 @@ int offset = 0;
struct sljit_jump *jump = NULL;
struct sljit_jump *partial;
struct sljit_jump *nopartial;
+#if defined SUPPORT_UNICODE
+struct sljit_label *loop;
+struct sljit_label *caseless_loop;
+jump_list *no_match = NULL;
+int source_reg = COUNT_MATCH;
+int source_end_reg = ARGUMENTS;
+int char1_reg = STACK_LIMIT;
+#endif /* SUPPORT_UNICODE */
if (ref)
{
@@ -7858,34 +8692,96 @@ else
#if defined SUPPORT_UNICODE
if (common->utf && *cc == OP_REFI)
{
- SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);
+ SLJIT_ASSERT(common->iref_ptr != 0);
+
if (ref)
- OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
else
- OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
- if (withchecks)
- jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_R2, 0);
- /* No free saved registers so save data on stack. */
+ if (withchecks && emptyfail)
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, TMP2, 0));
- OP1(SLJIT_MOV, SLJIT_R3, 0, STR_END, 0);
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp));
- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->iref_ptr, source_reg, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw), source_end_reg, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2, char1_reg, 0);
+
+ OP1(SLJIT_MOV, source_reg, 0, TMP1, 0);
+ OP1(SLJIT_MOV, source_end_reg, 0, TMP2, 0);
+
+ loop = LABEL();
+ jump = CMP(SLJIT_GREATER_EQUAL, source_reg, 0, source_end_reg, 0);
+ partial = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+
+ /* Read original character. It must be a valid UTF character. */
+ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
+ OP1(SLJIT_MOV, STR_PTR, 0, source_reg, 0);
+
+ read_char(common, 0, READ_CHAR_MAX, NULL, READ_CHAR_UPDATE_STR_PTR | READ_CHAR_VALID_UTF);
+
+ OP1(SLJIT_MOV, source_reg, 0, STR_PTR, 0);
+ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
+ OP1(SLJIT_MOV, char1_reg, 0, TMP1, 0);
+
+ /* Read second character. */
+ read_char(common, 0, READ_CHAR_MAX, &no_match, READ_CHAR_UPDATE_STR_PTR);
+
+ CMPTO(SLJIT_EQUAL, TMP1, 0, char1_reg, 0, loop);
+// PH hacking
+ OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
+
+ add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
+
+ OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2);
+
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
+
+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
+
+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records));
+
+ OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(ucd_record, other_case));
+ OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(ucd_record, caseset));
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP3, 0);
+ CMPTO(SLJIT_EQUAL, TMP1, 0, char1_reg, 0, loop);
+
+ add_jump(compiler, &no_match, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);
+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_caseless_sets));
+
+ caseless_loop = LABEL();
+ OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(TMP2), 0);
+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, sizeof(uint32_t));
+ OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, char1_reg, 0);
+ JUMPTO(SLJIT_EQUAL, loop);
+ JUMPTO(SLJIT_LESS, caseless_loop);
+
+ set_jumps(no_match, LABEL());
if (common->mode == PCRE2_JIT_COMPLETE)
- add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1));
- else
- {
- OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
+ JUMPHERE(partial);
- add_jump(compiler, backtracks, JUMP(SLJIT_LESS));
+ OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr);
+ OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw));
+ OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2);
+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
+
+ if (common->mode != PCRE2_JIT_COMPLETE)
+ {
+ JUMPHERE(partial);
+ OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr);
+ OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw));
+ OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2);
- nopartial = JUMP(SLJIT_NOT_EQUAL);
- OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);
check_partial(common, FALSE);
add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
- JUMPHERE(nopartial);
}
+
+ JUMPHERE(jump);
+ OP1(SLJIT_MOV, source_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr);
+ OP1(SLJIT_MOV, source_end_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw));
+ OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), common->iref_ptr + sizeof(sljit_sw) * 2);
+ return;
}
else
#endif /* SUPPORT_UNICODE */
@@ -8862,6 +9758,42 @@ if (common->optimized_cbracket[offset >> 1] == 0)
return stacksize;
}
+static PCRE2_SPTR SLJIT_FUNC do_script_run(PCRE2_SPTR ptr, PCRE2_SPTR endptr)
+{
+ if (PRIV(script_run)(ptr, endptr, FALSE))
+ return endptr;
+ return NULL;
+}
+
+#ifdef SUPPORT_UNICODE
+
+static PCRE2_SPTR SLJIT_FUNC do_script_run_utf(PCRE2_SPTR ptr, PCRE2_SPTR endptr)
+{
+ if (PRIV(script_run)(ptr, endptr, TRUE))
+ return endptr;
+ return NULL;
+}
+
+#endif /* SUPPORT_UNICODE */
+
+static SLJIT_INLINE void match_script_run_common(compiler_common *common, int private_data_ptr, backtrack_common *parent)
+{
+DEFINE_COMPILER;
+
+SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
+#ifdef SUPPORT_UNICODE
+sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM,
+ common->utf ? SLJIT_FUNC_OFFSET(do_script_run_utf) : SLJIT_FUNC_OFFSET(do_script_run));
+#else
+sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_script_run));
+#endif
+
+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
+add_jump(compiler, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
+}
+
/*
Handling bracketed expressions is probably the most complex part.
@@ -8997,7 +9929,7 @@ if (opcode == OP_CBRA || opcode == OP_SCBRA)
BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr;
matchingpath += IMM2_SIZE;
}
-else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND)
+else if (opcode == OP_ONCE || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND)
{
/* Other brackets simply allocate the next entry. */
private_data_ptr = PRIVATE_DATA(ccbegin);
@@ -9036,35 +9968,32 @@ if (bra == OP_BRAMINZERO)
free_stack(common, 1);
braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
}
- else
+ else if (opcode == OP_ONCE || opcode >= OP_SBRA)
{
- if (opcode == OP_ONCE || opcode >= OP_SBRA)
+ jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
+ /* Nothing stored during the first run. */
+ skip = JUMP(SLJIT_JUMP);
+ JUMPHERE(jump);
+ /* Checking zero-length iteration. */
+ if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
{
- jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
- /* Nothing stored during the first run. */
- skip = JUMP(SLJIT_JUMP);
- JUMPHERE(jump);
- /* Checking zero-length iteration. */
- if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
- {
- /* When we come from outside, private_data_ptr contains the previous STR_PTR. */
- braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
- }
- else
- {
- /* Except when the whole stack frame must be saved. */
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
- braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), STACK(-BACKTRACK_AS(bracket_backtrack)->u.framesize - 2));
- }
- JUMPHERE(skip);
+ /* When we come from outside, private_data_ptr contains the previous STR_PTR. */
+ braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
}
else
{
- jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
- OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
- JUMPHERE(jump);
+ /* Except when the whole stack frame must be saved. */
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
+ braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), STACK(-BACKTRACK_AS(bracket_backtrack)->u.framesize - 2));
}
+ JUMPHERE(skip);
+ }
+ else
+ {
+ jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
+ JUMPHERE(jump);
}
}
@@ -9081,7 +10010,7 @@ if (ket == OP_KETRMIN)
if (ket == OP_KETRMAX)
{
rmax_label = LABEL();
- if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA && repeat_type == 0)
+ if (has_alternatives && opcode >= OP_BRA && opcode < OP_SBRA && repeat_type == 0)
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmax_label;
}
@@ -9185,7 +10114,7 @@ else if (opcode == OP_CBRA || opcode == OP_SCBRA)
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
}
}
-else if (opcode == OP_SBRA || opcode == OP_SCOND)
+else if (opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND)
{
/* Saving the previous value. */
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
@@ -9314,6 +10243,9 @@ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
if (opcode == OP_ONCE)
match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);
+if (opcode == OP_SCRIPT_RUN)
+ match_script_run_common(common, private_data_ptr, backtrack);
+
stacksize = 0;
if (repeat_type == OP_MINUPTO)
{
@@ -9356,10 +10288,23 @@ if (ket != OP_KET || bra != OP_BRA)
if (offset != 0)
stacksize = match_capture_common(common, stacksize, offset, private_data_ptr);
+/* Skip and count the other alternatives. */
+i = 1;
+while (*cc == OP_ALT)
+ {
+ cc += GET(cc, 1);
+ i++;
+ }
+
if (has_alternatives)
{
if (opcode != OP_ONCE)
- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
+ {
+ if (i <= 3)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
+ else
+ BACKTRACK_AS(bracket_backtrack)->u.matching_put_label = sljit_emit_put_label(compiler, SLJIT_MEM1(STACK_TOP), STACK(stacksize));
+ }
if (ket != OP_KETRMAX)
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
}
@@ -9383,13 +10328,15 @@ if (ket == OP_KETRMAX)
if (opcode != OP_ONCE)
free_stack(common, 1);
}
- else if (opcode == OP_ONCE || opcode >= OP_SBRA)
+ else if (opcode < OP_BRA || opcode >= OP_SBRA)
{
if (has_alternatives)
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
+
/* Checking zero-length iteration. */
if (opcode != OP_ONCE)
{
+ /* This case includes opcodes such as OP_SCRIPT_RUN. */
CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0, rmax_label);
/* Drop STR_PTR for greedy plus quantifier. */
if (bra != OP_BRAZERO)
@@ -9446,9 +10393,6 @@ if (bra == OP_BRAMINZERO)
if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)
count_match(common);
-/* Skip the other alternatives. */
-while (*cc == OP_ALT)
- cc += GET(cc, 1);
cc += 1 + LINK_SIZE;
if (opcode == OP_ONCE)
@@ -9456,7 +10400,7 @@ if (opcode == OP_ONCE)
/* We temporarily encode the needs_control_head in the lowest bit.
Note: on the target architectures of SLJIT the ((x << 1) >> 1) returns
the same value for small signed numbers (including negative numbers). */
- BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);
+ BACKTRACK_AS(bracket_backtrack)->u.framesize = (int)((unsigned)BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);
}
return cc + repeat_length;
}
@@ -9951,7 +10895,7 @@ if (exact > 1)
#ifdef SUPPORT_UNICODE
&& !common->utf
#endif
- )
+ && type != OP_ANYNL && type != OP_EXTUNI)
{
OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(exact));
add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER, TMP1, 0, STR_END, 0));
@@ -10007,174 +10951,232 @@ switch(opcode)
JUMPTO(SLJIT_JUMP, label);
if (jump != NULL)
JUMPHERE(jump);
+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
+ break;
}
- else
+#ifdef SUPPORT_UNICODE
+ else if (type == OP_ALLANY && !common->invalid_utf)
+#else
+ else if (type == OP_ALLANY)
+#endif
{
- charpos_enabled = FALSE;
- charpos_char = 0;
- charpos_othercasebit = 0;
-
- if ((type != OP_CHAR && type != OP_CHARI) && (*end == OP_CHAR || *end == OP_CHARI))
+ if (opcode == OP_STAR)
{
- charpos_enabled = TRUE;
+ if (private_data_ptr == 0)
+ allocate_stack(common, 2);
+
+ OP1(SLJIT_MOV, base, offset0, STR_END, 0);
+ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
+
+ OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);
+ process_partial_match(common);
+
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_END, 0);
+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
+ break;
+ }
#ifdef SUPPORT_UNICODE
- charpos_enabled = !common->utf || !HAS_EXTRALEN(end[1]);
+ else if (!common->utf)
+#else
+ else
#endif
- if (charpos_enabled && *end == OP_CHARI && char_has_othercase(common, end + 1))
+ {
+ if (private_data_ptr == 0)
+ allocate_stack(common, 2);
+
+ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(max));
+
+ if (common->mode == PCRE2_JIT_COMPLETE)
{
- charpos_othercasebit = char_get_othercase_bit(common, end + 1);
- if (charpos_othercasebit == 0)
- charpos_enabled = FALSE;
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
+ CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);
}
-
- if (charpos_enabled)
+ else
{
- charpos_char = end[1];
- /* Consumpe the OP_CHAR opcode. */
- end += 2;
+ jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, STR_END, 0);
+ process_partial_match(common);
+ JUMPHERE(jump);
+ }
+
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
+ break;
+ }
+ }
+
+ charpos_enabled = FALSE;
+ charpos_char = 0;
+ charpos_othercasebit = 0;
+
+ if ((type != OP_CHAR && type != OP_CHARI) && (*end == OP_CHAR || *end == OP_CHARI))
+ {
+#ifdef SUPPORT_UNICODE
+ charpos_enabled = !common->utf || !HAS_EXTRALEN(end[1]);
+#else
+ charpos_enabled = TRUE;
+#endif
+ if (charpos_enabled && *end == OP_CHARI && char_has_othercase(common, end + 1))
+ {
+ charpos_othercasebit = char_get_othercase_bit(common, end + 1);
+ if (charpos_othercasebit == 0)
+ charpos_enabled = FALSE;
+ }
+
+ if (charpos_enabled)
+ {
+ charpos_char = end[1];
+ /* Consumpe the OP_CHAR opcode. */
+ end += 2;
#if PCRE2_CODE_UNIT_WIDTH == 8
- SLJIT_ASSERT((charpos_othercasebit >> 8) == 0);
+ SLJIT_ASSERT((charpos_othercasebit >> 8) == 0);
#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
- SLJIT_ASSERT((charpos_othercasebit >> 9) == 0);
- if ((charpos_othercasebit & 0x100) != 0)
- charpos_othercasebit = (charpos_othercasebit & 0xff) << 8;
+ SLJIT_ASSERT((charpos_othercasebit >> 9) == 0);
+ if ((charpos_othercasebit & 0x100) != 0)
+ charpos_othercasebit = (charpos_othercasebit & 0xff) << 8;
#endif
- if (charpos_othercasebit != 0)
- charpos_char |= charpos_othercasebit;
+ if (charpos_othercasebit != 0)
+ charpos_char |= charpos_othercasebit;
+
+ BACKTRACK_AS(char_iterator_backtrack)->u.charpos.enabled = TRUE;
+ BACKTRACK_AS(char_iterator_backtrack)->u.charpos.chr = charpos_char;
+ BACKTRACK_AS(char_iterator_backtrack)->u.charpos.othercasebit = charpos_othercasebit;
+ }
+ }
+
+ if (charpos_enabled)
+ {
+ if (opcode == OP_UPTO)
+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max + 1);
+
+ /* Search the first instance of charpos_char. */
+ jump = JUMP(SLJIT_JUMP);
+ label = LABEL();
+ if (opcode == OP_UPTO)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_ZERO));
+ }
+ compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE);
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ JUMPHERE(jump);
- BACKTRACK_AS(char_iterator_backtrack)->u.charpos.enabled = TRUE;
- BACKTRACK_AS(char_iterator_backtrack)->u.charpos.chr = charpos_char;
- BACKTRACK_AS(char_iterator_backtrack)->u.charpos.othercasebit = charpos_othercasebit;
- }
- }
+ detect_partial_match(common, &backtrack->topbacktracks);
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ if (charpos_othercasebit != 0)
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit);
+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label);
- if (charpos_enabled)
+ if (private_data_ptr == 0)
+ allocate_stack(common, 2);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
+ if (opcode == OP_UPTO)
{
- if (opcode == OP_UPTO)
- OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max + 1);
-
- /* Search the first instance of charpos_char. */
- jump = JUMP(SLJIT_JUMP);
- label = LABEL();
- if (opcode == OP_UPTO)
- {
- OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
- add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_ZERO));
- }
- compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE);
- if (fast_str_ptr != 0)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
- JUMPHERE(jump);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));
+ }
- detect_partial_match(common, &backtrack->topbacktracks);
- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
- if (charpos_othercasebit != 0)
- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit);
+ /* Search the last instance of charpos_char. */
+ label = LABEL();
+ compile_char1_matchingpath(common, type, cc, &no_match, FALSE);
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ detect_partial_match(common, &no_match);
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ if (charpos_othercasebit != 0)
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit);
+ if (opcode == OP_STAR)
+ {
CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label);
-
- if (private_data_ptr == 0)
- allocate_stack(common, 2);
OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
- OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
- if (opcode == OP_UPTO)
- {
- OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
- add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));
- }
-
- /* Search the last instance of charpos_char. */
- label = LABEL();
- compile_char1_matchingpath(common, type, cc, &no_match, FALSE);
- if (fast_str_ptr != 0)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
- detect_partial_match(common, &no_match);
- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
- if (charpos_othercasebit != 0)
- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit);
- if (opcode == OP_STAR)
- {
- CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label);
- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
- }
- else
- {
- jump = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char);
- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
- JUMPHERE(jump);
- }
-
- if (opcode == OP_UPTO)
- {
- OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
- JUMPTO(SLJIT_NOT_ZERO, label);
- }
- else
- JUMPTO(SLJIT_JUMP, label);
-
- set_jumps(no_match, LABEL());
- OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ }
+ else
+ {
+ jump = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char);
OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ JUMPHERE(jump);
}
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
- else if (common->utf)
+
+ if (opcode == OP_UPTO)
{
- if (private_data_ptr == 0)
- allocate_stack(common, 2);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ JUMPTO(SLJIT_NOT_ZERO, label);
+ }
+ else
+ JUMPTO(SLJIT_JUMP, label);
- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
- OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
+ set_jumps(no_match, LABEL());
+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ }
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ else if (common->utf)
+ {
+ if (private_data_ptr == 0)
+ allocate_stack(common, 2);
- if (opcode == OP_UPTO)
- OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
- label = LABEL();
- compile_char1_matchingpath(common, type, cc, &no_match, TRUE);
- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ if (opcode == OP_UPTO)
+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
- if (opcode == OP_UPTO)
- {
- OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
- JUMPTO(SLJIT_NOT_ZERO, label);
- }
- else
- JUMPTO(SLJIT_JUMP, label);
+ detect_partial_match(common, &no_match);
+ label = LABEL();
+ compile_char1_matchingpath(common, type, cc, &no_match, FALSE);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
- set_jumps(no_match, LABEL());
- OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
- if (fast_str_ptr != 0)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
- }
-#endif
- else
+ if (opcode == OP_UPTO)
{
- if (private_data_ptr == 0)
- allocate_stack(common, 2);
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));
+ }
- OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
- if (opcode == OP_UPTO)
- OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
+ detect_partial_match_to(common, label);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- label = LABEL();
- detect_partial_match(common, &no_match);
- compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
- if (opcode == OP_UPTO)
- {
- OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
- JUMPTO(SLJIT_NOT_ZERO, label);
- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- }
- else
- JUMPTO(SLJIT_JUMP, label);
+ set_jumps(no_match, LABEL());
+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ }
+#endif
+ else
+ {
+ if (private_data_ptr == 0)
+ allocate_stack(common, 2);
- set_jumps(no_char1_match, LABEL());
- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- set_jumps(no_match, LABEL());
- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
- if (fast_str_ptr != 0)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
+ if (opcode == OP_UPTO)
+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
+
+ detect_partial_match(common, &no_match);
+ label = LABEL();
+ compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
+ if (opcode == OP_UPTO)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));
}
+
+ detect_partial_match_to(common, label);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+ set_jumps(no_char1_match, LABEL());
+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ set_jumps(no_match, LABEL());
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
}
+
BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
break;
@@ -10211,25 +11213,47 @@ switch(opcode)
break;
case OP_POSSTAR:
+#if defined SUPPORT_UNICODE
+ if (type == OP_ALLANY && !common->invalid_utf)
+#else
+ if (type == OP_ALLANY)
+#endif
+ {
+ OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);
+ process_partial_match(common);
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_END, 0);
+ break;
+ }
+
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf)
{
OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
+ detect_partial_match(common, &no_match);
label = LABEL();
- compile_char1_matchingpath(common, type, cc, &no_match, TRUE);
+ compile_char1_matchingpath(common, type, cc, &no_match, FALSE);
OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
- JUMPTO(SLJIT_JUMP, label);
+ detect_partial_match_to(common, label);
+
set_jumps(no_match, LABEL());
OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);
if (fast_str_ptr != 0)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ {
+ if (tmp_base == TMP3)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, TMP3, 0);
+ else
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ }
break;
}
#endif
- label = LABEL();
detect_partial_match(common, &no_match);
+ label = LABEL();
compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
- JUMPTO(SLJIT_JUMP, label);
+ detect_partial_match_to(common, label);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
set_jumps(no_char1_match, LABEL());
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
set_jumps(no_match, LABEL());
@@ -10244,23 +11268,52 @@ switch(opcode)
{
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0);
OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
+
+ detect_partial_match(common, &no_match);
label = LABEL();
- compile_char1_matchingpath(common, type, cc, &no_match, TRUE);
+ compile_char1_matchingpath(common, type, cc, &no_match, FALSE);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0);
OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
- JUMPTO(SLJIT_NOT_ZERO, label);
+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));
+ detect_partial_match_to(common, label);
+
set_jumps(no_match, LABEL());
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1);
break;
}
#endif
+
+ if (type == OP_ALLANY)
+ {
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(max));
+
+ if (common->mode == PCRE2_JIT_COMPLETE)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
+ CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);
+ }
+ else
+ {
+ jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, STR_END, 0);
+ process_partial_match(common);
+ JUMPHERE(jump);
+ }
+
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ break;
+ }
+
OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
- label = LABEL();
+
detect_partial_match(common, &no_match);
+ label = LABEL();
compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
- JUMPTO(SLJIT_NOT_ZERO, label);
+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));
+ detect_partial_match_to(common, label);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
set_jumps(no_char1_match, LABEL());
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
set_jumps(no_match, LABEL());
@@ -10314,8 +11367,15 @@ if (common->accept_label == NULL)
add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)));
else
CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), common->accept_label);
-OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
-OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options));
+
+if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options));
+ }
+else
+ OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options));
+
OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY);
add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_NOT_ZERO));
OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART);
@@ -10323,7 +11383,8 @@ if (common->accept_label == NULL)
add_jump(compiler, &common->accept, JUMP(SLJIT_ZERO));
else
JUMPTO(SLJIT_ZERO, common->accept_label);
-OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? TMP1 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));
if (common->accept_label == NULL)
add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0));
else
@@ -10373,10 +11434,11 @@ if (opcode == OP_SKIP)
if (opcode == OP_COMMIT_ARG || opcode == OP_PRUNE_ARG || opcode == OP_THEN_ARG)
{
- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ if (HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0);
- OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? TMP1 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
}
return ccend;
@@ -10634,6 +11696,7 @@ while (cc < ccend)
break;
case OP_ONCE:
+ case OP_SCRIPT_RUN:
case OP_BRA:
case OP_CBRA:
case OP_COND:
@@ -10666,11 +11729,12 @@ while (cc < ccend)
SLJIT_ASSERT(common->mark_ptr != 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
allocate_stack(common, common->has_skip_arg ? 5 : 1);
- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ if (HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0), TMP2, 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0);
- OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? TMP1 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
if (common->has_skip_arg)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
@@ -10787,14 +11851,14 @@ switch(opcode)
if (CURRENT_AS(char_iterator_backtrack)->u.charpos.othercasebit != 0)
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->u.charpos.othercasebit);
CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->u.charpos.chr, CURRENT_AS(char_iterator_backtrack)->matchingpath);
- skip_char_back(common);
+ move_back(common, NULL, TRUE);
CMPTO(SLJIT_GREATER, STR_PTR, 0, TMP2, 0, label);
}
else
{
OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, base, offset1);
- skip_char_back(common);
+ move_back(common, NULL, TRUE);
OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath);
}
@@ -10997,16 +12061,15 @@ PCRE2_SPTR ccprev;
PCRE2_UCHAR bra = OP_BRA;
PCRE2_UCHAR ket;
assert_backtrack *assert;
-sljit_uw *next_update_addr = NULL;
BOOL has_alternatives;
BOOL needs_control_head = FALSE;
struct sljit_jump *brazero = NULL;
-struct sljit_jump *alt1 = NULL;
-struct sljit_jump *alt2 = NULL;
+struct sljit_jump *next_alt = NULL;
struct sljit_jump *once = NULL;
struct sljit_jump *cond = NULL;
struct sljit_label *rmin_label = NULL;
struct sljit_label *exact_label = NULL;
+struct sljit_put_label *put_label = NULL;
if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
{
@@ -11155,7 +12218,7 @@ else if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)
free_stack(common, 1);
alt_max = 2;
- alt1 = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw));
+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
}
}
else if (has_alternatives)
@@ -11163,21 +12226,15 @@ else if (has_alternatives)
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
free_stack(common, 1);
- if (alt_max > 4)
+ if (alt_max > 3)
{
- /* Table jump if alt_max is greater than 4. */
- next_update_addr = allocate_read_only_data(common, alt_max * sizeof(sljit_uw));
- if (SLJIT_UNLIKELY(next_update_addr == NULL))
- return;
- sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(TMP1), (sljit_sw)next_update_addr);
- add_label_addr(common, next_update_addr++);
+ sljit_emit_ijump(compiler, SLJIT_JUMP, TMP1, 0);
+
+ SLJIT_ASSERT(CURRENT_AS(bracket_backtrack)->u.matching_put_label);
+ sljit_set_put_label(CURRENT_AS(bracket_backtrack)->u.matching_put_label, LABEL());
}
else
- {
- if (alt_max == 4)
- alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw));
- alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw));
- }
+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
}
COMPILE_BACKTRACKINGPATH(current->top);
@@ -11214,7 +12271,7 @@ if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
if (has_alternatives)
{
- alt_count = sizeof(sljit_uw);
+ alt_count = 1;
do
{
current->top = NULL;
@@ -11240,6 +12297,9 @@ if (has_alternatives)
compile_matchingpath(common, ccprev, cc, current);
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
return;
+
+ if (opcode == OP_SCRIPT_RUN)
+ match_script_run_common(common, private_data_ptr, current);
}
/* Instructions after the current alternative is successfully matched. */
@@ -11290,7 +12350,12 @@ if (has_alternatives)
stacksize = match_capture_common(common, stacksize, offset, private_data_ptr);
if (opcode != OP_ONCE)
- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, alt_count);
+ {
+ if (alt_max <= 3)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, alt_count);
+ else
+ put_label = sljit_emit_put_label(compiler, SLJIT_MEM1(STACK_TOP), STACK(stacksize));
+ }
if (offset != 0 && ket == OP_KETRMAX && common->optimized_cbracket[offset >> 1] != 0)
{
@@ -11303,24 +12368,18 @@ if (has_alternatives)
if (opcode != OP_ONCE)
{
- if (alt_max > 4)
- add_label_addr(common, next_update_addr++);
- else
+ if (alt_max <= 3)
{
- if (alt_count != 2 * sizeof(sljit_uw))
- {
- JUMPHERE(alt1);
- if (alt_max == 3 && alt_count == sizeof(sljit_uw))
- alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw));
- }
- else
+ JUMPHERE(next_alt);
+ alt_count++;
+ if (alt_count < alt_max)
{
- JUMPHERE(alt2);
- if (alt_max == 4)
- alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_uw));
+ SLJIT_ASSERT(alt_count == 2 && alt_max == 3);
+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 1);
}
}
- alt_count += sizeof(sljit_uw);
+ else
+ sljit_set_put_label(put_label, LABEL());
}
COMPILE_BACKTRACKINGPATH(current->top);
@@ -11368,7 +12427,7 @@ if (offset != 0)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0);
}
}
-else if (opcode == OP_SBRA || opcode == OP_SCOND)
+else if (opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND)
{
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(0));
free_stack(common, 1);
@@ -11717,6 +12776,7 @@ while (current)
break;
case OP_ONCE:
+ case OP_SCRIPT_RUN:
case OP_BRA:
case OP_CBRA:
case OP_COND:
@@ -11809,11 +12869,10 @@ int private_data_size = get_recurse_data_length(common, ccbegin, ccend, &needs_c
int alt_count, alt_max, local_size;
backtrack_common altbacktrack;
jump_list *match = NULL;
-sljit_uw *next_update_addr = NULL;
-struct sljit_jump *alt1 = NULL;
-struct sljit_jump *alt2 = NULL;
+struct sljit_jump *next_alt = NULL;
struct sljit_jump *accept_exit = NULL;
struct sljit_label *quit;
+struct sljit_put_label *put_label;
/* Recurse captures then. */
common->then_trap = NULL;
@@ -11874,7 +12933,12 @@ while (1)
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);
if (alt_max > 1 || has_accept)
- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, alt_count);
+ {
+ if (alt_max > 3)
+ put_label = sljit_emit_put_label(compiler, SLJIT_MEM1(STACK_TOP), STACK(1));
+ else
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, alt_count);
+ }
add_jump(compiler, &match, JUMP(SLJIT_JUMP));
@@ -11888,7 +12952,7 @@ while (1)
sljit_emit_fast_enter(compiler, TMP1, 0);
if (has_accept)
- accept_exit = CMP(SLJIT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, alt_max * sizeof (sljit_sw));
+ accept_exit = CMP(SLJIT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, -1);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
/* Save return address. */
@@ -11901,44 +12965,30 @@ while (1)
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
free_stack(common, 2);
- if (alt_max > 4)
+ if (alt_max > 3)
{
- /* Table jump if alt_max is greater than 4. */
- next_update_addr = allocate_read_only_data(common, alt_max * sizeof(sljit_uw));
- if (SLJIT_UNLIKELY(next_update_addr == NULL))
- return;
- sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(TMP1), (sljit_sw)next_update_addr);
- add_label_addr(common, next_update_addr++);
+ sljit_emit_ijump(compiler, SLJIT_JUMP, TMP1, 0);
+ sljit_set_put_label(put_label, LABEL());
}
else
- {
- if (alt_max == 4)
- alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw));
- alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw));
- }
+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
}
else
free_stack(common, has_accept ? 2 : 1);
}
- else if (alt_max > 4)
- add_label_addr(common, next_update_addr++);
+ else if (alt_max > 3)
+ sljit_set_put_label(put_label, LABEL());
else
{
- if (alt_count != 2 * sizeof(sljit_uw))
+ JUMPHERE(next_alt);
+ if (alt_count + 1 < alt_max)
{
- JUMPHERE(alt1);
- if (alt_max == 3 && alt_count == sizeof(sljit_uw))
- alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw));
- }
- else
- {
- JUMPHERE(alt2);
- if (alt_max == 4)
- alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_uw));
+ SLJIT_ASSERT(alt_count == 1 && alt_max == 3);
+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 1);
}
}
- alt_count += sizeof(sljit_uw);
+ alt_count++;
compile_backtrackingpath(common, altbacktrack.top);
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
@@ -11999,7 +13049,7 @@ if (common->accept != NULL)
OP1(SLJIT_MOV, TMP2, 0, STACK_TOP, 0);
allocate_stack(common, 2);
- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, alt_count);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, -1);
}
set_jumps(match, LABEL());
@@ -12016,6 +13066,9 @@ sljit_emit_fast_return(compiler, TMP2, 0);
#undef COMPILE_BACKTRACKINGPATH
#undef CURRENT_AS
+#define PUBLIC_JIT_COMPILE_CONFIGURATION_OPTIONS \
+ (PCRE2_JIT_INVALID_UTF)
+
static int jit_compile(pcre2_code *code, sljit_u32 mode)
{
pcre2_real_code *re = (pcre2_real_code *)code;
@@ -12031,7 +13084,6 @@ executable_functions *functions;
void *executable_func;
sljit_uw executable_size;
sljit_uw total_length;
-label_addr_list *label_addr;
struct sljit_label *mainloop_label = NULL;
struct sljit_label *continue_match_label;
struct sljit_label *empty_match_found_label = NULL;
@@ -12046,18 +13098,32 @@ struct sljit_jump *end_anchor_failed = NULL;
SLJIT_ASSERT(tables);
+#if HAS_VIRTUAL_REGISTERS == 1
+SLJIT_ASSERT(sljit_get_register_index(TMP3) < 0 && sljit_get_register_index(ARGUMENTS) < 0 && sljit_get_register_index(RETURN_ADDR) < 0);
+#elif HAS_VIRTUAL_REGISTERS == 0
+SLJIT_ASSERT(sljit_get_register_index(TMP3) >= 0 && sljit_get_register_index(ARGUMENTS) >= 0 && sljit_get_register_index(RETURN_ADDR) >= 0);
+#else
+#error "Invalid value for HAS_VIRTUAL_REGISTERS"
+#endif
+
memset(&rootbacktrack, 0, sizeof(backtrack_common));
memset(common, 0, sizeof(compiler_common));
common->re = re;
common->name_table = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code));
rootbacktrack.cc = common->name_table + re->name_count * re->name_entry_size;
+#ifdef SUPPORT_UNICODE
+common->invalid_utf = (mode & PCRE2_JIT_INVALID_UTF) != 0;
+#endif /* SUPPORT_UNICODE */
+mode &= ~PUBLIC_JIT_COMPILE_CONFIGURATION_OPTIONS;
+
common->start = rootbacktrack.cc;
common->read_only_data_head = NULL;
common->fcc = tables + fcc_offset;
common->lcc = (sljit_sw)(tables + lcc_offset);
common->mode = mode;
common->might_be_empty = re->minlength == 0;
+common->allow_empty_partial = (re->max_lookbehind > 0) || (re->flags & PCRE2_MATCH_EMPTY) != 0;
common->nltype = NLTYPE_FIXED;
switch(re->newline_convention)
{
@@ -12066,6 +13132,7 @@ switch(re->newline_convention)
case PCRE2_NEWLINE_CRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; break;
case PCRE2_NEWLINE_ANY: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;
case PCRE2_NEWLINE_ANYCRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;
+ case PCRE2_NEWLINE_NUL: common->newline = CHAR_NUL; break;
default: return PCRE2_ERROR_INTERNAL;
}
common->nlmax = READ_CHAR_MAX;
@@ -12117,6 +13184,8 @@ if (common->utf)
common->bsr_nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL;
common->bsr_nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL;
}
+else
+ common->invalid_utf = FALSE;
#endif /* SUPPORT_UNICODE */
ccend = bracketend(common->start);
@@ -12321,7 +13390,7 @@ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
sljit_free_compiler(compiler);
SLJIT_FREE(common->optimized_cbracket, allocator_data);
SLJIT_FREE(common->private_data_ptrs, allocator_data);
- PRIV(jit_free_rodata)(common->read_only_data_head, compiler->allocator_data);
+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);
return PCRE2_ERROR_NOMEMORY;
}
@@ -12375,7 +13444,7 @@ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
sljit_free_compiler(compiler);
SLJIT_FREE(common->optimized_cbracket, allocator_data);
SLJIT_FREE(common->private_data_ptrs, allocator_data);
- PRIV(jit_free_rodata)(common->read_only_data_head, compiler->allocator_data);
+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);
return PCRE2_ERROR_NOMEMORY;
}
@@ -12464,7 +13533,7 @@ while (common->currententry != NULL)
sljit_free_compiler(compiler);
SLJIT_FREE(common->optimized_cbracket, allocator_data);
SLJIT_FREE(common->private_data_ptrs, allocator_data);
- PRIV(jit_free_rodata)(common->read_only_data_head, compiler->allocator_data);
+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);
return PCRE2_ERROR_NOMEMORY;
}
flush_stubs(common);
@@ -12557,22 +13626,49 @@ if (common->utfreadchar != NULL)
set_jumps(common->utfreadchar, LABEL());
do_utfreadchar(common);
}
-if (common->utfreadchar16 != NULL)
- {
- set_jumps(common->utfreadchar16, LABEL());
- do_utfreadchar16(common);
- }
if (common->utfreadtype8 != NULL)
{
set_jumps(common->utfreadtype8, LABEL());
do_utfreadtype8(common);
}
+if (common->utfpeakcharback != NULL)
+ {
+ set_jumps(common->utfpeakcharback, LABEL());
+ do_utfpeakcharback(common);
+ }
#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
+#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16
+if (common->utfreadchar_invalid != NULL)
+ {
+ set_jumps(common->utfreadchar_invalid, LABEL());
+ do_utfreadchar_invalid(common);
+ }
+if (common->utfreadnewline_invalid != NULL)
+ {
+ set_jumps(common->utfreadnewline_invalid, LABEL());
+ do_utfreadnewline_invalid(common);
+ }
+if (common->utfmoveback_invalid)
+ {
+ set_jumps(common->utfmoveback_invalid, LABEL());
+ do_utfmoveback_invalid(common);
+ }
+if (common->utfpeakcharback_invalid)
+ {
+ set_jumps(common->utfpeakcharback_invalid, LABEL());
+ do_utfpeakcharback_invalid(common);
+ }
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16 */
if (common->getucd != NULL)
{
set_jumps(common->getucd, LABEL());
do_getucd(common);
}
+if (common->getucdtype != NULL)
+ {
+ set_jumps(common->getucdtype, LABEL());
+ do_getucdtype(common);
+ }
#endif /* SUPPORT_UNICODE */
SLJIT_FREE(common->optimized_cbracket, allocator_data);
@@ -12580,16 +13676,11 @@ SLJIT_FREE(common->private_data_ptrs, allocator_data);
executable_func = sljit_generate_code(compiler);
executable_size = sljit_get_generated_code_size(compiler);
-label_addr = common->label_addrs;
-while (label_addr != NULL)
- {
- *label_addr->update_addr = sljit_get_label_addr(label_addr->label);
- label_addr = label_addr->next;
- }
sljit_free_compiler(compiler);
+
if (executable_func == NULL)
{
- PRIV(jit_free_rodata)(common->read_only_data_head, compiler->allocator_data);
+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);
return PCRE2_ERROR_NOMEMORY;
}
@@ -12604,7 +13695,7 @@ else
/* This case is highly unlikely since we just recently
freed a lot of memory. Not impossible though. */
sljit_free_code(executable_func);
- PRIV(jit_free_rodata)(common->read_only_data_head, compiler->allocator_data);
+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);
return PCRE2_ERROR_NOMEMORY;
}
memset(functions, 0, sizeof(executable_functions));
@@ -12644,22 +13735,17 @@ Returns: 0: success or (*NOJIT) was used
*/
#define PUBLIC_JIT_COMPILE_OPTIONS \
- (PCRE2_JIT_COMPLETE|PCRE2_JIT_PARTIAL_SOFT|PCRE2_JIT_PARTIAL_HARD)
+ (PCRE2_JIT_COMPLETE|PCRE2_JIT_PARTIAL_SOFT|PCRE2_JIT_PARTIAL_HARD|PCRE2_JIT_INVALID_UTF)
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_jit_compile(pcre2_code *code, uint32_t options)
{
-#ifndef SUPPORT_JIT
-
-(void)code;
-(void)options;
-return PCRE2_ERROR_JIT_BADOPTION;
-
-#else /* SUPPORT_JIT */
-
pcre2_real_code *re = (pcre2_real_code *)code;
-executable_functions *functions;
-int result;
+
+#ifdef SUPPORT_JIT
+executable_functions *functions = (executable_functions *)re->executable_jit;
+static int executable_allocator_is_working = 0;
+#endif
if (code == NULL)
return PCRE2_ERROR_NULL;
@@ -12667,27 +13753,98 @@ if (code == NULL)
if ((options & ~PUBLIC_JIT_COMPILE_OPTIONS) != 0)
return PCRE2_ERROR_JIT_BADOPTION;
+/* Support for invalid UTF was first introduced in JIT, with the option
+PCRE2_JIT_INVALID_UTF. Later, support was added to the interpreter, and the
+compile-time option PCRE2_MATCH_INVALID_UTF was created. This is now the
+preferred feature, with the earlier option deprecated. However, for backward
+compatibility, if the earlier option is set, it forces the new option so that
+if JIT matching falls back to the interpreter, there is still support for
+invalid UTF. However, if this function has already been successfully called
+without PCRE2_JIT_INVALID_UTF and without PCRE2_MATCH_INVALID_UTF (meaning that
+non-invalid-supporting JIT code was compiled), give an error.
+
+If in the future support for PCRE2_JIT_INVALID_UTF is withdrawn, the following
+actions are needed:
+
+ 1. Remove the definition from pcre2.h.in and from the list in
+ PUBLIC_JIT_COMPILE_OPTIONS above.
+
+ 2. Replace PCRE2_JIT_INVALID_UTF with a local flag in this module.
+
+ 3. Replace PCRE2_JIT_INVALID_UTF in pcre2_jit_test.c.
+
+ 4. Delete the following short block of code. The setting of "re" and
+ "functions" can be moved into the JIT-only block below, but if that is
+ done, (void)re and (void)functions will be needed in the non-JIT case, to
+ avoid compiler warnings.
+*/
+
+if ((options & PCRE2_JIT_INVALID_UTF) != 0)
+ {
+ if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) == 0)
+ {
+#ifdef SUPPORT_JIT
+ if (functions != NULL) return PCRE2_ERROR_JIT_BADOPTION;
+#endif
+ re->overall_options |= PCRE2_MATCH_INVALID_UTF;
+ }
+ }
+
+/* The above tests are run with and without JIT support. This means that
+PCRE2_JIT_INVALID_UTF propagates back into the regex options (ensuring
+interpreter support) even in the absence of JIT. But now, if there is no JIT
+support, give an error return. */
+
+#ifndef SUPPORT_JIT
+return PCRE2_ERROR_JIT_BADOPTION;
+#else /* SUPPORT_JIT */
+
+/* There is JIT support. Do the necessary. */
+
if ((re->flags & PCRE2_NOJIT) != 0) return 0;
-functions = (executable_functions *)re->executable_jit;
+if (executable_allocator_is_working == 0)
+ {
+ /* Checks whether the executable allocator is working. This check
+ might run multiple times in multi-threaded environments, but the
+ result should not be affected by it. */
+ void *ptr = SLJIT_MALLOC_EXEC(32);
+
+ executable_allocator_is_working = -1;
+
+ if (ptr != NULL)
+ {
+ SLJIT_FREE_EXEC(((sljit_u8*)(ptr)) + SLJIT_EXEC_OFFSET(ptr));
+ executable_allocator_is_working = 1;
+ }
+ }
+
+if (executable_allocator_is_working < 0)
+ return PCRE2_ERROR_NOMEMORY;
+
+if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0)
+ options |= PCRE2_JIT_INVALID_UTF;
if ((options & PCRE2_JIT_COMPLETE) != 0 && (functions == NULL
|| functions->executable_funcs[0] == NULL)) {
- result = jit_compile(code, PCRE2_JIT_COMPLETE);
+ uint32_t excluded_options = (PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_PARTIAL_HARD);
+ int result = jit_compile(code, options & ~excluded_options);
if (result != 0)
return result;
}
if ((options & PCRE2_JIT_PARTIAL_SOFT) != 0 && (functions == NULL
|| functions->executable_funcs[1] == NULL)) {
- result = jit_compile(code, PCRE2_JIT_PARTIAL_SOFT);
+ uint32_t excluded_options = (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_HARD);
+ int result = jit_compile(code, options & ~excluded_options);
if (result != 0)
return result;
}
if ((options & PCRE2_JIT_PARTIAL_HARD) != 0 && (functions == NULL
|| functions->executable_funcs[2] == NULL)) {
- result = jit_compile(code, PCRE2_JIT_PARTIAL_HARD);
+ uint32_t excluded_options = (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT);
+ int result = jit_compile(code, options & ~excluded_options);
if (result != 0)
return result;
}
diff --git a/src/pcre2_jit_match.c b/src/pcre2_jit_match.c
index 5a66545..7e13b8c 100644
--- a/src/pcre2_jit_match.c
+++ b/src/pcre2_jit_match.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -74,7 +74,6 @@ Arguments:
options option bits
match_data points to a match_data block
mcontext points to a match context
- jit_stack points to a JIT stack
Returns: > 0 => success; value is the number of ovector pairs filled
= 0 => success, but ovector is not big enough
@@ -152,8 +151,6 @@ else
jit_stack = NULL;
}
-/* JIT only need two offsets for each ovector entry. Hence
- the last 1/3 of the ovector will never be touched. */
max_oveccount = functions->top_bracket;
if (oveccount > max_oveccount)
@@ -173,7 +170,7 @@ else
if (rc > (int)oveccount)
rc = 0;
match_data->code = re;
-match_data->subject = subject;
+match_data->subject = (rc >= 0 || rc == PCRE2_ERROR_PARTIAL)? subject : NULL;
match_data->rc = rc;
match_data->startchar = arguments.startchar_ptr - subject;
match_data->leftchar = 0;
diff --git a/src/pcre2_jit_neon_inc.h b/src/pcre2_jit_neon_inc.h
new file mode 100644
index 0000000..55b1f32
--- /dev/null
+++ b/src/pcre2_jit_neon_inc.h
@@ -0,0 +1,321 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ This module by Zoltan Herczeg and Sebastian Pop
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+# if defined(FFCS)
+# if defined(FF_UTF)
+# define FF_FUN ffcs_utf
+# else
+# define FF_FUN ffcs
+# endif
+
+# elif defined(FFCS_2)
+# if defined(FF_UTF)
+# define FF_FUN ffcs_2_utf
+# else
+# define FF_FUN ffcs_2
+# endif
+
+# elif defined(FFCS_MASK)
+# if defined(FF_UTF)
+# define FF_FUN ffcs_mask_utf
+# else
+# define FF_FUN ffcs_mask
+# endif
+
+# elif defined(FFCPS_0)
+# if defined (FF_UTF)
+# define FF_FUN ffcps_0_utf
+# else
+# define FF_FUN ffcps_0
+# endif
+
+# elif defined (FFCPS_1)
+# if defined (FF_UTF)
+# define FF_FUN ffcps_1_utf
+# else
+# define FF_FUN ffcps_1
+# endif
+
+# elif defined (FFCPS_DEFAULT)
+# if defined (FF_UTF)
+# define FF_FUN ffcps_default_utf
+# else
+# define FF_FUN ffcps_default
+# endif
+# endif
+
+static sljit_u8* SLJIT_FUNC FF_FUN(sljit_u8 *str_end, sljit_u8 *str_ptr, sljit_uw offs1, sljit_uw offs2, sljit_uw chars)
+#undef FF_FUN
+{
+quad_word qw;
+int_char ic;
+ic.x = chars;
+
+#if defined(FFCS)
+sljit_u8 c1 = ic.c.c1;
+vect_t vc1 = VDUPQ(c1);
+
+#elif defined(FFCS_2)
+sljit_u8 c1 = ic.c.c1;
+vect_t vc1 = VDUPQ(c1);
+sljit_u8 c2 = ic.c.c2;
+vect_t vc2 = VDUPQ(c2);
+
+#elif defined(FFCS_MASK)
+sljit_u8 c1 = ic.c.c1;
+vect_t vc1 = VDUPQ(c1);
+sljit_u8 mask = ic.c.c2;
+vect_t vmask = VDUPQ(mask);
+#endif
+
+#if defined(FFCPS)
+compare_type compare1_type = compare_match1;
+compare_type compare2_type = compare_match1;
+vect_t cmp1a, cmp1b, cmp2a, cmp2b;
+const sljit_u32 diff = IN_UCHARS(offs1 - offs2);
+PCRE2_UCHAR char1a = ic.c.c1;
+PCRE2_UCHAR char2a = ic.c.c3;
+
+# ifdef FFCPS_CHAR1A2A
+cmp1a = VDUPQ(char1a);
+cmp2a = VDUPQ(char2a);
+# else
+PCRE2_UCHAR char1b = ic.c.c2;
+PCRE2_UCHAR char2b = ic.c.c4;
+if (char1a == char1b)
+ cmp1a = VDUPQ(char1a);
+else
+ {
+ sljit_u32 bit1 = char1a ^ char1b;
+ if (is_powerof2(bit1))
+ {
+ compare1_type = compare_match1i;
+ cmp1a = VDUPQ(char1a | bit1);
+ cmp1b = VDUPQ(bit1);
+ }
+ else
+ {
+ compare1_type = compare_match2;
+ cmp1a = VDUPQ(char1a);
+ cmp1b = VDUPQ(char1b);
+ }
+ }
+
+if (char2a == char2b)
+ cmp2a = VDUPQ(char2a);
+else
+ {
+ sljit_u32 bit2 = char2a ^ char2b;
+ if (is_powerof2(bit2))
+ {
+ compare2_type = compare_match1i;
+ cmp2a = VDUPQ(char2a | bit2);
+ cmp2b = VDUPQ(bit2);
+ }
+ else
+ {
+ compare2_type = compare_match2;
+ cmp2a = VDUPQ(char2a);
+ cmp2b = VDUPQ(char2b);
+ }
+ }
+# endif
+
+str_ptr += IN_UCHARS(offs1);
+#endif
+
+#if PCRE2_CODE_UNIT_WIDTH != 8
+vect_t char_mask = VDUPQ(0xff);
+#endif
+
+#if defined(FF_UTF)
+restart:;
+#endif
+
+#if defined(FFCPS)
+sljit_u8 *p1 = str_ptr - diff;
+#endif
+sljit_s32 align_offset = ((uint64_t)str_ptr & 0xf);
+str_ptr = (sljit_u8 *) ((uint64_t)str_ptr & ~0xf);
+vect_t data = VLD1Q(str_ptr);
+#if PCRE2_CODE_UNIT_WIDTH != 8
+data = VANDQ(data, char_mask);
+#endif
+
+#if defined(FFCS)
+vect_t eq = VCEQQ(data, vc1);
+
+#elif defined(FFCS_2)
+vect_t eq1 = VCEQQ(data, vc1);
+vect_t eq2 = VCEQQ(data, vc2);
+vect_t eq = VORRQ(eq1, eq2);
+
+#elif defined(FFCS_MASK)
+vect_t eq = VORRQ(data, vmask);
+eq = VCEQQ(eq, vc1);
+
+#elif defined(FFCPS)
+# if defined(FFCPS_DIFF1)
+vect_t prev_data = data;
+# endif
+
+vect_t data2;
+if (p1 < str_ptr)
+ {
+ data2 = VLD1Q(str_ptr - diff);
+#if PCRE2_CODE_UNIT_WIDTH != 8
+ data2 = VANDQ(data2, char_mask);
+#endif
+ }
+else
+ data2 = shift_left_n_lanes(data, offs1 - offs2);
+
+data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
+data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
+vect_t eq = VANDQ(data, data2);
+#endif
+
+VST1Q(qw.mem, eq);
+/* Ignore matches before the first STR_PTR. */
+if (align_offset < 8)
+ {
+ qw.dw[0] >>= align_offset * 8;
+ if (qw.dw[0])
+ {
+ str_ptr += align_offset + __builtin_ctzll(qw.dw[0]) / 8;
+ goto match;
+ }
+ if (qw.dw[1])
+ {
+ str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
+ goto match;
+ }
+ }
+else
+ {
+ qw.dw[1] >>= (align_offset - 8) * 8;
+ if (qw.dw[1])
+ {
+ str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8;
+ goto match;
+ }
+ }
+str_ptr += 16;
+
+while (str_ptr < str_end)
+ {
+ vect_t orig_data = VLD1Q(str_ptr);
+#if PCRE2_CODE_UNIT_WIDTH != 8
+ orig_data = VANDQ(orig_data, char_mask);
+#endif
+ data = orig_data;
+
+#if defined(FFCS)
+ eq = VCEQQ(data, vc1);
+
+#elif defined(FFCS_2)
+ eq1 = VCEQQ(data, vc1);
+ eq2 = VCEQQ(data, vc2);
+ eq = VORRQ(eq1, eq2);
+
+#elif defined(FFCS_MASK)
+ eq = VORRQ(data, vmask);
+ eq = VCEQQ(eq, vc1);
+#endif
+
+#if defined(FFCPS)
+# if defined (FFCPS_DIFF1)
+ data2 = VEXTQ(prev_data, data, VECTOR_FACTOR - 1);
+# else
+ data2 = VLD1Q(str_ptr - diff);
+# if PCRE2_CODE_UNIT_WIDTH != 8
+ data2 = VANDQ(data2, char_mask);
+# endif
+# endif
+
+# ifdef FFCPS_CHAR1A2A
+ data = VCEQQ(data, cmp1a);
+ data2 = VCEQQ(data2, cmp2a);
+# else
+ data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
+ data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
+# endif
+
+ eq = VANDQ(data, data2);
+#endif
+
+ VST1Q(qw.mem, eq);
+ if (qw.dw[0])
+ str_ptr += __builtin_ctzll(qw.dw[0]) / 8;
+ else if (qw.dw[1])
+ str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
+ else {
+ str_ptr += 16;
+#if defined (FFCPS_DIFF1)
+ prev_data = orig_data;
+#endif
+ continue;
+ }
+
+match:;
+ if (str_ptr >= str_end)
+ /* Failed match. */
+ return NULL;
+
+#if defined(FF_UTF)
+ if (utf_continue(str_ptr + IN_UCHARS(-offs1)))
+ {
+ /* Not a match. */
+ str_ptr += IN_UCHARS(1);
+ goto restart;
+ }
+#endif
+
+ /* Match. */
+#if defined (FFCPS)
+ str_ptr -= IN_UCHARS(offs1);
+#endif
+ return str_ptr;
+ }
+
+/* Failed match. */
+return NULL;
+}
diff --git a/src/pcre2_jit_simd_inc.h b/src/pcre2_jit_simd_inc.h
new file mode 100644
index 0000000..f7d56b2
--- /dev/null
+++ b/src/pcre2_jit_simd_inc.h
@@ -0,0 +1,993 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ This module by Zoltan Herczeg
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND)
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+static struct sljit_jump *jump_if_utf_char_start(struct sljit_compiler *compiler, sljit_s32 reg)
+{
+#if PCRE2_CODE_UNIT_WIDTH == 8
+OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xc0);
+return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0x80);
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xfc00);
+return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00);
+#else
+#error "Unknown code width"
+#endif
+}
+#endif
+
+static sljit_s32 character_to_int32(PCRE2_UCHAR chr)
+{
+sljit_u32 value = chr;
+#if PCRE2_CODE_UNIT_WIDTH == 8
+#define SSE2_COMPARE_TYPE_INDEX 0
+return (sljit_s32)((value << 24) | (value << 16) | (value << 8) | value);
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+#define SSE2_COMPARE_TYPE_INDEX 1
+return (sljit_s32)((value << 16) | value);
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+#define SSE2_COMPARE_TYPE_INDEX 2
+return (sljit_s32)(value);
+#else
+#error "Unsupported unit width"
+#endif
+}
+
+static void load_from_mem_sse2(struct sljit_compiler *compiler, sljit_s32 dst_xmm_reg, sljit_s32 src_general_reg, sljit_s8 offset)
+{
+sljit_u8 instruction[5];
+
+SLJIT_ASSERT(dst_xmm_reg < 8);
+SLJIT_ASSERT(src_general_reg < 8);
+
+/* MOVDQA xmm1, xmm2/m128 */
+instruction[0] = ((sljit_u8)offset & 0xf) == 0 ? 0x66 : 0xf3;
+instruction[1] = 0x0f;
+instruction[2] = 0x6f;
+
+if (offset == 0)
+ {
+ instruction[3] = (dst_xmm_reg << 3) | src_general_reg;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ return;
+ }
+
+instruction[3] = 0x40 | (dst_xmm_reg << 3) | src_general_reg;
+instruction[4] = (sljit_u8)offset;
+sljit_emit_op_custom(compiler, instruction, 5);
+}
+
+typedef enum {
+ sse2_compare_match1,
+ sse2_compare_match1i,
+ sse2_compare_match2,
+} sse2_compare_type;
+
+static void fast_forward_char_pair_sse2_compare(struct sljit_compiler *compiler, sse2_compare_type compare_type,
+ int step, sljit_s32 dst_ind, sljit_s32 cmp1_ind, sljit_s32 cmp2_ind, sljit_s32 tmp_ind)
+{
+sljit_u8 instruction[4];
+instruction[0] = 0x66;
+instruction[1] = 0x0f;
+
+SLJIT_ASSERT(step >= 0 && step <= 3);
+
+if (compare_type != sse2_compare_match2)
+ {
+ if (step == 0)
+ {
+ if (compare_type == sse2_compare_match1i)
+ {
+ /* POR xmm1, xmm2/m128 */
+ /* instruction[0] = 0x66; */
+ /* instruction[1] = 0x0f; */
+ instruction[2] = 0xeb;
+ instruction[3] = 0xc0 | (dst_ind << 3) | cmp2_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ }
+ return;
+ }
+
+ if (step != 2)
+ return;
+
+ /* PCMPEQB/W/D xmm1, xmm2/m128 */
+ /* instruction[0] = 0x66; */
+ /* instruction[1] = 0x0f; */
+ instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
+ instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ return;
+ }
+
+switch (step)
+ {
+ case 0:
+ /* MOVDQA xmm1, xmm2/m128 */
+ /* instruction[0] = 0x66; */
+ /* instruction[1] = 0x0f; */
+ instruction[2] = 0x6f;
+ instruction[3] = 0xc0 | (tmp_ind << 3) | dst_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ return;
+
+ case 1:
+ /* PCMPEQB/W/D xmm1, xmm2/m128 */
+ /* instruction[0] = 0x66; */
+ /* instruction[1] = 0x0f; */
+ instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
+ instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ return;
+
+ case 2:
+ /* PCMPEQB/W/D xmm1, xmm2/m128 */
+ /* instruction[0] = 0x66; */
+ /* instruction[1] = 0x0f; */
+ instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
+ instruction[3] = 0xc0 | (tmp_ind << 3) | cmp2_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ return;
+
+ case 3:
+ /* POR xmm1, xmm2/m128 */
+ /* instruction[0] = 0x66; */
+ /* instruction[1] = 0x0f; */
+ instruction[2] = 0xeb;
+ instruction[3] = 0xc0 | (dst_ind << 3) | tmp_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ return;
+ }
+}
+
+#define JIT_HAS_FAST_FORWARD_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SSE2))
+
+static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)
+{
+DEFINE_COMPILER;
+struct sljit_label *start;
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+struct sljit_label *restart;
+#endif
+struct sljit_jump *quit;
+struct sljit_jump *partial_quit[2];
+sse2_compare_type compare_type = sse2_compare_match1;
+sljit_u8 instruction[8];
+sljit_s32 tmp1_reg_ind = sljit_get_register_index(TMP1);
+sljit_s32 str_ptr_reg_ind = sljit_get_register_index(STR_PTR);
+sljit_s32 data_ind = 0;
+sljit_s32 tmp_ind = 1;
+sljit_s32 cmp1_ind = 2;
+sljit_s32 cmp2_ind = 3;
+sljit_u32 bit = 0;
+int i;
+
+SLJIT_UNUSED_ARG(offset);
+
+if (char1 != char2)
+ {
+ bit = char1 ^ char2;
+ compare_type = sse2_compare_match1i;
+
+ if (!is_powerof2(bit))
+ {
+ bit = 0;
+ compare_type = sse2_compare_match2;
+ }
+ }
+
+partial_quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+if (common->mode == PCRE2_JIT_COMPLETE)
+ add_jump(compiler, &common->failed_match, partial_quit[0]);
+
+/* First part (unaligned start) */
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit));
+
+SLJIT_ASSERT(tmp1_reg_ind < 8);
+
+/* MOVD xmm, r/m32 */
+instruction[0] = 0x66;
+instruction[1] = 0x0f;
+instruction[2] = 0x6e;
+instruction[3] = 0xc0 | (cmp1_ind << 3) | tmp1_reg_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+if (char1 != char2)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));
+
+ /* MOVD xmm, r/m32 */
+ instruction[3] = 0xc0 | (cmp2_ind << 3) | tmp1_reg_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ }
+
+OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
+
+/* PSHUFD xmm1, xmm2/m128, imm8 */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0x70;
+instruction[3] = 0xc0 | (cmp1_ind << 3) | cmp1_ind;
+instruction[4] = 0;
+sljit_emit_op_custom(compiler, instruction, 5);
+
+if (char1 != char2)
+ {
+ /* PSHUFD xmm1, xmm2/m128, imm8 */
+ instruction[3] = 0xc0 | (cmp2_ind << 3) | cmp2_ind;
+ sljit_emit_op_custom(compiler, instruction, 5);
+ }
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+restart = LABEL();
+#endif
+OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);
+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);
+
+load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0);
+for (i = 0; i < 4; i++)
+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
+
+/* PMOVMSKB reg, xmm */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0xd7;
+instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);
+
+quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);
+
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+
+/* Second part (aligned) */
+start = LABEL();
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
+
+partial_quit[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+if (common->mode == PCRE2_JIT_COMPLETE)
+ add_jump(compiler, &common->failed_match, partial_quit[1]);
+
+load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0);
+for (i = 0; i < 4; i++)
+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
+
+/* PMOVMSKB reg, xmm */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0xd7;
+instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);
+
+JUMPHERE(quit);
+
+/* BSF r32, r/m32 */
+instruction[0] = 0x0f;
+instruction[1] = 0xbc;
+instruction[2] = 0xc0 | (tmp1_reg_ind << 3) | tmp1_reg_ind;
+sljit_emit_op_custom(compiler, instruction, 3);
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+
+if (common->mode != PCRE2_JIT_COMPLETE)
+ {
+ JUMPHERE(partial_quit[0]);
+ JUMPHERE(partial_quit[1]);
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
+ CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);
+ }
+else
+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+if (common->utf && offset > 0)
+ {
+ SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);
+
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));
+
+ quit = jump_if_utf_char_start(compiler, TMP1);
+
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+ OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
+ JUMPTO(SLJIT_JUMP, restart);
+
+ JUMPHERE(quit);
+ }
+#endif
+}
+
+#ifndef _WIN64
+
+static SLJIT_INLINE sljit_u32 max_fast_forward_char_pair_offset(void)
+{
+#if PCRE2_CODE_UNIT_WIDTH == 8
+return 15;
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+return 7;
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+return 3;
+#else
+#error "Unsupported unit width"
+#endif
+}
+
+#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SSE2))
+
+static void fast_forward_char_pair_simd(compiler_common *common, sljit_s32 offs1,
+ PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)
+{
+DEFINE_COMPILER;
+sse2_compare_type compare1_type = sse2_compare_match1;
+sse2_compare_type compare2_type = sse2_compare_match1;
+sljit_u32 bit1 = 0;
+sljit_u32 bit2 = 0;
+sljit_u32 diff = IN_UCHARS(offs1 - offs2);
+sljit_s32 tmp1_reg_ind = sljit_get_register_index(TMP1);
+sljit_s32 tmp2_reg_ind = sljit_get_register_index(TMP2);
+sljit_s32 str_ptr_reg_ind = sljit_get_register_index(STR_PTR);
+sljit_s32 data1_ind = 0;
+sljit_s32 data2_ind = 1;
+sljit_s32 tmp1_ind = 2;
+sljit_s32 tmp2_ind = 3;
+sljit_s32 cmp1a_ind = 4;
+sljit_s32 cmp1b_ind = 5;
+sljit_s32 cmp2a_ind = 6;
+sljit_s32 cmp2b_ind = 7;
+struct sljit_label *start;
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+struct sljit_label *restart;
+#endif
+struct sljit_jump *jump[2];
+sljit_u8 instruction[8];
+int i;
+
+SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);
+SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_offset()));
+SLJIT_ASSERT(tmp1_reg_ind < 8 && tmp2_reg_ind == 1);
+
+/* Initialize. */
+if (common->match_end_ptr != 0)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));
+
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);
+ CMOV(SLJIT_LESS, STR_END, TMP1, 0);
+ }
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));
+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
+/* MOVD xmm, r/m32 */
+instruction[0] = 0x66;
+instruction[1] = 0x0f;
+instruction[2] = 0x6e;
+
+if (char1a == char1b)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a));
+else
+ {
+ bit1 = char1a ^ char1b;
+ if (is_powerof2(bit1))
+ {
+ compare1_type = sse2_compare_match1i;
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a | bit1));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit1));
+ }
+ else
+ {
+ compare1_type = sse2_compare_match2;
+ bit1 = 0;
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char1b));
+ }
+ }
+
+instruction[3] = 0xc0 | (cmp1a_ind << 3) | tmp1_reg_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+if (char1a != char1b)
+ {
+ instruction[3] = 0xc0 | (cmp1b_ind << 3) | tmp2_reg_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ }
+
+if (char2a == char2b)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));
+else
+ {
+ bit2 = char2a ^ char2b;
+ if (is_powerof2(bit2))
+ {
+ compare2_type = sse2_compare_match1i;
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a | bit2));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit2));
+ }
+ else
+ {
+ compare2_type = sse2_compare_match2;
+ bit2 = 0;
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char2b));
+ }
+ }
+
+instruction[3] = 0xc0 | (cmp2a_ind << 3) | tmp1_reg_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+if (char2a != char2b)
+ {
+ instruction[3] = 0xc0 | (cmp2b_ind << 3) | tmp2_reg_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ }
+
+/* PSHUFD xmm1, xmm2/m128, imm8 */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0x70;
+instruction[4] = 0;
+
+instruction[3] = 0xc0 | (cmp1a_ind << 3) | cmp1a_ind;
+sljit_emit_op_custom(compiler, instruction, 5);
+
+if (char1a != char1b)
+ {
+ instruction[3] = 0xc0 | (cmp1b_ind << 3) | cmp1b_ind;
+ sljit_emit_op_custom(compiler, instruction, 5);
+ }
+
+instruction[3] = 0xc0 | (cmp2a_ind << 3) | cmp2a_ind;
+sljit_emit_op_custom(compiler, instruction, 5);
+
+if (char2a != char2b)
+ {
+ instruction[3] = 0xc0 | (cmp2b_ind << 3) | cmp2b_ind;
+ sljit_emit_op_custom(compiler, instruction, 5);
+ }
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+restart = LABEL();
+#endif
+
+OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, diff);
+OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
+OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);
+
+load_from_mem_sse2(compiler, data1_ind, str_ptr_reg_ind, 0);
+
+jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_PTR, 0);
+
+load_from_mem_sse2(compiler, data2_ind, str_ptr_reg_ind, -(sljit_s8)diff);
+jump[1] = JUMP(SLJIT_JUMP);
+
+JUMPHERE(jump[0]);
+
+/* MOVDQA xmm1, xmm2/m128 */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0x6f;
+instruction[3] = 0xc0 | (data2_ind << 3) | data1_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+/* PSLLDQ xmm1, imm8 */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0x73;
+instruction[3] = 0xc0 | (7 << 3) | data2_ind;
+instruction[4] = diff;
+sljit_emit_op_custom(compiler, instruction, 5);
+
+JUMPHERE(jump[1]);
+
+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);
+
+for (i = 0; i < 4; i++)
+ {
+ fast_forward_char_pair_sse2_compare(compiler, compare2_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp2_ind);
+ fast_forward_char_pair_sse2_compare(compiler, compare1_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind);
+ }
+
+/* PAND xmm1, xmm2/m128 */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0xdb;
+instruction[3] = 0xc0 | (data1_ind << 3) | data2_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+/* PMOVMSKB reg, xmm */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0xd7;
+instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | 0;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+/* Ignore matches before the first STR_PTR. */
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);
+
+jump[0] = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);
+
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+
+/* Main loop. */
+start = LABEL();
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
+load_from_mem_sse2(compiler, data1_ind, str_ptr_reg_ind, 0);
+load_from_mem_sse2(compiler, data2_ind, str_ptr_reg_ind, -(sljit_s8)diff);
+
+for (i = 0; i < 4; i++)
+ {
+ fast_forward_char_pair_sse2_compare(compiler, compare1_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp2_ind);
+ fast_forward_char_pair_sse2_compare(compiler, compare2_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp1_ind);
+ }
+
+/* PAND xmm1, xmm2/m128 */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0xdb;
+instruction[3] = 0xc0 | (data1_ind << 3) | data2_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+/* PMOVMSKB reg, xmm */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0xd7;
+instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | 0;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);
+
+JUMPHERE(jump[0]);
+
+/* BSF r32, r/m32 */
+instruction[0] = 0x0f;
+instruction[1] = 0xbc;
+instruction[2] = 0xc0 | (tmp1_reg_ind << 3) | tmp1_reg_ind;
+sljit_emit_op_custom(compiler, instruction, 3);
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+
+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
+if (common->match_end_ptr != 0)
+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+if (common->utf)
+ {
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offs1));
+
+ jump[0] = jump_if_utf_char_start(compiler, TMP1);
+
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, restart);
+
+ add_jump(compiler, &common->failed_match, JUMP(SLJIT_JUMP));
+
+ JUMPHERE(jump[0]);
+ }
+#endif
+
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));
+
+if (common->match_end_ptr != 0)
+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
+}
+
+#endif /* !_WIN64 */
+
+#undef SSE2_COMPARE_TYPE_INDEX
+
+#endif /* SLJIT_CONFIG_X86 && !SUPPORT_VALGRIND */
+
+#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64 && (defined __ARM_NEON || defined __ARM_NEON__))
+
+#include
+
+typedef union {
+ unsigned int x;
+ struct { unsigned char c1, c2, c3, c4; } c;
+} int_char;
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+static SLJIT_INLINE int utf_continue(sljit_u8 *s)
+{
+#if PCRE2_CODE_UNIT_WIDTH == 8
+return (*s & 0xc0) == 0x80;
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+return (*s & 0xfc00) == 0xdc00;
+#else
+#error "Unknown code width"
+#endif
+}
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */
+
+#if PCRE2_CODE_UNIT_WIDTH == 8
+# define VECTOR_FACTOR 16
+# define vect_t uint8x16_t
+# define VLD1Q(X) vld1q_u8((sljit_u8 *)(X))
+# define VCEQQ vceqq_u8
+# define VORRQ vorrq_u8
+# define VST1Q vst1q_u8
+# define VDUPQ vdupq_n_u8
+# define VEXTQ vextq_u8
+# define VANDQ vandq_u8
+typedef union {
+ uint8_t mem[16];
+ uint64_t dw[2];
+} quad_word;
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+# define VECTOR_FACTOR 8
+# define vect_t uint16x8_t
+# define VLD1Q(X) vld1q_u16((sljit_u16 *)(X))
+# define VCEQQ vceqq_u16
+# define VORRQ vorrq_u16
+# define VST1Q vst1q_u16
+# define VDUPQ vdupq_n_u16
+# define VEXTQ vextq_u16
+# define VANDQ vandq_u16
+typedef union {
+ uint16_t mem[8];
+ uint64_t dw[2];
+} quad_word;
+#else
+# define VECTOR_FACTOR 4
+# define vect_t uint32x4_t
+# define VLD1Q(X) vld1q_u32((sljit_u32 *)(X))
+# define VCEQQ vceqq_u32
+# define VORRQ vorrq_u32
+# define VST1Q vst1q_u32
+# define VDUPQ vdupq_n_u32
+# define VEXTQ vextq_u32
+# define VANDQ vandq_u32
+typedef union {
+ uint32_t mem[4];
+ uint64_t dw[2];
+} quad_word;
+#endif
+
+#define FFCS
+#include "pcre2_jit_neon_inc.h"
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+# define FF_UTF
+# include "pcre2_jit_neon_inc.h"
+# undef FF_UTF
+#endif
+#undef FFCS
+
+#define FFCS_2
+#include "pcre2_jit_neon_inc.h"
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+# define FF_UTF
+# include "pcre2_jit_neon_inc.h"
+# undef FF_UTF
+#endif
+#undef FFCS_2
+
+#define FFCS_MASK
+#include "pcre2_jit_neon_inc.h"
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+# define FF_UTF
+# include "pcre2_jit_neon_inc.h"
+# undef FF_UTF
+#endif
+#undef FFCS_MASK
+
+#define JIT_HAS_FAST_FORWARD_CHAR_SIMD 1
+
+static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)
+{
+DEFINE_COMPILER;
+int_char ic;
+struct sljit_jump *partial_quit;
+/* Save temporary registers. */
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP3, 0);
+
+/* Prepare function arguments */
+OP1(SLJIT_MOV, SLJIT_R0, 0, STR_END, 0);
+OP1(SLJIT_MOV, SLJIT_R1, 0, STR_PTR, 0);
+OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, offset);
+
+if (char1 == char2)
+ {
+ ic.c.c1 = char1;
+ ic.c.c2 = char2;
+ OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ if (common->utf && offset > 0)
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_utf));
+ else
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs));
+#else
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs));
+#endif
+ }
+else
+ {
+ PCRE2_UCHAR mask = char1 ^ char2;
+ if (is_powerof2(mask))
+ {
+ ic.c.c1 = char1 | mask;
+ ic.c.c2 = mask;
+ OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ if (common->utf && offset > 0)
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_mask_utf));
+ else
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_mask));
+#else
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_mask));
+#endif
+ }
+ else
+ {
+ ic.c.c1 = char1;
+ ic.c.c2 = char2;
+ OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ if (common->utf && offset > 0)
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_2_utf));
+ else
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_2));
+#else
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_2));
+#endif
+ }
+ }
+/* Restore registers. */
+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
+OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
+
+/* Check return value. */
+partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
+if (common->mode == PCRE2_JIT_COMPLETE)
+ add_jump(compiler, &common->failed_match, partial_quit);
+
+/* Fast forward STR_PTR to the result of memchr. */
+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
+
+if (common->mode != PCRE2_JIT_COMPLETE)
+ JUMPHERE(partial_quit);
+}
+
+typedef enum {
+ compare_match1,
+ compare_match1i,
+ compare_match2,
+} compare_type;
+
+static inline vect_t fast_forward_char_pair_compare(compare_type ctype, vect_t dst, vect_t cmp1, vect_t cmp2)
+{
+if (ctype == compare_match2)
+ {
+ vect_t tmp = dst;
+ dst = VCEQQ(dst, cmp1);
+ tmp = VCEQQ(tmp, cmp2);
+ dst = VORRQ(dst, tmp);
+ return dst;
+ }
+
+if (ctype == compare_match1i)
+ dst = VORRQ(dst, cmp2);
+dst = VCEQQ(dst, cmp1);
+return dst;
+}
+
+static SLJIT_INLINE sljit_u32 max_fast_forward_char_pair_offset(void)
+{
+#if PCRE2_CODE_UNIT_WIDTH == 8
+return 15;
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+return 7;
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+return 3;
+#else
+#error "Unsupported unit width"
+#endif
+}
+
+/* ARM doesn't have a shift left across lanes. */
+static SLJIT_INLINE vect_t shift_left_n_lanes(vect_t a, sljit_u8 n)
+{
+vect_t zero = VDUPQ(0);
+SLJIT_ASSERT(0 < n && n < VECTOR_FACTOR);
+/* VEXTQ takes an immediate as last argument. */
+#define C(X) case X: return VEXTQ(zero, a, VECTOR_FACTOR - X);
+switch (n)
+ {
+ C(1); C(2); C(3);
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ C(4); C(5); C(6); C(7);
+# if PCRE2_CODE_UNIT_WIDTH != 16
+ C(8); C(9); C(10); C(11); C(12); C(13); C(14); C(15);
+# endif
+#endif
+ default:
+ /* Based on the ASSERT(0 < n && n < VECTOR_FACTOR) above, this won't
+ happen. The return is still here for compilers to not warn. */
+ return a;
+ }
+}
+
+#define FFCPS
+#define FFCPS_DIFF1
+#define FFCPS_CHAR1A2A
+
+#define FFCPS_0
+#include "pcre2_jit_neon_inc.h"
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+# define FF_UTF
+# include "pcre2_jit_neon_inc.h"
+# undef FF_UTF
+#endif
+#undef FFCPS_0
+
+#undef FFCPS_CHAR1A2A
+
+#define FFCPS_1
+#include "pcre2_jit_neon_inc.h"
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+# define FF_UTF
+# include "pcre2_jit_neon_inc.h"
+# undef FF_UTF
+#endif
+#undef FFCPS_1
+
+#undef FFCPS_DIFF1
+
+#define FFCPS_DEFAULT
+#include "pcre2_jit_neon_inc.h"
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+# define FF_UTF
+# include "pcre2_jit_neon_inc.h"
+# undef FF_UTF
+#endif
+#undef FFCPS
+
+#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD 1
+
+static void fast_forward_char_pair_simd(compiler_common *common, sljit_s32 offs1,
+ PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)
+{
+DEFINE_COMPILER;
+sljit_u32 diff = IN_UCHARS(offs1 - offs2);
+struct sljit_jump *partial_quit;
+int_char ic;
+SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);
+SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_offset()));
+SLJIT_ASSERT(compiler->scratches == 5);
+
+/* Save temporary register STR_PTR. */
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);
+
+/* Prepare arguments for the function call. */
+if (common->match_end_ptr == 0)
+ OP1(SLJIT_MOV, SLJIT_R0, 0, STR_END, 0);
+else
+ {
+ OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
+ OP2(SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));
+
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, STR_END, 0, SLJIT_R0, 0);
+ CMOV(SLJIT_LESS, SLJIT_R0, STR_END, 0);
+ }
+
+OP1(SLJIT_MOV, SLJIT_R1, 0, STR_PTR, 0);
+OP1(SLJIT_MOV_S32, SLJIT_R2, 0, SLJIT_IMM, offs1);
+OP1(SLJIT_MOV_S32, SLJIT_R3, 0, SLJIT_IMM, offs2);
+ic.c.c1 = char1a;
+ic.c.c2 = char1b;
+ic.c.c3 = char2a;
+ic.c.c4 = char2b;
+OP1(SLJIT_MOV_U32, SLJIT_R4, 0, SLJIT_IMM, ic.x);
+
+if (diff == 1) {
+ if (char1a == char1b && char2a == char2b) {
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ if (common->utf)
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_0_utf));
+ else
+#endif
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_0));
+ } else {
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ if (common->utf)
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_1_utf));
+ else
+#endif
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_1));
+ }
+} else {
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ if (common->utf)
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_default_utf));
+ else
+#endif
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_default));
+}
+
+/* Restore STR_PTR register. */
+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
+
+/* Check return value. */
+partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
+add_jump(compiler, &common->failed_match, partial_quit);
+
+/* Fast forward STR_PTR to the result of memchr. */
+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
+
+JUMPHERE(partial_quit);
+}
+
+#endif /* SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64 */
diff --git a/src/pcre2_jit_test.c b/src/pcre2_jit_test.c
index a28e9a0..a9b3880 100644
--- a/src/pcre2_jit_test.c
+++ b/src/pcre2_jit_test.c
@@ -93,6 +93,9 @@ POSSIBILITY OF SUCH DAMAGE.
*/
static int regression_tests(void);
+static int invalid_utf8_regression_tests(void);
+static int invalid_utf16_regression_tests(void);
+static int invalid_utf32_regression_tests(void);
int main(void)
{
@@ -108,7 +111,10 @@ int main(void)
printf("JIT must be enabled to run pcre_jit_test\n");
return 1;
}
- return regression_tests();
+ return regression_tests()
+ | invalid_utf8_regression_tests()
+ | invalid_utf16_regression_tests()
+ | invalid_utf32_regression_tests();
}
/* --------------------------------------------------------------------------------------- */
@@ -184,12 +190,14 @@ static struct regression_test_case regression_test_cases[] = {
{ CM, A, 0, 0, "\\Ca", "CDA" },
{ M, A, 0, 0 | F_NOMATCH, "\\Cx", "cda" },
{ CM, A, 0, 0 | F_NOMATCH, "\\Cx", "CDA" },
-#endif
+#endif /* !NEVER_BACKSLASH_C */
{ CMUP, A, 0, 0, "\xf0\x90\x90\x80\xf0\x90\x90\xa8", "\xf0\x90\x90\xa8\xf0\x90\x90\x80" },
{ CMUP, A, 0, 0, "\xf0\x90\x90\x80{2}", "\xf0\x90\x90\x80#\xf0\x90\x90\xa8\xf0\x90\x90\x80" },
{ CMUP, A, 0, 0, "\xf0\x90\x90\xa8{2}", "\xf0\x90\x90\x80#\xf0\x90\x90\xa8\xf0\x90\x90\x80" },
{ CMUP, A, 0, 0, "\xe1\xbd\xb8\xe1\xbf\xb8", "\xe1\xbf\xb8\xe1\xbd\xb8" },
{ M, A, 0, 0, "[3-57-9]", "5" },
+ { PCRE2_AUTO_CALLOUT, A, 0, 0, "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890" },
/* Assertions. */
{ MU, A, 0, 0, "\\b[^A]", "A_B#" },
@@ -262,6 +270,9 @@ static struct regression_test_case regression_test_cases[] = {
{ MU, A, 0, 0, "\xc6\x82\xc6\x82|\xc7\x83\xc7\x83|\xc8\x84\xc8\x84", "\xf1\x83\x82\x82\xc8\x84\xc8\x84" },
{ U, A, 0, 0, "\xe1\x81\x80|\xe2\x82\x80|\xe4\x84\x80", "\xdf\xbf\xc2\x80\xe4\x84\x80" },
{ U, A, 0, 0, "(?:\xe1\x81\x80|\xe2\x82\x80|\xe4\x84\x80)#", "\xdf\xbf\xc2\x80#\xe4\x84\x80#" },
+ { CM, A, 0, 0, "ab|cd", "CD" },
+ { CM, A, 0, 0, "a1277|a1377|bX487", "bx487" },
+ { CM, A, 0, 0, "a1277|a1377|bx487", "bX487" },
/* Greedy and non-greedy ? operators. */
{ MU, A, 0, 0, "(?:a)?a", "laab" },
@@ -374,6 +385,7 @@ static struct regression_test_case regression_test_cases[] = {
{ MU, A, 0, 0, "[^\\x{801}-\\x{fffe}]+", "\xe0\xa0\x81#\xc3\xa9\xf0\x90\x90\x80\xe0\xa0\x80\xef\xbf\xbf\xef\xbf\xbe" },
{ MU, A, 0, 0, "[\\x{10001}-\\x{10fffe}]+", "#\xc3\xa9\xe2\xb1\xa5\xf0\x90\x80\x80\xf0\x90\x80\x81\xf4\x8f\xbf\xbe\xf4\x8f\xbf\xbf" },
{ MU, A, 0, 0, "[^\\x{10001}-\\x{10fffe}]+", "\xf0\x90\x80\x81#\xc3\xa9\xe2\xb1\xa5\xf0\x90\x80\x80\xf4\x8f\xbf\xbf\xf4\x8f\xbf\xbe" },
+ { CMU, A, 0, 0 | F_NOMATCH, "^[\\x{0100}-\\x{017f}]", " " },
/* Unicode properties. */
{ MUP, A, 0, 0, "[1-5\xc3\xa9\\w]", "\xc3\xa1_" },
@@ -858,6 +870,18 @@ static struct regression_test_case regression_test_cases[] = {
{ MU, A, 0, 0, "(a(*COMMIT)(?:b|bb)|c(*ACCEPT)d|dd){0}_(?1)+_", "_ax_ _cd_ _abbb_ _abcd_ _abbcdd_" },
{ MU, A, 0, 0, "((.)(?:.|(*COMMIT)\\2{3}(*ACCEPT).*|.*)){0}_(?1){0,4}_", "_aaaabbbbccccddd_ _aaaabbbbccccdddd_" },
+#ifdef SUPPORT_UNICODE
+ /* Script runs and iterations. */
+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)*#", "!abcdefghijklmno!abcdefghijklmno!abcdef#" },
+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)+#", "!abcdefghijklmno!abcdefghijklmno!abcdef#" },
+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)*?#", "!abcdefghijklmno!abcdefghijklmno!abcdef#" },
+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)+?#", "!abcdefghijklmno!abcdefghijklmno!abcdef#" },
+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)*+#", "!abcdefghijklmno!abcdefghijklmno!abcdef#" },
+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)++#", "!abcdefghijklmno!abcdefghijklmno!abcdef#" },
+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)?#", "!ab!abc!ab!ab#" },
+ { MU, A, 0, 0, "!(*sr:\\w\\w|\\w\\w\\w)??#", "!ab!abc!ab!ab#" },
+#endif
+
/* Deep recursion. */
{ MU, A, 0, 0, "((((?:(?:(?:\\w)+)?)*|(?>\\w)+?)+|(?>\\w)?\?)*)?\\s", "aaaaa+ " },
{ MU, A, 0, 0, "(?:((?:(?:(?:\\w*?)+)??|(?>\\w)?|\\w*+)*)+)+?\\s", "aa+ " },
@@ -1163,7 +1187,7 @@ static int regression_tests(void)
#elif defined SUPPORT_PCRE2_32
PCRE2_UCHAR32 cpu_info[128];
#endif
-#if defined SUPPORT_UTF && ((defined(SUPPORT_PCRE2_8) + defined(SUPPORT_PCRE2_16) + defined(SUPPORT_PCRE2_32)) >= 2)
+#if defined SUPPORT_UNICODE && ((defined(SUPPORT_PCRE2_8) + defined(SUPPORT_PCRE2_16) + defined(SUPPORT_PCRE2_32)) >= 2)
int return_value;
#endif
@@ -1331,9 +1355,8 @@ static int regression_tests(void)
ovector8_2[i] = -2;
}
if (re8) {
- (void)pcre2_set_match_limit_8(mcontext8, 10000000);
return_value8[1] = pcre2_match_8(re8, (PCRE2_SPTR8)current->input, strlen(current->input),
- current->start_offset & OFFSET_MASK, current->match_options, mdata8_2, mcontext8);
+ current->start_offset & OFFSET_MASK, current->match_options, mdata8_2, NULL);
if (pcre2_jit_compile_8(re8, jit_compile_mode)) {
printf("\n8 bit: JIT compiler does not support \"%s\"\n", current->pattern);
@@ -1376,9 +1399,8 @@ static int regression_tests(void)
else
length16 = copy_char8_to_char16((PCRE2_SPTR8)current->input, regtest_buf16, REGTEST_MAX_LENGTH16);
- (void)pcre2_set_match_limit_16(mcontext16, 10000000);
return_value16[1] = pcre2_match_16(re16, regtest_buf16, length16,
- current->start_offset & OFFSET_MASK, current->match_options, mdata16_2, mcontext16);
+ current->start_offset & OFFSET_MASK, current->match_options, mdata16_2, NULL);
if (pcre2_jit_compile_16(re16, jit_compile_mode)) {
printf("\n16 bit: JIT compiler does not support \"%s\"\n", current->pattern);
@@ -1421,9 +1443,8 @@ static int regression_tests(void)
else
length32 = copy_char8_to_char32((PCRE2_SPTR8)current->input, regtest_buf32, REGTEST_MAX_LENGTH32);
- (void)pcre2_set_match_limit_32(mcontext32, 10000000);
return_value32[1] = pcre2_match_32(re32, regtest_buf32, length32,
- current->start_offset & OFFSET_MASK, current->match_options, mdata32_2, mcontext32);
+ current->start_offset & OFFSET_MASK, current->match_options, mdata32_2, NULL);
if (pcre2_jit_compile_32(re32, jit_compile_mode)) {
printf("\n32 bit: JIT compiler does not support \"%s\"\n", current->pattern);
@@ -1451,7 +1472,7 @@ static int regression_tests(void)
is_successful = 1;
if (!(current->start_offset & F_DIFF)) {
-#if defined SUPPORT_UTF && ((defined(SUPPORT_PCRE2_8) + defined(SUPPORT_PCRE2_16) + defined(SUPPORT_PCRE2_32)) >= 2)
+#if defined SUPPORT_UNICODE && ((defined(SUPPORT_PCRE2_8) + defined(SUPPORT_PCRE2_16) + defined(SUPPORT_PCRE2_32)) >= 2)
if (!(current->start_offset & F_FORCECONV)) {
/* All results must be the same. */
@@ -1500,8 +1521,8 @@ static int regression_tests(void)
is_successful = 0;
} else
#endif
- if (return_value >= 0 || return_value == PCRE_ERROR_PARTIAL) {
- if (return_value == PCRE_ERROR_PARTIAL) {
+ if (return_value >= 0 || return_value == PCRE2_ERROR_PARTIAL) {
+ if (return_value == PCRE2_ERROR_PARTIAL) {
return_value = 2;
} else {
return_value *= 2;
@@ -1516,20 +1537,20 @@ static int regression_tests(void)
return_value32[0] = return_value;
#endif
/* Transform back the results. */
- if (current->flags & PCRE_UTF8) {
+ if (current->compile_options & PCRE2_UTF) {
#ifdef SUPPORT_PCRE2_16
for (i = 0; i < return_value; ++i) {
- if (ovector16_1[i] >= 0)
+ if (ovector16_1[i] != PCRE2_UNSET)
ovector16_1[i] = regtest_offsetmap16[ovector16_1[i]];
- if (ovector16_2[i] >= 0)
+ if (ovector16_2[i] != PCRE2_UNSET)
ovector16_2[i] = regtest_offsetmap16[ovector16_2[i]];
}
#endif
#ifdef SUPPORT_PCRE2_32
for (i = 0; i < return_value; ++i) {
- if (ovector32_1[i] >= 0)
+ if (ovector32_1[i] != PCRE2_UNSET)
ovector32_1[i] = regtest_offsetmap32[ovector32_1[i]];
- if (ovector32_2[i] >= 0)
+ if (ovector32_2[i] != PCRE2_UNSET)
ovector32_2[i] = regtest_offsetmap32[ovector32_2[i]];
}
#endif
@@ -1539,7 +1560,7 @@ static int regression_tests(void)
#if defined SUPPORT_PCRE2_8 && defined SUPPORT_PCRE2_16
if (ovector8_1[i] != ovector8_2[i] || ovector8_1[i] != ovector16_1[i] || ovector8_1[i] != ovector16_2[i]) {
printf("\n8 and 16 bit: Ovector[%d] value differs(J8:%d,I8:%d,J16:%d,I16:%d): [%d] '%s' @ '%s' \n",
- i, ovector8_1[i], ovector8_2[i], ovector16_1[i], ovector16_2[i],
+ i, (int)ovector8_1[i], (int)ovector8_2[i], (int)ovector16_1[i], (int)ovector16_2[i],
total, current->pattern, current->input);
is_successful = 0;
}
@@ -1547,7 +1568,7 @@ static int regression_tests(void)
#if defined SUPPORT_PCRE2_8 && defined SUPPORT_PCRE2_32
if (ovector8_1[i] != ovector8_2[i] || ovector8_1[i] != ovector32_1[i] || ovector8_1[i] != ovector32_2[i]) {
printf("\n8 and 32 bit: Ovector[%d] value differs(J8:%d,I8:%d,J32:%d,I32:%d): [%d] '%s' @ '%s' \n",
- i, ovector8_1[i], ovector8_2[i], ovector32_1[i], ovector32_2[i],
+ i, (int)ovector8_1[i], (int)ovector8_2[i], (int)ovector32_1[i], (int)ovector32_2[i],
total, current->pattern, current->input);
is_successful = 0;
}
@@ -1555,7 +1576,7 @@ static int regression_tests(void)
#if defined SUPPORT_PCRE2_16 && defined SUPPORT_PCRE2_32
if (ovector16_1[i] != ovector16_2[i] || ovector16_1[i] != ovector32_1[i] || ovector16_1[i] != ovector32_2[i]) {
printf("\n16 and 32 bit: Ovector[%d] value differs(J16:%d,I16:%d,J32:%d,I32:%d): [%d] '%s' @ '%s' \n",
- i, ovector16_1[i], ovector16_2[i], ovector32_1[i], ovector32_2[i],
+ i, (int)ovector16_1[i], (int)ovector16_2[i], (int)ovector32_1[i], (int)ovector32_2[i],
total, current->pattern, current->input);
is_successful = 0;
}
@@ -1751,4 +1772,708 @@ static int regression_tests(void)
}
}
+#if defined SUPPORT_UNICODE
+
+static int check_invalid_utf_result(int pattern_index, const char *type, int result,
+ int match_start, int match_end, PCRE2_SIZE *ovector)
+{
+ if (match_start < 0) {
+ if (result != -1) {
+ printf("Pattern[%d] %s result is not -1.\n", pattern_index, type);
+ return 1;
+ }
+ return 0;
+ }
+
+ if (result <= 0) {
+ printf("Pattern[%d] %s result (%d) is not greater than 0.\n", pattern_index, type, result);
+ return 1;
+ }
+
+ if (ovector[0] != (PCRE2_SIZE)match_start) {
+ printf("Pattern[%d] %s ovector[0] is unexpected (%d instead of %d)\n",
+ pattern_index, type, (int)ovector[0], match_start);
+ return 1;
+ }
+
+ if (ovector[1] != (PCRE2_SIZE)match_end) {
+ printf("Pattern[%d] %s ovector[1] is unexpected (%d instead of %d)\n",
+ pattern_index, type, (int)ovector[1], match_end);
+ return 1;
+ }
+
+ return 0;
+}
+
+#endif /* SUPPORT_UNICODE */
+
+#if defined SUPPORT_UNICODE && defined SUPPORT_PCRE2_8
+
+#define UDA (PCRE2_UTF | PCRE2_DOTALL | PCRE2_ANCHORED)
+#define CI (PCRE2_JIT_COMPLETE | PCRE2_JIT_INVALID_UTF)
+#define CPI (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_INVALID_UTF)
+
+struct invalid_utf8_regression_test_case {
+ int compile_options;
+ int jit_compile_options;
+ int start_offset;
+ int skip_left;
+ int skip_right;
+ int match_start;
+ int match_end;
+ const char *pattern[2];
+ const char *input;
+};
+
+static struct invalid_utf8_regression_test_case invalid_utf8_regression_test_cases[] = {
+ { UDA, CI, 0, 0, 0, 0, 4, { ".", NULL }, "\xf4\x8f\xbf\xbf" },
+ { UDA, CI, 0, 0, 0, 0, 4, { ".", NULL }, "\xf0\x90\x80\x80" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xf4\x90\x80\x80" },
+ { UDA, CI, 0, 0, 1, -1, -1, { ".", NULL }, "\xf4\x8f\xbf\xbf" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xf0\x90\x80\x7f" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xf0\x90\x80\xc0" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xf0\x8f\xbf\xbf" },
+ { UDA, CI, 0, 0, 0, 0, 3, { ".", NULL }, "\xef\xbf\xbf#" },
+ { UDA, CI, 0, 0, 0, 0, 3, { ".", NULL }, "\xef\xbf\xbf" },
+ { UDA, CI, 0, 0, 0, 0, 3, { ".", NULL }, "\xe0\xa0\x80#" },
+ { UDA, CI, 0, 0, 0, 0, 3, { ".", NULL }, "\xe0\xa0\x80" },
+ { UDA, CI, 0, 0, 2, -1, -1, { ".", NULL }, "\xef\xbf\xbf#" },
+ { UDA, CI, 0, 0, 1, -1, -1, { ".", NULL }, "\xef\xbf\xbf" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xef\xbf\x7f#" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xef\xbf\xc0" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xe0\x9f\xbf#" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xe0\x9f\xbf" },
+ { UDA, CI, 0, 0, 0, 0, 3, { ".", NULL }, "\xed\x9f\xbf#" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xed\xa0\x80#" },
+ { UDA, CI, 0, 0, 0, 0, 3, { ".", NULL }, "\xee\x80\x80#" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xed\xbf\xbf#" },
+ { UDA, CI, 0, 0, 0, 0, 2, { ".", NULL }, "\xdf\xbf##" },
+ { UDA, CI, 0, 0, 0, 0, 2, { ".", NULL }, "\xdf\xbf#" },
+ { UDA, CI, 0, 0, 0, 0, 2, { ".", NULL }, "\xdf\xbf" },
+ { UDA, CI, 0, 0, 0, 0, 2, { ".", NULL }, "\xc2\x80##" },
+ { UDA, CI, 0, 0, 0, 0, 2, { ".", NULL }, "\xc2\x80#" },
+ { UDA, CI, 0, 0, 0, 0, 2, { ".", NULL }, "\xc2\x80" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xe0\x80##" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xdf\xc0##" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xe0\x80" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xdf\xc0" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xc1\xbf##" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xc1\xbf" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\x80###" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\x80" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xf8###" },
+ { UDA, CI, 0, 0, 0, -1, -1, { ".", NULL }, "\xf8" },
+ { UDA, CI, 0, 0, 0, 0, 1, { ".", NULL }, "\x7f" },
+
+ { UDA, CPI, 4, 0, 0, 4, 4, { "\\B", NULL }, "\xf4\x8f\xbf\xbf#" },
+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "\xf4\xa0\x80\x80\xf4\xa0\x80\x80" },
+ { UDA, CPI, 4, 1, 1, -1, -1, { "\\B", "\\b" }, "\xf4\x8f\xbf\xbf\xf4\x8f\xbf\xbf" },
+ { UDA, CPI, 4, 0, 0, 4, 4, { "\\B", NULL }, "#\xef\xbf\xbf#" },
+ { UDA, CPI, 4, 0, 0, 4, 4, { "\\B", NULL }, "#\xe0\xa0\x80#" },
+ { UDA, CPI, 4, 0, 0, 4, 4, { "\\B", NULL }, "\xf0\x90\x80\x80#" },
+ { UDA, CPI, 4, 0, 0, 4, 4, { "\\B", NULL }, "\xf3\xbf\xbf\xbf#" },
+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "\xf0\x8f\xbf\xbf\xf0\x8f\xbf\xbf" },
+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "\xf5\x80\x80\x80\xf5\x80\x80\x80" },
+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "\xf4\x90\x80\x80\xf4\x90\x80\x80" },
+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "\xf4\x8f\xbf\xff\xf4\x8f\xbf\xff" },
+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "\xf4\x8f\xff\xbf\xf4\x8f\xff\xbf" },
+ { UDA, CPI, 4, 0, 1, -1, -1, { "\\B", "\\b" }, "\xef\x80\x80\x80\xef\x80\x80" },
+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "\x80\x80\x80\x80\x80\x80\x80\x80" },
+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "#\xe0\x9f\xbf\xe0\x9f\xbf#" },
+ { UDA, CPI, 4, 2, 2, -1, -1, { "\\B", "\\b" }, "#\xe0\xa0\x80\xe0\xa0\x80#" },
+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "#\xf0\x80\x80\xf0\x80\x80#" },
+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "#\xed\xa0\x80\xed\xa0\x80#" },
+ { UDA, CPI, 4, 0, 0, 4, 4, { "\\B", NULL }, "##\xdf\xbf#" },
+ { UDA, CPI, 4, 2, 0, 2, 2, { "\\B", NULL }, "##\xdf\xbf#" },
+ { UDA, CPI, 4, 0, 0, 4, 4, { "\\B", NULL }, "##\xc2\x80#" },
+ { UDA, CPI, 4, 2, 0, 2, 2, { "\\B", NULL }, "##\xc2\x80#" },
+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "##\xc1\xbf\xc1\xbf##" },
+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "##\xdf\xc0\xdf\xc0##" },
+ { UDA, CPI, 4, 0, 0, -1, -1, { "\\B", "\\b" }, "##\xe0\x80\xe0\x80##" },
+
+ { UDA, CPI, 3, 0, 0, 3, 3, { "\\B", NULL }, "\xef\xbf\xbf#" },
+ { UDA, CPI, 3, 0, 0, 3, 3, { "\\B", NULL }, "\xe0\xa0\x80#" },
+ { UDA, CPI, 3, 0, 0, -1, -1, { "\\B", "\\b" }, "\xe0\x9f\xbf\xe0\x9f\xbf" },
+ { UDA, CPI, 3, 1, 1, -1, -1, { "\\B", "\\b" }, "\xef\xbf\xbf\xef\xbf\xbf" },
+ { UDA, CPI, 3, 0, 1, -1, -1, { "\\B", "\\b" }, "\xdf\x80\x80\xdf\x80" },
+ { UDA, CPI, 3, 0, 0, -1, -1, { "\\B", "\\b" }, "\xef\xbf\xff\xef\xbf\xff" },
+ { UDA, CPI, 3, 0, 0, -1, -1, { "\\B", "\\b" }, "\xef\xff\xbf\xef\xff\xbf" },
+ { UDA, CPI, 3, 0, 0, -1, -1, { "\\B", "\\b" }, "\xed\xbf\xbf\xed\xbf\xbf" },
+
+ { UDA, CPI, 2, 0, 0, 2, 2, { "\\B", NULL }, "\xdf\xbf#" },
+ { UDA, CPI, 2, 0, 0, 2, 2, { "\\B", NULL }, "\xc2\x80#" },
+ { UDA, CPI, 2, 1, 1, -1, -1, { "\\B", "\\b" }, "\xdf\xbf\xdf\xbf" },
+ { UDA, CPI, 2, 0, 0, -1, -1, { "\\B", "\\b" }, "\xc1\xbf\xc1\xbf" },
+ { UDA, CPI, 2, 0, 0, -1, -1, { "\\B", "\\b" }, "\xe0\x80\xe0\x80" },
+ { UDA, CPI, 2, 0, 0, -1, -1, { "\\B", "\\b" }, "\xdf\xff\xdf\xff" },
+ { UDA, CPI, 2, 0, 0, -1, -1, { "\\B", "\\b" }, "\xff\xbf\xff\xbf" },
+
+ { UDA, CPI, 1, 0, 0, 1, 1, { "\\B", NULL }, "\x7f#" },
+ { UDA, CPI, 1, 0, 0, 1, 1, { "\\B", NULL }, "\x01#" },
+ { UDA, CPI, 1, 0, 0, -1, -1, { "\\B", "\\b" }, "\x80\x80" },
+ { UDA, CPI, 1, 0, 0, -1, -1, { "\\B", "\\b" }, "\xb0\xb0" },
+
+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, 0, 2, { "(.)\\1", NULL }, "aA" },
+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, -1, -1, { "(.)\\1", NULL }, "a\xff" },
+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, 0, 4, { "(.)\\1", NULL }, "\xc3\xa1\xc3\x81" },
+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 1, -1, -1, { "(.)\\1", NULL }, "\xc3\xa1\xc3\x81" },
+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, -1, -1, { "(.)\\1", NULL }, "\xc2\x80\x80" },
+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, 0, 6, { "(.)\\1", NULL }, "\xe1\xbd\xb8\xe1\xbf\xb8" },
+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 1, -1, -1, { "(.)\\1", NULL }, "\xe1\xbd\xb8\xe1\xbf\xb8" },
+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, 0, 8, { "(.)\\1", NULL }, "\xf0\x90\x90\x80\xf0\x90\x90\xa8" },
+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 1, -1, -1, { "(.)\\1", NULL }, "\xf0\x90\x90\x80\xf0\x90\x90\xa8" },
+
+ { UDA, CPI, 0, 0, 0, 0, 1, { "\\X", NULL }, "A" },
+ { UDA, CPI, 0, 0, 0, -1, -1, { "\\X", NULL }, "\xff" },
+ { UDA, CPI, 0, 0, 0, 0, 2, { "\\X", NULL }, "\xc3\xa1" },
+ { UDA, CPI, 0, 0, 1, -1, -1, { "\\X", NULL }, "\xc3\xa1" },
+ { UDA, CPI, 0, 0, 0, -1, -1, { "\\X", NULL }, "\xc3\x7f" },
+ { UDA, CPI, 0, 0, 0, 0, 3, { "\\X", NULL }, "\xe1\xbd\xb8" },
+ { UDA, CPI, 0, 0, 1, -1, -1, { "\\X", NULL }, "\xe1\xbd\xb8" },
+ { UDA, CPI, 0, 0, 0, 0, 4, { "\\X", NULL }, "\xf0\x90\x90\x80" },
+ { UDA, CPI, 0, 0, 1, -1, -1, { "\\X", NULL }, "\xf0\x90\x90\x80" },
+
+ { UDA, CPI, 0, 0, 0, -1, -1, { "[^#]", NULL }, "#" },
+ { UDA, CPI, 0, 0, 0, 0, 4, { "[^#]", NULL }, "\xf4\x8f\xbf\xbf" },
+ { UDA, CPI, 0, 0, 0, -1, -1, { "[^#]", NULL }, "\xf4\x90\x80\x80" },
+ { UDA, CPI, 0, 0, 0, -1, -1, { "[^#]", NULL }, "\xc1\x80" },
+
+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 2, 3, { "^\\W", NULL }, " \x0a#"},
+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 14, 15, { "^\\W", NULL }, " \xc0\x8a#\xe0\x80\x8a#\xf0\x80\x80\x8a#\x0a#"},
+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 3, 4, { "^\\W", NULL }, " \xf8\x0a#"},
+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 3, 4, { "^\\W", NULL }, " \xc3\x0a#"},
+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 3, 4, { "^\\W", NULL }, " \xf1\x0a#"},
+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 4, 5, { "^\\W", NULL }, " \xf2\xbf\x0a#"},
+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 5, 6, { "^\\W", NULL }, " \xf2\xbf\xbf\x0a#"},
+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 3, 4, { "^\\W", NULL }, " \xef\x0a#"},
+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 4, 5, { "^\\W", NULL }, " \xef\xbf\x0a#"},
+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 5, 6, { "^\\W", NULL }, " \x85#\xc2\x85#"},
+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 7, 8, { "^\\W", NULL }, " \xe2\x80\xf8\xe2\x80\xa8#"},
+
+ { PCRE2_UTF | PCRE2_FIRSTLINE, CI, 0, 0, 0, -1, -1, { "#", NULL }, "\xe2\x80\xf8\xe2\x80\xa8#"},
+ { PCRE2_UTF | PCRE2_FIRSTLINE, CI, 0, 0, 0, 3, 4, { "#", NULL }, "\xe2\x80\xf8#\xe2\x80\xa8#"},
+ { PCRE2_UTF | PCRE2_FIRSTLINE, CI, 0, 0, 0, -1, -1, { "#", NULL }, "abcd\xc2\x85#"},
+ { PCRE2_UTF | PCRE2_FIRSTLINE, CI, 0, 0, 0, 1, 2, { "#", NULL }, "\x85#\xc2\x85#"},
+ { PCRE2_UTF | PCRE2_FIRSTLINE, CI, 0, 0, 0, 5, 6, { "#", NULL }, "\xef,\x80,\xf8#\x0a"},
+ { PCRE2_UTF | PCRE2_FIRSTLINE, CI, 0, 0, 0, -1, -1, { "#", NULL }, "\xef,\x80,\xf8\x0a#"},
+
+ { PCRE2_UTF | PCRE2_NO_START_OPTIMIZE, CI, 0, 0, 0, 4, 8, { "#\xc7\x85#", NULL }, "\x80\x80#\xc7#\xc7\x85#" },
+ { PCRE2_UTF | PCRE2_NO_START_OPTIMIZE, CI, 0, 0, 0, 7, 11, { "#\xc7\x85#", NULL }, "\x80\x80#\xc7\x80\x80\x80#\xc7\x85#" },
+ { PCRE2_UTF, CI, 0, 0, 0, 4, 8, { "#\xc7\x85#", NULL }, "\x80\x80#\xc7#\xc7\x85#" },
+ { PCRE2_UTF, CI, 0, 0, 0, 7, 11, { "#\xc7\x85#", NULL }, "\x80\x80#\xc7\x80\x80\x80#\xc7\x85#" },
+
+ /* These two are not invalid UTF tests, but this infrastructure fits better for them. */
+ { 0, PCRE2_JIT_COMPLETE, 0, 0, 1, -1, -1, { "\\X{2}", NULL }, "\r\n\n" },
+ { 0, PCRE2_JIT_COMPLETE, 0, 0, 1, -1, -1, { "\\R{2}", NULL }, "\r\n\n" },
+
+ { 0, 0, 0, 0, 0, 0, 0, { NULL, NULL }, NULL }
+};
+
+#undef UDA
+#undef CI
+#undef CPI
+
+static int run_invalid_utf8_test(struct invalid_utf8_regression_test_case *current,
+ int pattern_index, int i, pcre2_compile_context_8 *ccontext, pcre2_match_data_8 *mdata)
+{
+ pcre2_code_8 *code;
+ int result, errorcode;
+ PCRE2_SIZE length, erroroffset;
+ PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_8(mdata);
+
+ if (current->pattern[i] == NULL)
+ return 1;
+
+ code = pcre2_compile_8((PCRE2_UCHAR8*)current->pattern[i], PCRE2_ZERO_TERMINATED,
+ current->compile_options, &errorcode, &erroroffset, ccontext);
+
+ if (!code) {
+ printf("Pattern[%d:0] cannot be compiled. Error offset: %d\n", pattern_index, (int)erroroffset);
+ return 0;
+ }
+
+ if (pcre2_jit_compile_8(code, current->jit_compile_options) != 0) {
+ printf("Pattern[%d:0] cannot be compiled by the JIT compiler.\n", pattern_index);
+ pcre2_code_free_8(code);
+ return 0;
+ }
+
+ length = (PCRE2_SIZE)(strlen(current->input) - current->skip_left - current->skip_right);
+
+ if (current->jit_compile_options & PCRE2_JIT_COMPLETE) {
+ result = pcre2_jit_match_8(code, (PCRE2_UCHAR8*)(current->input + current->skip_left),
+ length, current->start_offset - current->skip_left, 0, mdata, NULL);
+
+ if (check_invalid_utf_result(pattern_index, "match", result, current->match_start, current->match_end, ovector)) {
+ pcre2_code_free_8(code);
+ return 0;
+ }
+ }
+
+ if (current->jit_compile_options & PCRE2_JIT_PARTIAL_SOFT) {
+ result = pcre2_jit_match_8(code, (PCRE2_UCHAR8*)(current->input + current->skip_left),
+ length, current->start_offset - current->skip_left, PCRE2_PARTIAL_SOFT, mdata, NULL);
+
+ if (check_invalid_utf_result(pattern_index, "partial match", result, current->match_start, current->match_end, ovector)) {
+ pcre2_code_free_8(code);
+ return 0;
+ }
+ }
+
+ pcre2_code_free_8(code);
+ return 1;
+}
+
+static int invalid_utf8_regression_tests(void)
+{
+ struct invalid_utf8_regression_test_case *current;
+ pcre2_compile_context_8 *ccontext;
+ pcre2_match_data_8 *mdata;
+ int total = 0, successful = 0;
+ int result;
+
+ printf("\nRunning invalid-utf8 JIT regression tests\n");
+
+ ccontext = pcre2_compile_context_create_8(NULL);
+ pcre2_set_newline_8(ccontext, PCRE2_NEWLINE_ANY);
+ mdata = pcre2_match_data_create_8(4, NULL);
+
+ for (current = invalid_utf8_regression_test_cases; current->pattern[0]; current++) {
+ /* printf("\nPattern: %s :\n", current->pattern); */
+ total++;
+
+ result = 1;
+ if (!run_invalid_utf8_test(current, total - 1, 0, ccontext, mdata))
+ result = 0;
+ if (!run_invalid_utf8_test(current, total - 1, 1, ccontext, mdata))
+ result = 0;
+
+ if (result) {
+ successful++;
+ }
+
+ printf(".");
+ if ((total % 60) == 0)
+ printf("\n");
+ }
+
+ if ((total % 60) != 0)
+ printf("\n");
+
+ pcre2_match_data_free_8(mdata);
+ pcre2_compile_context_free_8(ccontext);
+
+ if (total == successful) {
+ printf("\nAll invalid UTF8 JIT regression tests are successfully passed.\n");
+ return 0;
+ } else {
+ printf("\nInvalid UTF8 successful test ratio: %d%% (%d failed)\n", successful * 100 / total, total - successful);
+ return 1;
+ }
+}
+
+#else /* !SUPPORT_UNICODE || !SUPPORT_PCRE2_8 */
+
+static int invalid_utf8_regression_tests(void)
+{
+ return 0;
+}
+
+#endif /* SUPPORT_UNICODE && SUPPORT_PCRE2_8 */
+
+#if defined SUPPORT_UNICODE && defined SUPPORT_PCRE2_16
+
+#define UDA (PCRE2_UTF | PCRE2_DOTALL | PCRE2_ANCHORED)
+#define CI (PCRE2_JIT_COMPLETE | PCRE2_JIT_INVALID_UTF)
+#define CPI (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_INVALID_UTF)
+
+struct invalid_utf16_regression_test_case {
+ int compile_options;
+ int jit_compile_options;
+ int start_offset;
+ int skip_left;
+ int skip_right;
+ int match_start;
+ int match_end;
+ const PCRE2_UCHAR16 *pattern[2];
+ const PCRE2_UCHAR16 *input;
+};
+
+static PCRE2_UCHAR16 allany16[] = { '.', 0 };
+static PCRE2_UCHAR16 non_word_boundary16[] = { '\\', 'B', 0 };
+static PCRE2_UCHAR16 word_boundary16[] = { '\\', 'b', 0 };
+static PCRE2_UCHAR16 backreference16[] = { '(', '.', ')', '\\', '1', 0 };
+static PCRE2_UCHAR16 grapheme16[] = { '\\', 'X', 0 };
+static PCRE2_UCHAR16 nothashmark16[] = { '[', '^', '#', ']', 0 };
+static PCRE2_UCHAR16 afternl16[] = { '^', '\\', 'W', 0 };
+static PCRE2_UCHAR16 generic16[] = { '#', 0xd800, 0xdc00, '#', 0 };
+static PCRE2_UCHAR16 test16_1[] = { 0xd7ff, 0xe000, 0xffff, 0x01, '#', 0 };
+static PCRE2_UCHAR16 test16_2[] = { 0xd800, 0xdc00, 0xd800, 0xdc00, 0 };
+static PCRE2_UCHAR16 test16_3[] = { 0xdbff, 0xdfff, 0xdbff, 0xdfff, 0 };
+static PCRE2_UCHAR16 test16_4[] = { 0xd800, 0xdbff, 0xd800, 0xdbff, 0 };
+static PCRE2_UCHAR16 test16_5[] = { '#', 0xd800, 0xdc00, '#', 0 };
+static PCRE2_UCHAR16 test16_6[] = { 'a', 'A', 0xdc28, 0 };
+static PCRE2_UCHAR16 test16_7[] = { 0xd801, 0xdc00, 0xd801, 0xdc28, 0 };
+static PCRE2_UCHAR16 test16_8[] = { '#', 0xd800, 0xdc00, 0 };
+static PCRE2_UCHAR16 test16_9[] = { ' ', 0x2028, '#', 0 };
+static PCRE2_UCHAR16 test16_10[] = { ' ', 0xdc00, 0xd800, 0x2028, '#', 0 };
+static PCRE2_UCHAR16 test16_11[] = { 0xdc00, 0xdc00, 0xd800, 0xdc00, 0xdc00, '#', 0xd800, 0xdc00, '#', 0 };
+static PCRE2_UCHAR16 test16_12[] = { '#', 0xd800, 0xdc00, 0xd800, '#', 0xd800, 0xdc00, 0xdc00, 0xdc00, '#', 0xd800, 0xdc00, '#', 0 };
+
+static struct invalid_utf16_regression_test_case invalid_utf16_regression_test_cases[] = {
+ { UDA, CI, 0, 0, 0, 0, 1, { allany16, NULL }, test16_1 },
+ { UDA, CI, 1, 0, 0, 1, 2, { allany16, NULL }, test16_1 },
+ { UDA, CI, 2, 0, 0, 2, 3, { allany16, NULL }, test16_1 },
+ { UDA, CI, 3, 0, 0, 3, 4, { allany16, NULL }, test16_1 },
+ { UDA, CI, 0, 0, 0, 0, 2, { allany16, NULL }, test16_2 },
+ { UDA, CI, 0, 0, 3, -1, -1, { allany16, NULL }, test16_2 },
+ { UDA, CI, 1, 0, 0, -1, -1, { allany16, NULL }, test16_2 },
+ { UDA, CI, 0, 0, 0, 0, 2, { allany16, NULL }, test16_3 },
+ { UDA, CI, 0, 0, 3, -1, -1, { allany16, NULL }, test16_3 },
+ { UDA, CI, 1, 0, 0, -1, -1, { allany16, NULL }, test16_3 },
+
+ { UDA, CPI, 1, 0, 0, 1, 1, { non_word_boundary16, NULL }, test16_1 },
+ { UDA, CPI, 2, 0, 0, 2, 2, { non_word_boundary16, NULL }, test16_1 },
+ { UDA, CPI, 3, 0, 0, 3, 3, { non_word_boundary16, NULL }, test16_1 },
+ { UDA, CPI, 4, 0, 0, 4, 4, { non_word_boundary16, NULL }, test16_1 },
+ { UDA, CPI, 2, 0, 0, 2, 2, { non_word_boundary16, NULL }, test16_2 },
+ { UDA, CPI, 2, 0, 0, 2, 2, { non_word_boundary16, NULL }, test16_3 },
+ { UDA, CPI, 2, 1, 1, -1, -1, { non_word_boundary16, word_boundary16 }, test16_2 },
+ { UDA, CPI, 2, 1, 1, -1, -1, { non_word_boundary16, word_boundary16 }, test16_3 },
+ { UDA, CPI, 2, 0, 0, -1, -1, { non_word_boundary16, word_boundary16 }, test16_4 },
+ { UDA, CPI, 2, 0, 0, -1, -1, { non_word_boundary16, word_boundary16 }, test16_5 },
+
+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, 0, 2, { backreference16, NULL }, test16_6 },
+ { UDA | PCRE2_CASELESS, CPI, 1, 0, 0, -1, -1, { backreference16, NULL }, test16_6 },
+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, 0, 4, { backreference16, NULL }, test16_7 },
+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 1, -1, -1, { backreference16, NULL }, test16_7 },
+
+ { UDA, CPI, 0, 0, 0, 0, 1, { grapheme16, NULL }, test16_6 },
+ { UDA, CPI, 1, 0, 0, 1, 2, { grapheme16, NULL }, test16_6 },
+ { UDA, CPI, 2, 0, 0, -1, -1, { grapheme16, NULL }, test16_6 },
+ { UDA, CPI, 0, 0, 0, 0, 2, { grapheme16, NULL }, test16_7 },
+ { UDA, CPI, 2, 0, 0, 2, 4, { grapheme16, NULL }, test16_7 },
+ { UDA, CPI, 1, 0, 0, -1, -1, { grapheme16, NULL }, test16_7 },
+
+ { UDA, CPI, 0, 0, 0, -1, -1, { nothashmark16, NULL }, test16_8 },
+ { UDA, CPI, 1, 0, 0, 1, 3, { nothashmark16, NULL }, test16_8 },
+ { UDA, CPI, 2, 0, 0, -1, -1, { nothashmark16, NULL }, test16_8 },
+
+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 2, 3, { afternl16, NULL }, test16_9 },
+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 4, 5, { afternl16, NULL }, test16_10 },
+
+ { PCRE2_UTF | PCRE2_NO_START_OPTIMIZE, CI, 0, 0, 0, 5, 9, { generic16, NULL }, test16_11 },
+ { PCRE2_UTF | PCRE2_NO_START_OPTIMIZE, CI, 0, 0, 0, 9, 13, { generic16, NULL }, test16_12 },
+ { PCRE2_UTF, CI, 0, 0, 0, 5, 9, { generic16, NULL }, test16_11 },
+ { PCRE2_UTF, CI, 0, 0, 0, 9, 13, { generic16, NULL }, test16_12 },
+
+ { 0, 0, 0, 0, 0, 0, 0, { NULL, NULL }, NULL }
+};
+
+#undef UDA
+#undef CI
+#undef CPI
+
+static int run_invalid_utf16_test(struct invalid_utf16_regression_test_case *current,
+ int pattern_index, int i, pcre2_compile_context_16 *ccontext, pcre2_match_data_16 *mdata)
+{
+ pcre2_code_16 *code;
+ int result, errorcode;
+ PCRE2_SIZE length, erroroffset;
+ const PCRE2_UCHAR16 *input;
+ PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_16(mdata);
+
+ if (current->pattern[i] == NULL)
+ return 1;
+
+ code = pcre2_compile_16(current->pattern[i], PCRE2_ZERO_TERMINATED,
+ current->compile_options, &errorcode, &erroroffset, ccontext);
+
+ if (!code) {
+ printf("Pattern[%d:0] cannot be compiled. Error offset: %d\n", pattern_index, (int)erroroffset);
+ return 0;
+ }
+
+ if (pcre2_jit_compile_16(code, current->jit_compile_options) != 0) {
+ printf("Pattern[%d:0] cannot be compiled by the JIT compiler.\n", pattern_index);
+ pcre2_code_free_16(code);
+ return 0;
+ }
+
+ input = current->input;
+ length = 0;
+
+ while (*input++ != 0)
+ length++;
+
+ length -= current->skip_left + current->skip_right;
+
+ if (current->jit_compile_options & PCRE2_JIT_COMPLETE) {
+ result = pcre2_jit_match_16(code, (current->input + current->skip_left),
+ length, current->start_offset - current->skip_left, 0, mdata, NULL);
+
+ if (check_invalid_utf_result(pattern_index, "match", result, current->match_start, current->match_end, ovector)) {
+ pcre2_code_free_16(code);
+ return 0;
+ }
+ }
+
+ if (current->jit_compile_options & PCRE2_JIT_PARTIAL_SOFT) {
+ result = pcre2_jit_match_16(code, (current->input + current->skip_left),
+ length, current->start_offset - current->skip_left, PCRE2_PARTIAL_SOFT, mdata, NULL);
+
+ if (check_invalid_utf_result(pattern_index, "partial match", result, current->match_start, current->match_end, ovector)) {
+ pcre2_code_free_16(code);
+ return 0;
+ }
+ }
+
+ pcre2_code_free_16(code);
+ return 1;
+}
+
+static int invalid_utf16_regression_tests(void)
+{
+ struct invalid_utf16_regression_test_case *current;
+ pcre2_compile_context_16 *ccontext;
+ pcre2_match_data_16 *mdata;
+ int total = 0, successful = 0;
+ int result;
+
+ printf("\nRunning invalid-utf16 JIT regression tests\n");
+
+ ccontext = pcre2_compile_context_create_16(NULL);
+ pcre2_set_newline_16(ccontext, PCRE2_NEWLINE_ANY);
+ mdata = pcre2_match_data_create_16(4, NULL);
+
+ for (current = invalid_utf16_regression_test_cases; current->pattern[0]; current++) {
+ /* printf("\nPattern: %s :\n", current->pattern); */
+ total++;
+
+ result = 1;
+ if (!run_invalid_utf16_test(current, total - 1, 0, ccontext, mdata))
+ result = 0;
+ if (!run_invalid_utf16_test(current, total - 1, 1, ccontext, mdata))
+ result = 0;
+
+ if (result) {
+ successful++;
+ }
+
+ printf(".");
+ if ((total % 60) == 0)
+ printf("\n");
+ }
+
+ if ((total % 60) != 0)
+ printf("\n");
+
+ pcre2_match_data_free_16(mdata);
+ pcre2_compile_context_free_16(ccontext);
+
+ if (total == successful) {
+ printf("\nAll invalid UTF16 JIT regression tests are successfully passed.\n");
+ return 0;
+ } else {
+ printf("\nInvalid UTF16 successful test ratio: %d%% (%d failed)\n", successful * 100 / total, total - successful);
+ return 1;
+ }
+}
+
+#else /* !SUPPORT_UNICODE || !SUPPORT_PCRE2_16 */
+
+static int invalid_utf16_regression_tests(void)
+{
+ return 0;
+}
+
+#endif /* SUPPORT_UNICODE && SUPPORT_PCRE2_16 */
+
+#if defined SUPPORT_UNICODE && defined SUPPORT_PCRE2_32
+
+#define UDA (PCRE2_UTF | PCRE2_DOTALL | PCRE2_ANCHORED)
+#define CI (PCRE2_JIT_COMPLETE | PCRE2_JIT_INVALID_UTF)
+#define CPI (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_INVALID_UTF)
+
+struct invalid_utf32_regression_test_case {
+ int compile_options;
+ int jit_compile_options;
+ int start_offset;
+ int skip_left;
+ int skip_right;
+ int match_start;
+ int match_end;
+ const PCRE2_UCHAR32 *pattern[2];
+ const PCRE2_UCHAR32 *input;
+};
+
+static PCRE2_UCHAR32 allany32[] = { '.', 0 };
+static PCRE2_UCHAR32 non_word_boundary32[] = { '\\', 'B', 0 };
+static PCRE2_UCHAR32 word_boundary32[] = { '\\', 'b', 0 };
+static PCRE2_UCHAR32 backreference32[] = { '(', '.', ')', '\\', '1', 0 };
+static PCRE2_UCHAR32 grapheme32[] = { '\\', 'X', 0 };
+static PCRE2_UCHAR32 nothashmark32[] = { '[', '^', '#', ']', 0 };
+static PCRE2_UCHAR32 afternl32[] = { '^', '\\', 'W', 0 };
+static PCRE2_UCHAR32 test32_1[] = { 0x10ffff, 0x10ffff, 0x110000, 0x110000, 0x10ffff, 0 };
+static PCRE2_UCHAR32 test32_2[] = { 0xd7ff, 0xe000, 0xd800, 0xdfff, 0xe000, 0xdfff, 0xd800, 0 };
+static PCRE2_UCHAR32 test32_3[] = { 'a', 'A', 0x110000, 0 };
+static PCRE2_UCHAR32 test32_4[] = { '#', 0x10ffff, 0x110000, 0 };
+static PCRE2_UCHAR32 test32_5[] = { ' ', 0x2028, '#', 0 };
+static PCRE2_UCHAR32 test32_6[] = { ' ', 0x110000, 0x2028, '#', 0 };
+
+static struct invalid_utf32_regression_test_case invalid_utf32_regression_test_cases[] = {
+ { UDA, CI, 0, 0, 0, 0, 1, { allany32, NULL }, test32_1 },
+ { UDA, CI, 2, 0, 0, -1, -1, { allany32, NULL }, test32_1 },
+ { UDA, CI, 0, 0, 0, 0, 1, { allany32, NULL }, test32_2 },
+ { UDA, CI, 1, 0, 0, 1, 2, { allany32, NULL }, test32_2 },
+ { UDA, CI, 2, 0, 0, -1, -1, { allany32, NULL }, test32_2 },
+ { UDA, CI, 3, 0, 0, -1, -1, { allany32, NULL }, test32_2 },
+
+ { UDA, CPI, 1, 0, 0, 1, 1, { non_word_boundary32, NULL }, test32_1 },
+ { UDA, CPI, 3, 0, 0, -1, -1, { non_word_boundary32, word_boundary32 }, test32_1 },
+ { UDA, CPI, 1, 0, 0, 1, 1, { non_word_boundary32, NULL }, test32_2 },
+ { UDA, CPI, 3, 0, 0, -1, -1, { non_word_boundary32, word_boundary32 }, test32_2 },
+ { UDA, CPI, 6, 0, 0, -1, -1, { non_word_boundary32, word_boundary32 }, test32_2 },
+
+ { UDA | PCRE2_CASELESS, CPI, 0, 0, 0, 0, 2, { backreference32, NULL }, test32_3 },
+ { UDA | PCRE2_CASELESS, CPI, 1, 0, 0, -1, -1, { backreference32, NULL }, test32_3 },
+
+ { UDA, CPI, 0, 0, 0, 0, 1, { grapheme32, NULL }, test32_1 },
+ { UDA, CPI, 2, 0, 0, -1, -1, { grapheme32, NULL }, test32_1 },
+ { UDA, CPI, 1, 0, 0, 1, 2, { grapheme32, NULL }, test32_2 },
+ { UDA, CPI, 2, 0, 0, -1, -1, { grapheme32, NULL }, test32_2 },
+ { UDA, CPI, 3, 0, 0, -1, -1, { grapheme32, NULL }, test32_2 },
+ { UDA, CPI, 4, 0, 0, 4, 5, { grapheme32, NULL }, test32_2 },
+
+ { UDA, CPI, 0, 0, 0, -1, -1, { nothashmark32, NULL }, test32_4 },
+ { UDA, CPI, 1, 0, 0, 1, 2, { nothashmark32, NULL }, test32_4 },
+ { UDA, CPI, 2, 0, 0, -1, -1, { nothashmark32, NULL }, test32_4 },
+ { UDA, CPI, 1, 0, 0, 1, 2, { nothashmark32, NULL }, test32_2 },
+ { UDA, CPI, 2, 0, 0, -1, -1, { nothashmark32, NULL }, test32_2 },
+
+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 2, 3, { afternl32, NULL }, test32_5 },
+ { PCRE2_UTF | PCRE2_MULTILINE, CI, 1, 0, 0, 3, 4, { afternl32, NULL }, test32_6 },
+
+ { 0, 0, 0, 0, 0, 0, 0, { NULL, NULL }, NULL }
+};
+
+#undef UDA
+#undef CI
+#undef CPI
+
+static int run_invalid_utf32_test(struct invalid_utf32_regression_test_case *current,
+ int pattern_index, int i, pcre2_compile_context_32 *ccontext, pcre2_match_data_32 *mdata)
+{
+ pcre2_code_32 *code;
+ int result, errorcode;
+ PCRE2_SIZE length, erroroffset;
+ const PCRE2_UCHAR32 *input;
+ PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_32(mdata);
+
+ if (current->pattern[i] == NULL)
+ return 1;
+
+ code = pcre2_compile_32(current->pattern[i], PCRE2_ZERO_TERMINATED,
+ current->compile_options, &errorcode, &erroroffset, ccontext);
+
+ if (!code) {
+ printf("Pattern[%d:0] cannot be compiled. Error offset: %d\n", pattern_index, (int)erroroffset);
+ return 0;
+ }
+
+ if (pcre2_jit_compile_32(code, current->jit_compile_options) != 0) {
+ printf("Pattern[%d:0] cannot be compiled by the JIT compiler.\n", pattern_index);
+ pcre2_code_free_32(code);
+ return 0;
+ }
+
+ input = current->input;
+ length = 0;
+
+ while (*input++ != 0)
+ length++;
+
+ length -= current->skip_left + current->skip_right;
+
+ if (current->jit_compile_options & PCRE2_JIT_COMPLETE) {
+ result = pcre2_jit_match_32(code, (current->input + current->skip_left),
+ length, current->start_offset - current->skip_left, 0, mdata, NULL);
+
+ if (check_invalid_utf_result(pattern_index, "match", result, current->match_start, current->match_end, ovector)) {
+ pcre2_code_free_32(code);
+ return 0;
+ }
+ }
+
+ if (current->jit_compile_options & PCRE2_JIT_PARTIAL_SOFT) {
+ result = pcre2_jit_match_32(code, (current->input + current->skip_left),
+ length, current->start_offset - current->skip_left, PCRE2_PARTIAL_SOFT, mdata, NULL);
+
+ if (check_invalid_utf_result(pattern_index, "partial match", result, current->match_start, current->match_end, ovector)) {
+ pcre2_code_free_32(code);
+ return 0;
+ }
+ }
+
+ pcre2_code_free_32(code);
+ return 1;
+}
+
+static int invalid_utf32_regression_tests(void)
+{
+ struct invalid_utf32_regression_test_case *current;
+ pcre2_compile_context_32 *ccontext;
+ pcre2_match_data_32 *mdata;
+ int total = 0, successful = 0;
+ int result;
+
+ printf("\nRunning invalid-utf32 JIT regression tests\n");
+
+ ccontext = pcre2_compile_context_create_32(NULL);
+ pcre2_set_newline_32(ccontext, PCRE2_NEWLINE_ANY);
+ mdata = pcre2_match_data_create_32(4, NULL);
+
+ for (current = invalid_utf32_regression_test_cases; current->pattern[0]; current++) {
+ /* printf("\nPattern: %s :\n", current->pattern); */
+ total++;
+
+ result = 1;
+ if (!run_invalid_utf32_test(current, total - 1, 0, ccontext, mdata))
+ result = 0;
+ if (!run_invalid_utf32_test(current, total - 1, 1, ccontext, mdata))
+ result = 0;
+
+ if (result) {
+ successful++;
+ }
+
+ printf(".");
+ if ((total % 60) == 0)
+ printf("\n");
+ }
+
+ if ((total % 60) != 0)
+ printf("\n");
+
+ pcre2_match_data_free_32(mdata);
+ pcre2_compile_context_free_32(ccontext);
+
+ if (total == successful) {
+ printf("\nAll invalid UTF32 JIT regression tests are successfully passed.\n");
+ return 0;
+ } else {
+ printf("\nInvalid UTF32 successful test ratio: %d%% (%d failed)\n", successful * 100 / total, total - successful);
+ return 1;
+ }
+}
+
+#else /* !SUPPORT_UNICODE || !SUPPORT_PCRE2_32 */
+
+static int invalid_utf32_regression_tests(void)
+{
+ return 0;
+}
+
+#endif /* SUPPORT_UNICODE && SUPPORT_PCRE2_32 */
+
/* End of pcre2_jit_test.c */
diff --git a/src/pcre2_maketables.c b/src/pcre2_maketables.c
index 537edba..8c93b4b 100644
--- a/src/pcre2_maketables.c
+++ b/src/pcre2_maketables.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -114,17 +114,17 @@ test for alnum specially. */
memset(p, 0, cbit_length);
for (i = 0; i < 256; i++)
{
- if (isdigit(i)) p[cbit_digit + i/8] |= 1 << (i&7);
- if (isupper(i)) p[cbit_upper + i/8] |= 1 << (i&7);
- if (islower(i)) p[cbit_lower + i/8] |= 1 << (i&7);
- if (isalnum(i)) p[cbit_word + i/8] |= 1 << (i&7);
- if (i == '_') p[cbit_word + i/8] |= 1 << (i&7);
- if (isspace(i)) p[cbit_space + i/8] |= 1 << (i&7);
- if (isxdigit(i))p[cbit_xdigit + i/8] |= 1 << (i&7);
- if (isgraph(i)) p[cbit_graph + i/8] |= 1 << (i&7);
- if (isprint(i)) p[cbit_print + i/8] |= 1 << (i&7);
- if (ispunct(i)) p[cbit_punct + i/8] |= 1 << (i&7);
- if (iscntrl(i)) p[cbit_cntrl + i/8] |= 1 << (i&7);
+ if (isdigit(i)) p[cbit_digit + i/8] |= 1u << (i&7);
+ if (isupper(i)) p[cbit_upper + i/8] |= 1u << (i&7);
+ if (islower(i)) p[cbit_lower + i/8] |= 1u << (i&7);
+ if (isalnum(i)) p[cbit_word + i/8] |= 1u << (i&7);
+ if (i == '_') p[cbit_word + i/8] |= 1u << (i&7);
+ if (isspace(i)) p[cbit_space + i/8] |= 1u << (i&7);
+ if (isxdigit(i))p[cbit_xdigit + i/8] |= 1u << (i&7);
+ if (isgraph(i)) p[cbit_graph + i/8] |= 1u << (i&7);
+ if (isprint(i)) p[cbit_print + i/8] |= 1u << (i&7);
+ if (ispunct(i)) p[cbit_punct + i/8] |= 1u << (i&7);
+ if (iscntrl(i)) p[cbit_cntrl + i/8] |= 1u << (i&7);
}
p += cbit_length;
@@ -138,8 +138,8 @@ for (i = 0; i < 256; i++)
int x = 0;
if (isspace(i)) x += ctype_space;
if (isalpha(i)) x += ctype_letter;
+ if (islower(i)) x += ctype_lcletter;
if (isdigit(i)) x += ctype_digit;
- if (isxdigit(i)) x += ctype_xdigit;
if (isalnum(i) || i == '_') x += ctype_word;
*p++ = x;
}
@@ -147,4 +147,15 @@ for (i = 0; i < 256; i++)
return yield;
}
+#ifndef DFTABLES
+PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
+pcre2_maketables_free(pcre2_general_context *gcontext, const uint8_t *tables)
+{
+ if (gcontext)
+ gcontext->memctl.free((void *)tables, gcontext->memctl.memory_data);
+ else
+ free((void *)tables);
+}
+#endif
+
/* End of pcre2_maketables.c */
diff --git a/src/pcre2_match.c b/src/pcre2_match.c
index 8741e14..48e7b9d 100644
--- a/src/pcre2_match.c
+++ b/src/pcre2_match.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2015-2018 University of Cambridge
+ New API code Copyright (c) 2015-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -69,11 +69,12 @@ information, and fields within it. */
#define PUBLIC_MATCH_OPTIONS \
(PCRE2_ANCHORED|PCRE2_ENDANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \
PCRE2_NOTEMPTY_ATSTART|PCRE2_NO_UTF_CHECK|PCRE2_PARTIAL_HARD| \
- PCRE2_PARTIAL_SOFT|PCRE2_NO_JIT)
+ PCRE2_PARTIAL_SOFT|PCRE2_NO_JIT|PCRE2_COPY_MATCHED_SUBJECT)
#define PUBLIC_JIT_MATCH_OPTIONS \
(PCRE2_NO_UTF_CHECK|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY|\
- PCRE2_NOTEMPTY_ATSTART|PCRE2_PARTIAL_SOFT|PCRE2_PARTIAL_HARD)
+ PCRE2_NOTEMPTY_ATSTART|PCRE2_PARTIAL_SOFT|PCRE2_PARTIAL_HARD|\
+ PCRE2_COPY_MATCHED_SUBJECT)
/* Non-error returns from and within the match() function. Error returns are
externally defined PCRE2_ERROR_xxx codes, which are all negative. */
@@ -414,8 +415,7 @@ if (caseless)
else
#endif
- /* Not in UTF mode */
-
+ /* Not in UTF mode */
{
for (; length > 0; length--)
{
@@ -490,27 +490,32 @@ heap is used for a larger vector.
*************************************************/
/* These macros pack up tests that are used for partial matching several times
-in the code. We set the "hit end" flag if the pointer is at the end of the
-subject and also past the earliest inspected character (i.e. something has been
-matched, even if not part of the actual matched string). For hard partial
-matching, we then return immediately. The second one is used when we already
-know we are past the end of the subject. */
+in the code. The second one is used when we already know we are past the end of
+the subject. We set the "hit end" flag if the pointer is at the end of the
+subject and either (a) the pointer is past the earliest inspected character
+(i.e. something has been matched, even if not part of the actual matched
+string), or (b) the pattern contains a lookbehind. These are the conditions for
+which adding more characters may allow the current match to continue.
+
+For hard partial matching, we immediately return a partial match. Otherwise,
+carrying on means that a complete match on the current subject will be sought.
+A partial match is returned only if no complete match can be found. */
#define CHECK_PARTIAL()\
- if (mb->partial != 0 && Feptr >= mb->end_subject && \
- Feptr > mb->start_used_ptr) \
+ if (Feptr >= mb->end_subject) \
{ \
- mb->hitend = TRUE; \
- if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; \
+ SCHECK_PARTIAL(); \
}
#define SCHECK_PARTIAL()\
- if (mb->partial != 0 && Feptr > mb->start_used_ptr) \
+ if (mb->partial != 0 && \
+ (Feptr > mb->start_used_ptr || mb->allowemptypartial)) \
{ \
mb->hitend = TRUE; \
if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; \
}
+
/* These macros are used to implement backtracking. They simulate a recursive
call to the match() function by means of a local vector of frames which
remember the backtracking points. */
@@ -1848,7 +1853,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
if (Fop == OP_CLASS) RRETURN(MATCH_NOMATCH);
}
else
- if ((Lbyte_map[fc/8] & (1 << (fc&7))) == 0) RRETURN(MATCH_NOMATCH);
+ if ((Lbyte_map[fc/8] & (1u << (fc&7))) == 0) RRETURN(MATCH_NOMATCH);
}
}
else
@@ -1870,7 +1875,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
}
else
#endif
- if ((Lbyte_map[fc/8] & (1 << (fc&7))) == 0) RRETURN(MATCH_NOMATCH);
+ if ((Lbyte_map[fc/8] & (1u << (fc&7))) == 0) RRETURN(MATCH_NOMATCH);
}
}
@@ -1902,7 +1907,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
if (Fop == OP_CLASS) RRETURN(MATCH_NOMATCH);
}
else
- if ((Lbyte_map[fc/8] & (1 << (fc&7))) == 0) RRETURN(MATCH_NOMATCH);
+ if ((Lbyte_map[fc/8] & (1u << (fc&7))) == 0) RRETURN(MATCH_NOMATCH);
}
}
else
@@ -1927,7 +1932,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
}
else
#endif
- if ((Lbyte_map[fc/8] & (1 << (fc&7))) == 0) RRETURN(MATCH_NOMATCH);
+ if ((Lbyte_map[fc/8] & (1u << (fc&7))) == 0) RRETURN(MATCH_NOMATCH);
}
}
/* Control never gets here */
@@ -1956,7 +1961,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
if (Fop == OP_CLASS) break;
}
else
- if ((Lbyte_map[fc/8] & (1 << (fc&7))) == 0) break;
+ if ((Lbyte_map[fc/8] & (1u << (fc&7))) == 0) break;
Feptr += len;
}
@@ -1993,7 +1998,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
}
else
#endif
- if ((Lbyte_map[fc/8] & (1 << (fc&7))) == 0) break;
+ if ((Lbyte_map[fc/8] & (1u << (fc&7))) == 0) break;
Feptr++;
}
@@ -4084,7 +4089,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
GETCHAR(fc, fptr);
}
lgb = UCD_GRAPHBREAK(fc);
- if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
+ if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break;
Feptr = fptr;
rgb = lgb;
}
@@ -5014,6 +5019,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
must record a backtracking point and also set up a chained frame. */
case OP_ONCE:
+ case OP_SCRIPT_RUN:
case OP_SBRA:
Lframe_type = GF_NOCAPTURE | Fop;
@@ -5125,6 +5131,8 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
case OP_ASSERT:
case OP_ASSERTBACK:
+ case OP_ASSERT_NA:
+ case OP_ASSERTBACK_NA:
Lframe_type = GF_NOCAPTURE | Fop;
for (;;)
{
@@ -5410,7 +5418,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
{
while (number-- > 0)
{
- if (Feptr <= mb->start_subject) RRETURN(MATCH_NOMATCH);
+ if (Feptr <= mb->check_subject) RRETURN(MATCH_NOMATCH);
Feptr--;
BACKCHAR(Feptr);
}
@@ -5418,7 +5426,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
else
#endif
- /* No UTF-8 support, or not in UTF-8 mode: count is byte count */
+ /* No UTF-8 support, or not in UTF-8 mode: count is code unit count */
{
if ((ptrdiff_t)number > Feptr - mb->start_subject) RRETURN(MATCH_NOMATCH);
@@ -5470,15 +5478,16 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
/* If we are at the end of an assertion that is a condition, return a
match, discarding any intermediate backtracking points. Copy back the
- captures into the frame before N so that they are set on return. Doing
- this for all assertions, both positive and negative, seems to match what
- Perl does. */
+ mark setting and the captures into the frame before N so that they are
+ set on return. Doing this for all assertions, both positive and negative,
+ seems to match what Perl does. */
if (GF_IDMASK(N->group_frame_type) == GF_CONDASSERT)
{
memcpy((char *)P + offsetof(heapframe, ovector), Fovector,
Foffset_top * sizeof(PCRE2_SIZE));
P->offset_top = Foffset_top;
+ P->mark = Fmark;
Fback_frame = (char *)F - (char *)P;
RRETURN(MATCH_MATCH);
}
@@ -5494,10 +5503,20 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
case OP_SCOND:
break;
- /* Positive assertions are like OP_ONCE, except that in addition the
+ /* Non-atomic positive assertions are like OP_BRA, except that the
subject pointer must be put back to where it was at the start of the
assertion. */
+ case OP_ASSERT_NA:
+ case OP_ASSERTBACK_NA:
+ if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
+ Feptr = P->eptr;
+ break;
+
+ /* Atomic positive assertions are like OP_ONCE, except that in addition
+ the subject pointer must be put back to where it was at the start of the
+ assertion. */
+
case OP_ASSERT:
case OP_ASSERTBACK:
if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
@@ -5526,6 +5545,14 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
case OP_ASSERTBACK_NOT:
RRETURN(MATCH_MATCH);
+ /* At the end of a script run, apply the script-checking rules. This code
+ will never by exercised if Unicode support it not compiled, because in
+ that environment script runs cause an error at compile time. */
+
+ case OP_SCRIPT_RUN:
+ if (!PRIV(script_run)(P->eptr, Feptr, utf)) RRETURN(MATCH_NOMATCH);
+ break;
+
/* Whole-pattern recursion is coded as a recurse into group 0, so it
won't be picked up here. Instead, we catch it when the OP_END is reached.
Other recursion is handled here. */
@@ -5630,7 +5657,11 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
case OP_EOD:
if (Feptr < mb->end_subject) RRETURN(MATCH_NOMATCH);
- SCHECK_PARTIAL();
+ if (mb->partial != 0)
+ {
+ mb->hitend = TRUE;
+ if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
+ }
Fecode++;
break;
@@ -5655,7 +5686,11 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
/* Either at end of string or \n before end. */
- SCHECK_PARTIAL();
+ if (mb->partial != 0)
+ {
+ mb->hitend = TRUE;
+ if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
+ }
Fecode++;
break;
@@ -5733,7 +5768,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
case OP_NOT_WORD_BOUNDARY:
case OP_WORD_BOUNDARY:
- if (Feptr == mb->start_subject) prev_is_word = FALSE; else
+ if (Feptr == mb->check_subject) prev_is_word = FALSE; else
{
PCRE2_SPTR lastptr = Feptr - 1;
#ifdef SUPPORT_UNICODE
@@ -5936,6 +5971,7 @@ in rrc. */
#define LBL(val) case val: goto L_RM##val;
RETURN_SWITCH:
+if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
if (Frdepth == 0) return rrc; /* Exit from the top level */
F = (heapframe *)((char *)F - Fback_frame); /* Backtrack */
mb->cb->callout_flags |= PCRE2_CALLOUT_BACKTRACK; /* Note for callouts */
@@ -5989,9 +6025,9 @@ Arguments:
Returns: > 0 => success; value is the number of ovector pairs filled
= 0 => success, but ovector is not big enough
- -1 => failed to match (PCRE2_ERROR_NOMATCH)
- -2 => partial match (PCRE2_ERROR_PARTIAL)
- < -2 => some kind of unexpected problem
+ = -1 => failed to match (PCRE2_ERROR_NOMATCH)
+ = -2 => partial match (PCRE2_ERROR_PARTIAL)
+ < -2 => some kind of unexpected problem
*/
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
@@ -6000,8 +6036,8 @@ pcre2_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,
pcre2_match_context *mcontext)
{
int rc;
+int was_zero_terminated = 0;
const uint8_t *start_bits = NULL;
-
const pcre2_real_code *re = (const pcre2_real_code *)code;
BOOL anchored;
@@ -6011,6 +6047,11 @@ BOOL has_req_cu = FALSE;
BOOL startline;
BOOL utf;
+#if PCRE2_CODE_UNIT_WIDTH == 8
+BOOL memchr_not_found_first_cu = FALSE;
+BOOL memchr_not_found_first_cu2 = FALSE;
+#endif
+
PCRE2_UCHAR first_cu = 0;
PCRE2_UCHAR first_cu2 = 0;
PCRE2_UCHAR req_cu = 0;
@@ -6018,10 +6059,23 @@ PCRE2_UCHAR req_cu2 = 0;
PCRE2_SPTR bumpalong_limit;
PCRE2_SPTR end_subject;
+PCRE2_SPTR true_end_subject;
PCRE2_SPTR start_match = subject + start_offset;
PCRE2_SPTR req_cu_ptr = start_match - 1;
-PCRE2_SPTR start_partial = NULL;
-PCRE2_SPTR match_partial = NULL;
+PCRE2_SPTR start_partial;
+PCRE2_SPTR match_partial;
+
+#ifdef SUPPORT_JIT
+BOOL use_jit;
+#endif
+
+#ifdef SUPPORT_UNICODE
+BOOL allow_invalid;
+uint32_t fragment_options = 0;
+#ifdef SUPPORT_JIT
+BOOL jit_checked_utf = FALSE;
+#endif
+#endif
PCRE2_SIZE frame_size;
@@ -6043,8 +6097,12 @@ mb->stack_frames = (heapframe *)stack_frames_vector;
/* A length equal to PCRE2_ZERO_TERMINATED implies a zero-terminated
subject string. */
-if (length == PCRE2_ZERO_TERMINATED) length = PRIV(strlen)(subject);
-end_subject = subject + length;
+if (length == PCRE2_ZERO_TERMINATED)
+ {
+ length = PRIV(strlen)(subject);
+ was_zero_terminated = 1;
+ }
+true_end_subject = end_subject = subject + length;
/* Plausibility checks */
@@ -6080,12 +6138,24 @@ options |= (re->flags & FF) / ((FF & (~FF+1)) / (OO & (~OO+1)));
#undef FF
#undef OO
-/* These two settings are used in the code for checking a UTF string that
-follows immediately afterwards. Other values in the mb block are used only
-during interpretive processing, not when the JIT support is in use, so they are
-set up later. */
+/* If the pattern was successfully studied with JIT support, we will run the
+JIT executable instead of the rest of this function. Most options must be set
+at compile time for the JIT code to be usable. */
+
+#ifdef SUPPORT_JIT
+use_jit = (re->executable_jit != NULL &&
+ (options & ~PUBLIC_JIT_MATCH_OPTIONS) == 0);
+#endif
+
+/* Initialize UTF parameters. */
utf = (re->overall_options & PCRE2_UTF) != 0;
+#ifdef SUPPORT_UNICODE
+allow_invalid = (re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0;
+#endif
+
+/* Convert the partial matching flags into an integer. */
+
mb->partial = ((options & PCRE2_PARTIAL_HARD) != 0)? 2 :
((options & PCRE2_PARTIAL_SOFT) != 0)? 1 : 0;
@@ -6096,85 +6166,269 @@ if (mb->partial != 0 &&
((re->overall_options | options) & PCRE2_ENDANCHORED) != 0)
return PCRE2_ERROR_BADOPTION;
-/* Check a UTF string for validity if required. For 8-bit and 16-bit strings,
-we must also check that a starting offset does not point into the middle of a
-multiunit character. We check only the portion of the subject that is going to
-be inspected during matching - from the offset minus the maximum back reference
-to the given length. This saves time when a small part of a large subject is
-being matched by the use of a starting offset. Note that the maximum lookbehind
-is a number of characters, not code units. */
+/* It is an error to set an offset limit without setting the flag at compile
+time. */
-#ifdef SUPPORT_UNICODE
-if (utf && (options & PCRE2_NO_UTF_CHECK) == 0)
+if (mcontext != NULL && mcontext->offset_limit != PCRE2_UNSET &&
+ (re->overall_options & PCRE2_USE_OFFSET_LIMIT) == 0)
+ return PCRE2_ERROR_BADOFFSETLIMIT;
+
+/* If the match data block was previously used with PCRE2_COPY_MATCHED_SUBJECT,
+free the memory that was obtained. Set the field to NULL for no match cases. */
+
+if ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0)
{
- PCRE2_SPTR check_subject = start_match; /* start_match includes offset */
+ match_data->memctl.free((void *)match_data->subject,
+ match_data->memctl.memory_data);
+ match_data->flags &= ~PCRE2_MD_COPIED_SUBJECT;
+ }
+match_data->subject = NULL;
+
+/* Zero the error offset in case the first code unit is invalid UTF. */
+
+match_data->startchar = 0;
+
+
+/* ============================= JIT matching ============================== */
- if (start_offset > 0)
+/* Prepare for JIT matching. Check a UTF string for validity unless no check is
+requested or invalid UTF can be handled. We check only the portion of the
+subject that might be be inspected during matching - from the offset minus the
+maximum lookbehind to the given length. This saves time when a small part of a
+large subject is being matched by the use of a starting offset. Note that the
+maximum lookbehind is a number of characters, not code units. */
+
+#ifdef SUPPORT_JIT
+if (use_jit)
+ {
+#ifdef SUPPORT_UNICODE
+ if (utf && (options & PCRE2_NO_UTF_CHECK) == 0 && !allow_invalid)
{
#if PCRE2_CODE_UNIT_WIDTH != 32
unsigned int i;
+#endif
+
+ /* For 8-bit and 16-bit UTF, check that the first code unit is a valid
+ character start. */
+
+#if PCRE2_CODE_UNIT_WIDTH != 32
if (start_match < end_subject && NOT_FIRSTCU(*start_match))
- return PCRE2_ERROR_BADUTFOFFSET;
- for (i = re->max_lookbehind; i > 0 && check_subject > subject; i--)
{
- check_subject--;
- while (check_subject > subject &&
+ if (start_offset > 0) return PCRE2_ERROR_BADUTFOFFSET;
#if PCRE2_CODE_UNIT_WIDTH == 8
- (*check_subject & 0xc0) == 0x80)
+ return PCRE2_ERROR_UTF8_ERR20; /* Isolated 0x80 byte */
+#else
+ return PCRE2_ERROR_UTF16_ERR3; /* Isolated low surrogate */
+#endif
+ }
+#endif /* WIDTH != 32 */
+
+ /* Move back by the maximum lookbehind, just in case it happens at the very
+ start of matching. */
+
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ for (i = re->max_lookbehind; i > 0 && start_match > subject; i--)
+ {
+ start_match--;
+ while (start_match > subject &&
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ (*start_match & 0xc0) == 0x80)
#else /* 16-bit */
- (*check_subject & 0xfc00) == 0xdc00)
-#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
- check_subject--;
+ (*start_match & 0xfc00) == 0xdc00)
+#endif
+ start_match--;
}
-#else
+#else /* PCRE2_CODE_UNIT_WIDTH != 32 */
+
/* In the 32-bit library, one code unit equals one character. However,
we cannot just subtract the lookbehind and then compare pointers, because
a very large lookbehind could create an invalid pointer. */
if (start_offset >= re->max_lookbehind)
- check_subject -= re->max_lookbehind;
+ start_match -= re->max_lookbehind;
else
- check_subject = subject;
+ start_match = subject;
#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */
+
+ /* Validate the relevant portion of the subject. Adjust the offset of an
+ invalid code point to be an absolute offset in the whole string. */
+
+ match_data->rc = PRIV(valid_utf)(start_match,
+ length - (start_match - subject), &(match_data->startchar));
+ if (match_data->rc != 0)
+ {
+ match_data->startchar += start_match - subject;
+ return match_data->rc;
+ }
+ jit_checked_utf = TRUE;
}
+#endif /* SUPPORT_UNICODE */
- /* Validate the relevant portion of the subject. After an error, adjust the
- offset to be an absolute offset in the whole string. */
+ /* If JIT returns BADOPTION, which means that the selected complete or
+ partial matching mode was not compiled, fall through to the interpreter. */
- match_data->rc = PRIV(valid_utf)(check_subject,
- length - (check_subject - subject), &(match_data->startchar));
- if (match_data->rc != 0)
+ rc = pcre2_jit_match(code, subject, length, start_offset, options,
+ match_data, mcontext);
+ if (rc != PCRE2_ERROR_JIT_BADOPTION)
{
- match_data->startchar += check_subject - subject;
- return match_data->rc;
+ if (rc >= 0 && (options & PCRE2_COPY_MATCHED_SUBJECT) != 0)
+ {
+ length = CU2BYTES(length + was_zero_terminated);
+ match_data->subject = match_data->memctl.malloc(length,
+ match_data->memctl.memory_data);
+ if (match_data->subject == NULL) return PCRE2_ERROR_NOMEMORY;
+ memcpy((void *)match_data->subject, subject, length);
+ match_data->flags |= PCRE2_MD_COPIED_SUBJECT;
+ }
+ return rc;
}
}
-#endif /* SUPPORT_UNICODE */
+#endif /* SUPPORT_JIT */
-/* It is an error to set an offset limit without setting the flag at compile
-time. */
+/* ========================= End of JIT matching ========================== */
-if (mcontext != NULL && mcontext->offset_limit != PCRE2_UNSET &&
- (re->overall_options & PCRE2_USE_OFFSET_LIMIT) == 0)
- return PCRE2_ERROR_BADOFFSETLIMIT;
-/* If the pattern was successfully studied with JIT support, run the JIT
-executable instead of the rest of this function. Most options must be set at
-compile time for the JIT code to be usable. Fallback to the normal code path if
-an unsupported option is set or if JIT returns BADOPTION (which means that the
-selected normal or partial matching mode was not compiled). */
+/* Proceed with non-JIT matching. The default is to allow lookbehinds to the
+start of the subject. A UTF check when there is a non-zero offset may change
+this. */
+
+mb->check_subject = subject;
+
+/* If a UTF subject string was not checked for validity in the JIT code above,
+check it here, and handle support for invalid UTF strings. The check above
+happens only when invalid UTF is not supported and PCRE2_NO_CHECK_UTF is unset.
+If we get here in those circumstances, it means the subject string is valid,
+but for some reason JIT matching was not successful. There is no need to check
+the subject again.
+We check only the portion of the subject that might be be inspected during
+matching - from the offset minus the maximum lookbehind to the given length.
+This saves time when a small part of a large subject is being matched by the
+use of a starting offset. Note that the maximum lookbehind is a number of
+characters, not code units.
+
+Note also that support for invalid UTF forces a check, overriding the setting
+of PCRE2_NO_CHECK_UTF. */
+
+#ifdef SUPPORT_UNICODE
+if (utf &&
#ifdef SUPPORT_JIT
-if (re->executable_jit != NULL && (options & ~PUBLIC_JIT_MATCH_OPTIONS) == 0)
+ !jit_checked_utf &&
+#endif
+ ((options & PCRE2_NO_UTF_CHECK) == 0 || allow_invalid))
{
- rc = pcre2_jit_match(code, subject, length, start_offset, options,
- match_data, mcontext);
- if (rc != PCRE2_ERROR_JIT_BADOPTION) return rc;
- }
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ BOOL skipped_bad_start = FALSE;
+#endif
+
+ /* For 8-bit and 16-bit UTF, check that the first code unit is a valid
+ character start. If we are handling invalid UTF, just skip over such code
+ units. Otherwise, give an appropriate error. */
+
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ if (allow_invalid)
+ {
+ while (start_match < end_subject && NOT_FIRSTCU(*start_match))
+ {
+ start_match++;
+ skipped_bad_start = TRUE;
+ }
+ }
+ else if (start_match < end_subject && NOT_FIRSTCU(*start_match))
+ {
+ if (start_offset > 0) return PCRE2_ERROR_BADUTFOFFSET;
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ return PCRE2_ERROR_UTF8_ERR20; /* Isolated 0x80 byte */
+#else
+ return PCRE2_ERROR_UTF16_ERR3; /* Isolated low surrogate */
#endif
+ }
+#endif /* WIDTH != 32 */
+
+ /* The mb->check_subject field points to the start of UTF checking;
+ lookbehinds can go back no further than this. */
-/* Carry on with non-JIT matching. A NULL match context means "use a default
-context", but we take the memory control functions from the pattern. */
+ mb->check_subject = start_match;
+
+ /* Move back by the maximum lookbehind, just in case it happens at the very
+ start of matching, but don't do this if we skipped bad 8-bit or 16-bit code
+ units above. */
+
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ if (!skipped_bad_start)
+ {
+ unsigned int i;
+ for (i = re->max_lookbehind; i > 0 && mb->check_subject > subject; i--)
+ {
+ mb->check_subject--;
+ while (mb->check_subject > subject &&
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ (*mb->check_subject & 0xc0) == 0x80)
+#else /* 16-bit */
+ (*mb->check_subject & 0xfc00) == 0xdc00)
+#endif
+ mb->check_subject--;
+ }
+ }
+#else /* PCRE2_CODE_UNIT_WIDTH != 32 */
+
+ /* In the 32-bit library, one code unit equals one character. However,
+ we cannot just subtract the lookbehind and then compare pointers, because
+ a very large lookbehind could create an invalid pointer. */
+
+ if (start_offset >= re->max_lookbehind)
+ mb->check_subject -= re->max_lookbehind;
+ else
+ mb->check_subject = subject;
+#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */
+
+ /* Validate the relevant portion of the subject. There's a loop in case we
+ encounter bad UTF in the characters preceding start_match which we are
+ scanning because of a lookbehind. */
+
+ for (;;)
+ {
+ match_data->rc = PRIV(valid_utf)(mb->check_subject,
+ length - (mb->check_subject - subject), &(match_data->startchar));
+
+ if (match_data->rc == 0) break; /* Valid UTF string */
+
+ /* Invalid UTF string. Adjust the offset to be an absolute offset in the
+ whole string. If we are handling invalid UTF strings, set end_subject to
+ stop before the bad code unit, and set the options to "not end of line".
+ Otherwise return the error. */
+
+ match_data->startchar += mb->check_subject - subject;
+ if (!allow_invalid || match_data->rc > 0) return match_data->rc;
+ end_subject = subject + match_data->startchar;
+
+ /* If the end precedes start_match, it means there is invalid UTF in the
+ extra code units we reversed over because of a lookbehind. Advance past the
+ first bad code unit, and then skip invalid character starting code units in
+ 8-bit and 16-bit modes, and try again. */
+
+ if (end_subject < start_match)
+ {
+ mb->check_subject = end_subject + 1;
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ while (mb->check_subject < start_match && NOT_FIRSTCU(*mb->check_subject))
+ mb->check_subject++;
+#endif
+ }
+
+ /* Otherwise, set the not end of line option, and do the match. */
+
+ else
+ {
+ fragment_options = PCRE2_NOTEOL;
+ break;
+ }
+ }
+ }
+#endif /* SUPPORT_UNICODE */
+
+/* A NULL match context means "use a default context", but we take the memory
+control functions from the pattern. */
if (mcontext == NULL)
{
@@ -6186,8 +6440,8 @@ else mb->memctl = mcontext->memctl;
anchored = ((re->overall_options | options) & PCRE2_ANCHORED) != 0;
firstline = (re->overall_options & PCRE2_FIRSTLINE) != 0;
startline = (re->flags & PCRE2_STARTLINE) != 0;
-bumpalong_limit = (mcontext->offset_limit == PCRE2_UNSET)?
- end_subject : subject + mcontext->offset_limit;
+bumpalong_limit = (mcontext->offset_limit == PCRE2_UNSET)?
+ true_end_subject : subject + mcontext->offset_limit;
/* Initialize and set up the fixed fields in the callout block, with a pointer
in the match block. */
@@ -6198,7 +6452,8 @@ cb.subject = subject;
cb.subject_length = (PCRE2_SIZE)(end_subject - subject);
cb.callout_flags = 0;
-/* Fill in the remaining fields in the match block. */
+/* Fill in the remaining fields in the match block, except for moptions, which
+gets set later. */
mb->callout = mcontext->callout;
mb->callout_data = mcontext->callout_data;
@@ -6207,13 +6462,11 @@ mb->start_subject = subject;
mb->start_offset = start_offset;
mb->end_subject = end_subject;
mb->hasthen = (re->flags & PCRE2_HASTHEN) != 0;
-
-mb->moptions = options; /* Match options */
-mb->poptions = re->overall_options; /* Pattern options */
-
+mb->allowemptypartial = (re->max_lookbehind > 0) ||
+ (re->flags & PCRE2_MATCH_EMPTY) != 0;
+mb->poptions = re->overall_options; /* Pattern options */
mb->ignore_skip_arg = 0;
-mb->mark = mb->nomatch_mark = NULL; /* In case never set */
-mb->hitend = FALSE;
+mb->mark = mb->nomatch_mark = NULL; /* In case never set */
/* The name table is needed for finding all the numbers associated with a
given name, for condition testing. The code follows the name table. */
@@ -6366,6 +6619,13 @@ if ((re->flags & PCRE2_LASTSET) != 0)
/* Loop for handling unanchored repeated matching attempts; for anchored regexs
the loop runs just once. */
+#ifdef SUPPORT_UNICODE
+FRAGMENT_RESTART:
+#endif
+
+start_partial = match_partial = NULL;
+mb->hitend = FALSE;
+
for(;;)
{
PCRE2_SPTR new_start_match;
@@ -6421,7 +6681,7 @@ for(;;)
#if PCRE2_CODE_UNIT_WIDTH != 8
if (c > 255) c = 255;
#endif
- ok = (start_bits[c/8] & (1 << (c&7))) != 0;
+ ok = (start_bits[c/8] & (1u << (c&7))) != 0;
}
}
if (!ok)
@@ -6435,7 +6695,10 @@ for(;;)
/* Not anchored. Advance to a unique first code unit if there is one. In
8-bit mode, the use of memchr() gives a big speed up, even though we have
to call it twice in caseless mode, in order to find the earliest occurrence
- of the character in either of its cases. */
+ of the character in either of its cases. If a call to memchr() that
+ searches the rest of the subject fails to find one case, remember that in
+ order not to keep on repeating the search. This can make a huge difference
+ when the strings are very long and only one case is present. */
else
{
@@ -6449,11 +6712,29 @@ for(;;)
(smc = UCHAR21TEST(start_match)) != first_cu &&
smc != first_cu2)
start_match++;
+
#else /* 8-bit code units */
- PCRE2_SPTR pp1 =
- memchr(start_match, first_cu, end_subject-start_match);
- PCRE2_SPTR pp2 =
- memchr(start_match, first_cu2, end_subject-start_match);
+ PCRE2_SPTR pp1 = NULL;
+ PCRE2_SPTR pp2 = NULL;
+ PCRE2_SIZE cu2size = end_subject - start_match;
+
+ if (!memchr_not_found_first_cu)
+ {
+ pp1 = memchr(start_match, first_cu, end_subject - start_match);
+ if (pp1 == NULL) memchr_not_found_first_cu = TRUE;
+ else cu2size = pp1 - start_match;
+ }
+
+ /* If pp1 is not NULL, we have arranged to search only as far as pp1,
+ to see if the other case is earlier, so we can set "not found" only
+ when both searches have returned NULL. */
+
+ if (!memchr_not_found_first_cu2)
+ {
+ pp2 = memchr(start_match, first_cu2, cu2size);
+ memchr_not_found_first_cu2 = (pp2 == NULL && pp1 == NULL);
+ }
+
if (pp1 == NULL)
start_match = (pp2 == NULL)? end_subject : pp2;
else
@@ -6485,7 +6766,7 @@ for(;;)
we also let the cycle run, because the matching string is legitimately
allowed to start with the first code unit of a newline. */
- if (!mb->partial && start_match >= mb->end_subject)
+ if (mb->partial == 0 && start_match >= mb->end_subject)
{
rc = MATCH_NOMATCH;
break;
@@ -6538,13 +6819,13 @@ for(;;)
#if PCRE2_CODE_UNIT_WIDTH != 8
if (c > 255) c = 255;
#endif
- if ((start_bits[c/8] & (1 << (c&7))) != 0) break;
+ if ((start_bits[c/8] & (1u << (c&7))) != 0) break;
start_match++;
}
/* See comment above in first_cu checking about the next few lines. */
- if (!mb->partial && start_match >= mb->end_subject)
+ if (mb->partial == 0 && start_match >= mb->end_subject)
{
rc = MATCH_NOMATCH;
break;
@@ -6558,8 +6839,10 @@ for(;;)
/* The following two optimizations must be disabled for partial matching. */
- if (!mb->partial)
+ if (mb->partial == 0)
{
+ PCRE2_SPTR p;
+
/* The minimum matching length is a lower bound; no string of that length
may actually match the pattern. Although the value is, strictly, in
characters, we treat it as code units to avoid spending too much time in
@@ -6583,60 +6866,57 @@ for(;;)
memchr() twice in the caseless case because we only need to check for the
presence of the character in either case, not find the first occurrence.
+ The search can be skipped if the code unit was found later than the
+ current starting point in a previous iteration of the bumpalong loop.
+
HOWEVER: when the subject string is very, very long, searching to its end
can take a long time, and give bad performance on quite ordinary
- patterns. This showed up when somebody was matching something like
- /^\d+C/ on a 32-megabyte string... so we don't do this when the string is
- sufficiently long. */
+ anchored patterns. This showed up when somebody was matching something
+ like /^\d+C/ on a 32-megabyte string... so we don't do this when the
+ string is sufficiently long, but it's worth searching a lot more for
+ unanchored patterns. */
- if (has_req_cu && end_subject - start_match < REQ_CU_MAX)
+ p = start_match + (has_first_cu? 1:0);
+ if (has_req_cu && p > req_cu_ptr)
{
- PCRE2_SPTR p = start_match + (has_first_cu? 1:0);
-
- /* We don't need to repeat the search if we haven't yet reached the
- place we found it last time round the bumpalong loop. */
+ PCRE2_SIZE check_length = end_subject - start_match;
- if (p > req_cu_ptr)
+ if (check_length < REQ_CU_MAX ||
+ (!anchored && check_length < REQ_CU_MAX * 1000))
{
- if (p < end_subject)
+ if (req_cu != req_cu2) /* Caseless */
{
- if (req_cu != req_cu2) /* Caseless */
- {
#if PCRE2_CODE_UNIT_WIDTH != 8
- do
- {
- uint32_t pp = UCHAR21INCTEST(p);
- if (pp == req_cu || pp == req_cu2) { p--; break; }
- }
- while (p < end_subject);
-
+ while (p < end_subject)
+ {
+ uint32_t pp = UCHAR21INCTEST(p);
+ if (pp == req_cu || pp == req_cu2) { p--; break; }
+ }
#else /* 8-bit code units */
- PCRE2_SPTR pp = p;
- p = memchr(pp, req_cu, end_subject - pp);
- if (p == NULL)
- {
- p = memchr(pp, req_cu2, end_subject - pp);
- if (p == NULL) p = end_subject;
- }
-#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */
+ PCRE2_SPTR pp = p;
+ p = memchr(pp, req_cu, end_subject - pp);
+ if (p == NULL)
+ {
+ p = memchr(pp, req_cu2, end_subject - pp);
+ if (p == NULL) p = end_subject;
}
+#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */
+ }
- /* The caseful case */
+ /* The caseful case */
- else
- {
+ else
+ {
#if PCRE2_CODE_UNIT_WIDTH != 8
- do
- {
- if (UCHAR21INCTEST(p) == req_cu) { p--; break; }
- }
- while (p < end_subject);
+ while (p < end_subject)
+ {
+ if (UCHAR21INCTEST(p) == req_cu) { p--; break; }
+ }
#else /* 8-bit code units */
- p = memchr(p, req_cu, end_subject - p);
- if (p == NULL) p = end_subject;
+ p = memchr(p, req_cu, end_subject - p);
+ if (p == NULL) p = end_subject;
#endif
- }
}
/* If we can't find the required code unit, break the bumpalong loop,
@@ -6676,6 +6956,11 @@ for(;;)
mb->start_used_ptr = start_match;
mb->last_used_ptr = start_match;
+#ifdef SUPPORT_UNICODE
+ mb->moptions = options | fragment_options;
+#else
+ mb->moptions = options;
+#endif
mb->match_call_count = 0;
mb->end_offset_top = 0;
mb->skip_arg_count = 0;
@@ -6801,6 +7086,68 @@ for(;;)
ENDLOOP:
+/* If end_subject != true_end_subject, it means we are handling invalid UTF,
+and have just processed a non-terminal fragment. If this resulted in no match
+or a partial match we must carry on to the next fragment (a partial match is
+returned to the caller only at the very end of the subject). A loop is used to
+avoid trying to match against empty fragments; if the pattern can match an
+empty string it would have done so already. */
+
+#ifdef SUPPORT_UNICODE
+if (utf && end_subject != true_end_subject &&
+ (rc == MATCH_NOMATCH || rc == PCRE2_ERROR_PARTIAL))
+ {
+ for (;;)
+ {
+ /* Advance past the first bad code unit, and then skip invalid character
+ starting code units in 8-bit and 16-bit modes. */
+
+ start_match = end_subject + 1;
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ while (start_match < true_end_subject && NOT_FIRSTCU(*start_match))
+ start_match++;
+#endif
+
+ /* If we have hit the end of the subject, there isn't another non-empty
+ fragment, so give up. */
+
+ if (start_match >= true_end_subject)
+ {
+ rc = MATCH_NOMATCH; /* In case it was partial */
+ break;
+ }
+
+ /* Check the rest of the subject */
+
+ mb->check_subject = start_match;
+ rc = PRIV(valid_utf)(start_match, length - (start_match - subject),
+ &(match_data->startchar));
+
+ /* The rest of the subject is valid UTF. */
+
+ if (rc == 0)
+ {
+ mb->end_subject = end_subject = true_end_subject;
+ fragment_options = PCRE2_NOTBOL;
+ goto FRAGMENT_RESTART;
+ }
+
+ /* A subsequent UTF error has been found; if the next fragment is
+ non-empty, set up to process it. Otherwise, let the loop advance. */
+
+ else if (rc < 0)
+ {
+ mb->end_subject = end_subject = start_match + match_data->startchar;
+ if (end_subject > start_match)
+ {
+ fragment_options = PCRE2_NOTBOL|PCRE2_NOTEOL;
+ goto FRAGMENT_RESTART;
+ }
+ }
+ }
+ }
+#endif /* SUPPORT_UNICODE */
+
/* Release an enlarged frame vector that is on the heap. */
if (mb->match_frames != mb->stack_frames)
@@ -6809,13 +7156,13 @@ if (mb->match_frames != mb->stack_frames)
/* Fill in fields that are always returned in the match data. */
match_data->code = re;
-match_data->subject = subject;
match_data->mark = mb->mark;
match_data->matchedby = PCRE2_MATCHEDBY_INTERPRETER;
/* Handle a fully successful match. Set the return code to the number of
captured strings, or 0 if there were too many to fit into the ovector, and then
-set the remaining returned values before returning. */
+set the remaining returned values before returning. Make a copy of the subject
+string if requested. */
if (rc == MATCH_MATCH)
{
@@ -6825,6 +7172,16 @@ if (rc == MATCH_MATCH)
match_data->leftchar = mb->start_used_ptr - subject;
match_data->rightchar = ((mb->last_used_ptr > mb->end_match_ptr)?
mb->last_used_ptr : mb->end_match_ptr) - subject;
+ if ((options & PCRE2_COPY_MATCHED_SUBJECT) != 0)
+ {
+ length = CU2BYTES(length + was_zero_terminated);
+ match_data->subject = match_data->memctl.malloc(length,
+ match_data->memctl.memory_data);
+ if (match_data->subject == NULL) return PCRE2_ERROR_NOMEMORY;
+ memcpy((void *)match_data->subject, subject, length);
+ match_data->flags |= PCRE2_MD_COPIED_SUBJECT;
+ }
+ else match_data->subject = subject;
return match_data->rc;
}
@@ -6838,10 +7195,14 @@ match_data->mark = mb->nomatch_mark;
if (rc != MATCH_NOMATCH && rc != PCRE2_ERROR_PARTIAL) match_data->rc = rc;
-/* Handle a partial match. */
+/* Handle a partial match. If a "soft" partial match was requested, searching
+for a complete match will have continued, and the value of rc at this point
+will be MATCH_NOMATCH. For a "hard" partial match, it will already be
+PCRE2_ERROR_PARTIAL. */
else if (match_partial != NULL)
{
+ match_data->subject = subject;
match_data->ovector[0] = match_partial - subject;
match_data->ovector[1] = end_subject - subject;
match_data->startchar = match_partial - subject;
diff --git a/src/pcre2_match_data.c b/src/pcre2_match_data.c
index b297f32..53e4698 100644
--- a/src/pcre2_match_data.c
+++ b/src/pcre2_match_data.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2017 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -63,6 +63,7 @@ yield = PRIV(memctl_malloc)(
(pcre2_memctl *)gcontext);
if (yield == NULL) return NULL;
yield->oveccount = oveccount;
+yield->flags = 0;
return yield;
}
@@ -93,7 +94,12 @@ PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
pcre2_match_data_free(pcre2_match_data *match_data)
{
if (match_data != NULL)
+ {
+ if ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0)
+ match_data->memctl.free((void *)match_data->subject,
+ match_data->memctl.memory_data);
match_data->memctl.free(match_data, match_data->memctl.memory_data);
+ }
}
@@ -144,4 +150,17 @@ pcre2_get_startchar(pcre2_match_data *match_data)
return match_data->startchar;
}
+
+
+/*************************************************
+* Get size of match data block *
+*************************************************/
+
+PCRE2_EXP_DEFN PCRE2_SIZE PCRE2_CALL_CONVENTION
+pcre2_get_match_data_size(pcre2_match_data *match_data)
+{
+return offsetof(pcre2_match_data, ovector) +
+ 2 * (match_data->oveccount) * sizeof(PCRE2_SIZE);
+}
+
/* End of pcre2_match_data.c */
diff --git a/src/pcre2_printint.c b/src/pcre2_printint.c
index bd10c6b..b9bab02 100644
--- a/src/pcre2_printint.c
+++ b/src/pcre2_printint.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -392,7 +392,10 @@ for(;;)
case OP_ASSERT_NOT:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
+ case OP_ASSERT_NA:
+ case OP_ASSERTBACK_NA:
case OP_ONCE:
+ case OP_SCRIPT_RUN:
case OP_COND:
case OP_SCOND:
case OP_REVERSE:
@@ -672,17 +675,18 @@ for(;;)
map = (uint8_t *)ccode;
if (invertmap)
{
- for (i = 0; i < 32; i++) inverted_map[i] = ~map[i];
+ /* Using 255 ^ instead of ~ avoids clang sanitize warning. */
+ for (i = 0; i < 32; i++) inverted_map[i] = 255 ^ map[i];
map = inverted_map;
}
for (i = 0; i < 256; i++)
{
- if ((map[i/8] & (1 << (i&7))) != 0)
+ if ((map[i/8] & (1u << (i&7))) != 0)
{
int j;
for (j = i+1; j < 256; j++)
- if ((map[j/8] & (1 << (j&7))) == 0) break;
+ if ((map[j/8] & (1u << (j&7))) == 0) break;
if (i == '-' || i == ']') fprintf(f, "\\");
if (PRINTABLE(i)) fprintf(f, "%c", i);
else fprintf(f, "\\x%02x", i);
diff --git a/src/pcre2_script_run.c b/src/pcre2_script_run.c
new file mode 100644
index 0000000..91a4833
--- /dev/null
+++ b/src/pcre2_script_run.c
@@ -0,0 +1,441 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016-2018 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+/* This module contains the function for checking a script run. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre2_internal.h"
+
+
+/*************************************************
+* Check script run *
+*************************************************/
+
+/* A script run is conceptually a sequence of characters all in the same
+Unicode script. However, it isn't quite that simple. There are special rules
+for scripts that are commonly used together, and also special rules for digits.
+This function implements the appropriate checks, which is possible only when
+PCRE2 is compiled with Unicode support. The function returns TRUE if there is
+no Unicode support; however, it should never be called in that circumstance
+because an error is given by pcre2_compile() if a script run is called for in a
+version of PCRE2 compiled without Unicode support.
+
+Arguments:
+ pgr point to the first character
+ endptr point after the last character
+ utf TRUE if in UTF mode
+
+Returns: TRUE if this is a valid script run
+*/
+
+/* These dummy values must be less than the negation of the largest offset in
+the PRIV(ucd_script_sets) vector, which is held in a 16-bit field in UCD
+records (and is only likely to be a few hundred). */
+
+#define SCRIPT_UNSET (-99999)
+#define SCRIPT_HANPENDING (-99998)
+#define SCRIPT_HANHIRAKATA (-99997)
+#define SCRIPT_HANBOPOMOFO (-99996)
+#define SCRIPT_HANHANGUL (-99995)
+#define SCRIPT_LIST (-99994)
+
+#define INTERSECTION_LIST_SIZE 50
+
+BOOL
+PRIV(script_run)(PCRE2_SPTR ptr, PCRE2_SPTR endptr, BOOL utf)
+{
+#ifdef SUPPORT_UNICODE
+int require_script = SCRIPT_UNSET;
+uint8_t intersection_list[INTERSECTION_LIST_SIZE];
+const uint8_t *require_list = NULL;
+uint32_t require_digitset = 0;
+uint32_t c;
+
+#if PCRE2_CODE_UNIT_WIDTH == 32
+(void)utf; /* Avoid compiler warning */
+#endif
+
+/* Any string containing fewer than 2 characters is a valid script run. */
+
+if (ptr >= endptr) return TRUE;
+GETCHARINCTEST(c, ptr);
+if (ptr >= endptr) return TRUE;
+
+/* Scan strings of two or more characters, checking the Unicode characteristics
+of each code point. We make use of the Script Extensions property. There is
+special code for scripts that can be combined with characters from the Han
+Chinese script. This may be used in conjunction with four other scripts in
+these combinations:
+
+. Han with Hiragana and Katakana is allowed (for Japanese).
+. Han with Bopomofo is allowed (for Taiwanese Mandarin).
+. Han with Hangul is allowed (for Korean).
+
+If the first significant character's script is one of the four, the required
+script type is immediately known. However, if the first significant
+character's script is Han, we have to keep checking for a non-Han character.
+Hence the SCRIPT_HANPENDING state. */
+
+for (;;)
+ {
+ const ucd_record *ucd = GET_UCD(c);
+ int32_t scriptx = ucd->scriptx;
+
+ /* If the script extension is Unknown, the string is not a valid script run.
+ Such characters can only form script runs of length one. */
+
+ if (scriptx == ucp_Unknown) return FALSE;
+
+ /* A character whose script extension is Inherited is always accepted with
+ any script, and plays no further part in this testing. A character whose
+ script is Common is always accepted, but must still be tested for a digit
+ below. The scriptx value at this point is non-zero, because zero is
+ ucp_Unknown, tested for above. */
+
+ if (scriptx != ucp_Inherited)
+ {
+ if (scriptx != ucp_Common)
+ {
+ /* If the script extension value is positive, the character is not a mark
+ that can be used with many scripts. In the simple case we either set or
+ compare with the required script. However, handling the scripts that can
+ combine with Han are more complicated, as is the case when the previous
+ characters have been man-script marks. */
+
+ if (scriptx > 0)
+ {
+ switch(require_script)
+ {
+ /* Either the first significant character (require_script unset) or
+ after only Han characters. */
+
+ case SCRIPT_UNSET:
+ case SCRIPT_HANPENDING:
+ switch(scriptx)
+ {
+ case ucp_Han:
+ require_script = SCRIPT_HANPENDING;
+ break;
+
+ case ucp_Hiragana:
+ case ucp_Katakana:
+ require_script = SCRIPT_HANHIRAKATA;
+ break;
+
+ case ucp_Bopomofo:
+ require_script = SCRIPT_HANBOPOMOFO;
+ break;
+
+ case ucp_Hangul:
+ require_script = SCRIPT_HANHANGUL;
+ break;
+
+ /* Not a Han-related script. If expecting one, fail. Otherise set
+ the requirement to this script. */
+
+ default:
+ if (require_script == SCRIPT_HANPENDING) return FALSE;
+ require_script = scriptx;
+ break;
+ }
+ break;
+
+ /* Previously encountered one of the "with Han" scripts. Check that
+ this character is appropriate. */
+
+ case SCRIPT_HANHIRAKATA:
+ if (scriptx != ucp_Han && scriptx != ucp_Hiragana &&
+ scriptx != ucp_Katakana)
+ return FALSE;
+ break;
+
+ case SCRIPT_HANBOPOMOFO:
+ if (scriptx != ucp_Han && scriptx != ucp_Bopomofo) return FALSE;
+ break;
+
+ case SCRIPT_HANHANGUL:
+ if (scriptx != ucp_Han && scriptx != ucp_Hangul) return FALSE;
+ break;
+
+ /* We have a list of scripts to check that is derived from one or
+ more previous characters. This is either one of the lists in
+ ucd_script_sets[] (for one previous character) or the intersection of
+ several lists for multiple characters. */
+
+ case SCRIPT_LIST:
+ {
+ const uint8_t *list;
+ for (list = require_list; *list != 0; list++)
+ {
+ if (*list == scriptx) break;
+ }
+ if (*list == 0) return FALSE;
+ }
+
+ /* The rest of the string must be in this script, but we have to
+ allow for the Han complications. */
+
+ switch(scriptx)
+ {
+ case ucp_Han:
+ require_script = SCRIPT_HANPENDING;
+ break;
+
+ case ucp_Hiragana:
+ case ucp_Katakana:
+ require_script = SCRIPT_HANHIRAKATA;
+ break;
+
+ case ucp_Bopomofo:
+ require_script = SCRIPT_HANBOPOMOFO;
+ break;
+
+ case ucp_Hangul:
+ require_script = SCRIPT_HANHANGUL;
+ break;
+
+ default:
+ require_script = scriptx;
+ break;
+ }
+ break;
+
+ /* This is the easy case when a single script is required. */
+
+ default:
+ if (scriptx != require_script) return FALSE;
+ break;
+ }
+ } /* End of handing positive scriptx */
+
+ /* If scriptx is negative, this character is a mark-type character that
+ has a list of permitted scripts. */
+
+ else
+ {
+ uint32_t chspecial;
+ const uint8_t *clist, *rlist;
+ const uint8_t *list = PRIV(ucd_script_sets) - scriptx;
+
+ switch(require_script)
+ {
+ case SCRIPT_UNSET:
+ require_list = PRIV(ucd_script_sets) - scriptx;
+ require_script = SCRIPT_LIST;
+ break;
+
+ /* An inspection of the Unicode 11.0.0 files shows that there are the
+ following types of Script Extension list that involve the Han,
+ Bopomofo, Hiragana, Katakana, and Hangul scripts:
+
+ . Bopomofo + Han
+ . Han + Hiragana + Katakana
+ . Hiragana + Katakana
+ . Bopopmofo + Hangul + Han + Hiragana + Katakana
+
+ The following code tries to make sense of this. */
+
+#define FOUND_BOPOMOFO 1
+#define FOUND_HIRAGANA 2
+#define FOUND_KATAKANA 4
+#define FOUND_HANGUL 8
+
+ case SCRIPT_HANPENDING:
+ chspecial = 0;
+ for (; *list != 0; list++)
+ {
+ switch (*list)
+ {
+ case ucp_Bopomofo: chspecial |= FOUND_BOPOMOFO; break;
+ case ucp_Hiragana: chspecial |= FOUND_HIRAGANA; break;
+ case ucp_Katakana: chspecial |= FOUND_KATAKANA; break;
+ case ucp_Hangul: chspecial |= FOUND_HANGUL; break;
+ default: break;
+ }
+ }
+
+ if (chspecial == 0) return FALSE;
+
+ if (chspecial == FOUND_BOPOMOFO)
+ {
+ require_script = SCRIPT_HANBOPOMOFO;
+ }
+ else if (chspecial == (FOUND_HIRAGANA|FOUND_KATAKANA))
+ {
+ require_script = SCRIPT_HANHIRAKATA;
+ }
+
+ /* Otherwise it must be allowed with all of them, so remain in
+ the pending state. */
+
+ break;
+
+ case SCRIPT_HANHIRAKATA:
+ for (; *list != 0; list++)
+ {
+ if (*list == ucp_Hiragana || *list == ucp_Katakana) break;
+ }
+ if (*list == 0) return FALSE;
+ break;
+
+ case SCRIPT_HANBOPOMOFO:
+ for (; *list != 0; list++)
+ {
+ if (*list == ucp_Bopomofo) break;
+ }
+ if (*list == 0) return FALSE;
+ break;
+
+ case SCRIPT_HANHANGUL:
+ for (; *list != 0; list++)
+ {
+ if (*list == ucp_Hangul) break;
+ }
+ if (*list == 0) return FALSE;
+ break;
+
+ /* Previously encountered one or more characters that are allowed
+ with a list of scripts. Build the intersection of the required list
+ with this character's list in intersection_list[]. This code is
+ written so that it still works OK if the required list is already in
+ that vector. */
+
+ case SCRIPT_LIST:
+ {
+ int i = 0;
+ for (rlist = require_list; *rlist != 0; rlist++)
+ {
+ for (clist = list; *clist != 0; clist++)
+ {
+ if (*rlist == *clist)
+ {
+ intersection_list[i++] = *rlist;
+ break;
+ }
+ }
+ }
+ if (i == 0) return FALSE; /* No scripts in common */
+
+ /* If there's just one script in common, we can set it as the
+ unique required script. Otherwise, terminate the intersection list
+ and make it the required list. */
+
+ if (i == 1)
+ {
+ require_script = intersection_list[0];
+ }
+ else
+ {
+ intersection_list[i] = 0;
+ require_list = intersection_list;
+ }
+ }
+ break;
+
+ /* The previously set required script is a single script, not
+ Han-related. Check that it is in this character's list. */
+
+ default:
+ for (; *list != 0; list++)
+ {
+ if (*list == require_script) break;
+ }
+ if (*list == 0) return FALSE;
+ break;
+ }
+ } /* End of handling negative scriptx */
+ } /* End of checking non-Common character */
+
+ /* The character is in an acceptable script. We must now ensure that all
+ decimal digits in the string come from the same set. Some scripts (e.g.
+ Common, Arabic) have more than one set of decimal digits. This code does
+ not allow mixing sets, even within the same script. The vector called
+ PRIV(ucd_digit_sets)[] contains, in its first element, the number of
+ following elements, and then, in ascending order, the code points of the
+ '9' characters in every set of 10 digits. Each set is identified by the
+ offset in the vector of its '9' character. An initial check of the first
+ value picks up ASCII digits quickly. Otherwise, a binary chop is used. */
+
+ if (ucd->chartype == ucp_Nd)
+ {
+ uint32_t digitset;
+
+ if (c <= PRIV(ucd_digit_sets)[1]) digitset = 1; else
+ {
+ int mid;
+ int bot = 1;
+ int top = PRIV(ucd_digit_sets)[0];
+ for (;;)
+ {
+ if (top <= bot + 1) /* <= rather than == is paranoia */
+ {
+ digitset = top;
+ break;
+ }
+ mid = (top + bot) / 2;
+ if (c <= PRIV(ucd_digit_sets)[mid]) top = mid; else bot = mid;
+ }
+ }
+
+ /* A required value of 0 means "unset". */
+
+ if (require_digitset == 0) require_digitset = digitset;
+ else if (digitset != require_digitset) return FALSE;
+ } /* End digit handling */
+ } /* End checking non-Inherited character */
+
+ /* If we haven't yet got to the end, pick up the next character. */
+
+ if (ptr >= endptr) return TRUE;
+ GETCHARINCTEST(c, ptr);
+ } /* End checking loop */
+
+#else /* NOT SUPPORT_UNICODE */
+(void)ptr;
+(void)endptr;
+(void)utf;
+return TRUE;
+#endif /* SUPPORT_UNICODE */
+}
+
+/* End of pcre2_script_run.c */
diff --git a/src/pcre2_study.c b/src/pcre2_study.c
index acbf98b..2883868 100644
--- a/src/pcre2_study.c
+++ b/src/pcre2_study.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -54,7 +54,7 @@ collecting data (e.g. minimum matching length). */
/* Set a bit in the starting code unit bit map. */
-#define SET_BIT(c) re->start_bitmap[(c)/8] |= (1 << ((c)&7))
+#define SET_BIT(c) re->start_bitmap[(c)/8] |= (1u << ((c)&7))
/* Returns from set_start_bits() */
@@ -88,11 +88,13 @@ Arguments:
countptr pointer to call count (to catch over complexity)
backref_cache vector for caching back references.
+This function is no longer called when the pattern contains (*ACCEPT); however,
+the old code for returning -1 is retained, just in case.
+
Returns: the minimum length
-1 \C in UTF-8 mode
or (*ACCEPT)
or pattern too complicated
- or back reference to duplicate name/number
-2 internal error (missing capturing bracket)
-3 internal error (opcode not listed)
*/
@@ -103,6 +105,7 @@ find_minlength(const pcre2_real_code *re, PCRE2_SPTR code,
int *backref_cache)
{
int length = -1;
+int branchlength = 0;
int prev_cap_recno = -1;
int prev_cap_d = 0;
int prev_recurse_recno = -1;
@@ -110,9 +113,9 @@ int prev_recurse_d = 0;
uint32_t once_fudge = 0;
BOOL had_recurse = FALSE;
BOOL dupcapused = (re->flags & PCRE2_DUPCAPUSED) != 0;
-recurse_check this_recurse;
-int branchlength = 0;
+PCRE2_SPTR nextbranch = code + GET(code, 1);
PCRE2_UCHAR *cc = (PCRE2_UCHAR *)code + 1 + LINK_SIZE;
+recurse_check this_recurse;
/* If this is a "could be empty" group, its minimum length is 0. */
@@ -128,16 +131,20 @@ if ((*countptr)++ > 1000) return -1;
/* Scan along the opcodes for this branch. If we get to the end of the branch,
check the length against that of the other branches. If the accumulated length
-passes 16-bits, stop. */
+passes 16-bits, reset to that value and skip the rest of the branch. */
for (;;)
{
int d, min, recno;
- PCRE2_UCHAR *cs, *ce;
- PCRE2_UCHAR op = *cc;
+ PCRE2_UCHAR op, *cs, *ce;
- if (branchlength >= UINT16_MAX) return UINT16_MAX;
+ if (branchlength >= UINT16_MAX)
+ {
+ branchlength = UINT16_MAX;
+ cc = (PCRE2_UCHAR *)nextbranch;
+ }
+ op = *cc;
switch (op)
{
case OP_COND:
@@ -171,6 +178,7 @@ for (;;)
/* Fall through */
case OP_ONCE:
+ case OP_SCRIPT_RUN:
case OP_SBRA:
case OP_BRAPOS:
case OP_SBRAPOS:
@@ -205,7 +213,9 @@ for (;;)
cc += 1 + LINK_SIZE;
break;
- /* ACCEPT makes things far too complicated; we have to give up. */
+ /* ACCEPT makes things far too complicated; we have to give up. In fact,
+ from 10.34 onwards, if a pattern contains (*ACCEPT), this function is not
+ used. However, leave the code in place, just in case. */
case OP_ACCEPT:
case OP_ASSERT_ACCEPT:
@@ -213,9 +223,9 @@ for (;;)
/* Reached end of a branch; if it's a ket it is the end of a nested
call. If it's ALT it is an alternation in a nested call. If it is END it's
- the end of the outer call. All can be handled by the same code. If an
- ACCEPT was previously encountered, use the length that was in force at that
- time, and pass back the shortest ACCEPT length. */
+ the end of the outer call. All can be handled by the same code. If the
+ length of any branch is zero, there is no need to scan any subsequent
+ branches. */
case OP_ALT:
case OP_KET:
@@ -225,7 +235,8 @@ for (;;)
case OP_END:
if (length < 0 || (!had_recurse && branchlength < length))
length = branchlength;
- if (op != OP_ALT) return length;
+ if (op != OP_ALT || length == 0) return length;
+ nextbranch = cc + GET(cc, 1);
cc += 1 + LINK_SIZE;
branchlength = 0;
had_recurse = FALSE;
@@ -237,6 +248,8 @@ for (;;)
case OP_ASSERT_NOT:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
+ case OP_ASSERT_NA:
+ case OP_ASSERTBACK_NA:
do cc += GET(cc, 1); while (*cc == OP_ALT);
/* Fall through */
@@ -450,15 +463,17 @@ for (;;)
If PCRE2_MATCH_UNSET_BACKREF is set, a backreference to an unset bracket
matches an empty string (by default it causes a matching failure), so in
- that case we must set the minimum length to zero. */
+ that case we must set the minimum length to zero.
+
+ For backreferenes, if duplicate numbers are present in the pattern we check
+ for a reference to a duplicate. If it is, we don't know which version will
+ be referenced, so we have to set the minimum length to zero. */
- /* Duplicate named pattern back reference. We cannot reliably find a length
- for this if duplicate numbers are present in the pattern. */
+ /* Duplicate named pattern back reference. */
case OP_DNREF:
case OP_DNREFI:
- if (dupcapused) return -1;
- if ((re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0)
+ if (!dupcapused && (re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0)
{
int count = GET2(cc, 1+IMM2_SIZE);
PCRE2_UCHAR *slot =
@@ -481,28 +496,32 @@ for (;;)
ce = cs = (PCRE2_UCHAR *)PRIV(find_bracket)(startcode, utf, recno);
if (cs == NULL) return -2;
do ce += GET(ce, 1); while (*ce == OP_ALT);
- if (cc > cs && cc < ce) /* Simple recursion */
- {
- dd = 0;
- had_recurse = TRUE;
- }
- else
+
+ dd = 0;
+ if (!dupcapused ||
+ (PCRE2_UCHAR *)PRIV(find_bracket)(ce, utf, recno) == NULL)
{
- recurse_check *r = recurses;
- for (r = recurses; r != NULL; r = r->prev)
- if (r->group == cs) break;
- if (r != NULL) /* Mutual recursion */
+ if (cc > cs && cc < ce) /* Simple recursion */
{
- dd = 0;
had_recurse = TRUE;
}
else
{
- this_recurse.prev = recurses;
- this_recurse.group = cs;
- dd = find_minlength(re, cs, startcode, utf, &this_recurse,
- countptr, backref_cache);
- if (dd < 0) return dd;
+ recurse_check *r = recurses;
+ for (r = recurses; r != NULL; r = r->prev)
+ if (r->group == cs) break;
+ if (r != NULL) /* Mutual recursion */
+ {
+ had_recurse = TRUE;
+ }
+ else
+ {
+ this_recurse.prev = recurses; /* No recursion */
+ this_recurse.group = cs;
+ dd = find_minlength(re, cs, startcode, utf, &this_recurse,
+ countptr, backref_cache);
+ if (dd < 0) return dd;
+ }
}
}
@@ -520,48 +539,51 @@ for (;;)
cc += 1 + 2*IMM2_SIZE;
goto REPEAT_BACK_REFERENCE;
- /* Single back reference. We cannot find a length for this if duplicate
- numbers are present in the pattern. */
+ /* Single back reference by number. References by name are converted to by
+ number when there is no duplication. */
case OP_REF:
case OP_REFI:
- if (dupcapused) return -1;
recno = GET2(cc, 1);
if (recno <= backref_cache[0] && backref_cache[recno] >= 0)
d = backref_cache[recno];
else
{
int i;
+ d = 0;
+
if ((re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0)
{
ce = cs = (PCRE2_UCHAR *)PRIV(find_bracket)(startcode, utf, recno);
if (cs == NULL) return -2;
do ce += GET(ce, 1); while (*ce == OP_ALT);
- if (cc > cs && cc < ce) /* Simple recursion */
- {
- d = 0;
- had_recurse = TRUE;
- }
- else
+
+ if (!dupcapused ||
+ (PCRE2_UCHAR *)PRIV(find_bracket)(ce, utf, recno) == NULL)
{
- recurse_check *r = recurses;
- for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
- if (r != NULL) /* Mutual recursion */
+ if (cc > cs && cc < ce) /* Simple recursion */
{
- d = 0;
had_recurse = TRUE;
}
else
{
- this_recurse.prev = recurses;
- this_recurse.group = cs;
- d = find_minlength(re, cs, startcode, utf, &this_recurse, countptr,
- backref_cache);
- if (d < 0) return d;
+ recurse_check *r = recurses;
+ for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
+ if (r != NULL) /* Mutual recursion */
+ {
+ had_recurse = TRUE;
+ }
+ else /* No recursion */
+ {
+ this_recurse.prev = recurses;
+ this_recurse.group = cs;
+ d = find_minlength(re, cs, startcode, utf, &this_recurse, countptr,
+ backref_cache);
+ if (d < 0) return d;
+ }
}
}
}
- else d = 0;
backref_cache[recno] = d;
for (i = backref_cache[0] + 1; i < recno; i++) backref_cache[i] = -1;
@@ -842,7 +864,7 @@ for (c = 0; c < table_limit; c++)
if (table_limit == 32) return;
for (c = 128; c < 256; c++)
{
- if ((re->tables[cbits_offset + c/8] & (1 << (c&7))) != 0)
+ if ((re->tables[cbits_offset + c/8] & (1u << (c&7))) != 0)
{
PCRE2_UCHAR buff[6];
(void)PRIV(ord2utf)(c, buff);
@@ -887,7 +909,7 @@ if (table_limit != 32) for (c = 24; c < 32; c++) re->start_bitmap[c] = 0xff;
/*************************************************
-* Create bitmap of starting bytes *
+* Create bitmap of starting code units *
*************************************************/
/* This function scans a compiled unanchored expression recursively and
@@ -937,6 +959,9 @@ do
{
int rc;
uint8_t *classmap = NULL;
+#ifdef SUPPORT_WIDE_CHARS
+ PCRE2_UCHAR xclassflags;
+#endif
switch(*tcode)
{
@@ -1075,7 +1100,9 @@ do
case OP_CBRAPOS:
case OP_SCBRAPOS:
case OP_ONCE:
+ case OP_SCRIPT_RUN:
case OP_ASSERT:
+ case OP_ASSERT_NA:
rc = set_start_bits(re, tcode, utf);
if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc;
if (rc == SSB_DONE) try_next = FALSE; else
@@ -1118,6 +1145,7 @@ do
case OP_ASSERT_NOT:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
+ case OP_ASSERTBACK_NA:
do tcode += GET(tcode, 1); while (*tcode == OP_ALT);
tcode += 1 + LINK_SIZE;
break;
@@ -1442,20 +1470,59 @@ do
negative XCLASS without a map, give up. If there are no property checks,
there must be wide characters on the XCLASS list, because otherwise an
XCLASS would not have been created. This means that code points >= 255
- are always potential starters. */
+ are potential starters. In the UTF-8 case we can scan them and set bits
+ for the relevant leading bytes. */
#ifdef SUPPORT_WIDE_CHARS
case OP_XCLASS:
- if ((tcode[1 + LINK_SIZE] & XCL_HASPROP) != 0 ||
- (tcode[1 + LINK_SIZE] & (XCL_MAP|XCL_NOT)) == XCL_NOT)
+ xclassflags = tcode[1 + LINK_SIZE];
+ if ((xclassflags & XCL_HASPROP) != 0 ||
+ (xclassflags & (XCL_MAP|XCL_NOT)) == XCL_NOT)
return SSB_FAIL;
/* We have a positive XCLASS or a negative one without a map. Set up the
map pointer if there is one, and fall through. */
- classmap = ((tcode[1 + LINK_SIZE] & XCL_MAP) == 0)? NULL :
+ classmap = ((xclassflags & XCL_MAP) == 0)? NULL :
(uint8_t *)(tcode + 1 + LINK_SIZE + 1);
-#endif
+
+ /* In UTF-8 mode, scan the character list and set bits for leading bytes,
+ then jump to handle the map. */
+
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ if (utf && (xclassflags & XCL_NOT) == 0)
+ {
+ PCRE2_UCHAR b, e;
+ PCRE2_SPTR p = tcode + 1 + LINK_SIZE + 1 + ((classmap == NULL)? 0:32);
+ tcode += GET(tcode, 1);
+
+ for (;;) switch (*p++)
+ {
+ case XCL_SINGLE:
+ b = *p++;
+ while ((*p & 0xc0) == 0x80) p++;
+ re->start_bitmap[b/8] |= (1u << (b&7));
+ break;
+
+ case XCL_RANGE:
+ b = *p++;
+ while ((*p & 0xc0) == 0x80) p++;
+ e = *p++;
+ while ((*p & 0xc0) == 0x80) p++;
+ for (; b <= e; b++)
+ re->start_bitmap[b/8] |= (1u << (b&7));
+ break;
+
+ case XCL_END:
+ goto HANDLE_CLASSMAP;
+
+ default:
+ return SSB_UNKNOWN; /* Internal error, should not occur */
+ }
+ }
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */
+#endif /* SUPPORT_WIDE_CHARS */
+
/* It seems that the fall through comment must be outside the #ifdef if
it is to avoid the gcc compiler warning. */
@@ -1497,6 +1564,9 @@ do
greater than 127. In fact, there are only two possible starting bytes for
characters in the range 128 - 255. */
+#if defined SUPPORT_WIDE_CHARS && PCRE2_CODE_UNIT_WIDTH == 8
+ HANDLE_CLASSMAP:
+#endif
if (classmap != NULL)
{
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
@@ -1505,11 +1575,11 @@ do
for (c = 0; c < 16; c++) re->start_bitmap[c] |= classmap[c];
for (c = 128; c < 256; c++)
{
- if ((classmap[c/8] & (1 << (c&7))) != 0)
+ if ((classmap[c/8] & (1u << (c&7))) != 0)
{
- int d = (c >> 6) | 0xc0; /* Set bit for this starter */
- re->start_bitmap[d/8] |= (1 << (d&7)); /* and then skip on to the */
- c = (c & 0xc0) + 0x40 - 1; /* next relevant character. */
+ int d = (c >> 6) | 0xc0; /* Set bit for this starter */
+ re->start_bitmap[d/8] |= (1u << (d&7)); /* and then skip on to the */
+ c = (c & 0xc0) + 0x40 - 1; /* next relevant character. */
}
}
}
@@ -1567,7 +1637,9 @@ return yield;
/* This function is handed a compiled expression that it must study to produce
information that will speed up the matching.
-Argument: points to the compiled expression
+Argument:
+ re points to the compiled expression
+
Returns: 0 normally; non-zero should never normally occur
1 unknown opcode in set_start_bits
2 missing capturing bracket
@@ -1577,7 +1649,6 @@ Returns: 0 normally; non-zero should never normally occur
int
PRIV(study)(pcre2_real_code *re)
{
-int min;
int count = 0;
PCRE2_UCHAR *code;
BOOL utf = (re->overall_options & PCRE2_UTF) != 0;
@@ -1595,25 +1666,121 @@ if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0)
{
int rc = set_start_bits(re, code, utf);
if (rc == SSB_UNKNOWN) return 1;
- if (rc == SSB_DONE) re->flags |= PCRE2_FIRSTMAPSET;
+
+ /* If a list of starting code units was set up, scan the list to see if only
+ one or two were listed. Having only one listed is rare because usually a
+ single starting code unit will have been recognized and PCRE2_FIRSTSET set.
+ If two are listed, see if they are caseless versions of the same character;
+ if so we can replace the list with a caseless first code unit. This gives
+ better performance and is plausibly worth doing for patterns such as [Ww]ord
+ or (word|WORD). */
+
+ if (rc == SSB_DONE)
+ {
+ int i;
+ int a = -1;
+ int b = -1;
+ uint8_t *p = re->start_bitmap;
+ uint32_t flags = PCRE2_FIRSTMAPSET;
+
+ for (i = 0; i < 256; p++, i += 8)
+ {
+ uint8_t x = *p;
+ if (x != 0)
+ {
+ int c;
+ uint8_t y = x & (~x + 1); /* Least significant bit */
+ if (y != x) goto DONE; /* More than one bit set */
+
+ /* In the 16-bit and 32-bit libraries, the bit for 0xff means "0xff and
+ all wide characters", so we cannot use it here. */
+
+#if PCRE2_CODE_UNIT_WIDTH != 8
+ if (i == 248 && x == 0x80) goto DONE;
+#endif
+
+ /* Compute the character value */
+
+ c = i;
+ switch (x)
+ {
+ case 1: break;
+ case 2: c += 1; break; case 4: c += 2; break;
+ case 8: c += 3; break; case 16: c += 4; break;
+ case 32: c += 5; break; case 64: c += 6; break;
+ case 128: c += 7; break;
+ }
+
+ /* c contains the code unit value, in the range 0-255. In 8-bit UTF
+ mode, only values < 128 can be used. */
+
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ if (c > 127) goto DONE;
+#endif
+ if (a < 0) a = c; /* First one found */
+ else if (b < 0) /* Second one found */
+ {
+ int d = TABLE_GET((unsigned int)c, re->tables + fcc_offset, c);
+
+#ifdef SUPPORT_UNICODE
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ if (utf && UCD_CASESET(c) != 0) goto DONE; /* Multiple case set */
+#else /* 16-bit or 32-bit */
+ if (UCD_CASESET(c) != 0) goto DONE; /* Multiple case set */
+ if (utf && c > 127) d = UCD_OTHERCASE(c);
+#endif /* Code width */
+#endif /* SUPPORT_UNICODE */
+
+ if (d != a) goto DONE; /* Not other case of a */
+ b = c;
+ }
+ else goto DONE; /* More than two characters found */
+ }
+ }
+
+ /* Replace the start code unit bits with a first code unit, but only if it
+ is not the same as a required later code unit. This is because a search for
+ a required code unit starts after an explicit first code unit, but at a
+ code unit found from the bitmap. Patterns such as /a*a/ don't work
+ if both the start unit and required unit are the same. */
+
+ if (a >= 0 &&
+ (
+ (re->flags & PCRE2_LASTSET) == 0 ||
+ (
+ re->last_codeunit != (uint32_t)a &&
+ (b < 0 || re->last_codeunit != (uint32_t)b)
+ )
+ ))
+ {
+ re->first_codeunit = a;
+ flags = PCRE2_FIRSTSET;
+ if (b >= 0) flags |= PCRE2_FIRSTCASELESS;
+ }
+
+ DONE:
+ re->flags |= flags;
+ }
}
/* Find the minimum length of subject string. If the pattern can match an empty
-string, the minimum length is already known. If there are more back references
-than the size of the vector we are going to cache them in, do nothing. A
-pattern that complicated will probably take a long time to analyze and may in
-any case turn out to be too complicated. Note that back reference minima are
-held as 16-bit numbers. */
-
-if ((re->flags & PCRE2_MATCH_EMPTY) == 0 &&
+string, the minimum length is already known. If the pattern contains (*ACCEPT)
+all bets are off, and we don't even try to find a minimum length. If there are
+more back references than the size of the vector we are going to cache them in,
+do nothing. A pattern that complicated will probably take a long time to
+analyze and may in any case turn out to be too complicated. Note that back
+reference minima are held as 16-bit numbers. */
+
+if ((re->flags & (PCRE2_MATCH_EMPTY|PCRE2_HASACCEPT)) == 0 &&
re->top_backref <= MAX_CACHE_BACKREF)
{
+ int min;
int backref_cache[MAX_CACHE_BACKREF+1];
backref_cache[0] = 0; /* Highest one that is set */
min = find_minlength(re, code, code, utf, NULL, &count, backref_cache);
switch(min)
{
- case -1: /* \C in UTF mode or (*ACCEPT) or over-complex regex */
+ case -1: /* \C in UTF mode or over-complex regex */
break; /* Leave minlength unchanged (will be zero) */
case -2:
@@ -1623,8 +1790,7 @@ if ((re->flags & PCRE2_MATCH_EMPTY) == 0 &&
return 3; /* unrecognized opcode */
default:
- if (min > UINT16_MAX) min = UINT16_MAX;
- re->minlength = min;
+ re->minlength = (min > UINT16_MAX)? UINT16_MAX : min;
break;
}
}
diff --git a/src/pcre2_substitute.c b/src/pcre2_substitute.c
index ab8d109..ec3dd66 100644
--- a/src/pcre2_substitute.c
+++ b/src/pcre2_substitute.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -129,7 +129,7 @@ for (; ptr < ptrend; ptr++)
ptr += 1; /* Must point after \ */
erc = PRIV(check_escape)(&ptr, ptrend, &ch, &errorcode,
- code->overall_options, FALSE, NULL);
+ code->overall_options, code->extra_options, FALSE, NULL);
ptr -= 1; /* Back to last code unit of escape */
if (errorcode != 0)
{
@@ -239,13 +239,17 @@ PCRE2_SIZE extra_needed = 0;
PCRE2_SIZE buff_offset, buff_length, lengthleft, fraglength;
PCRE2_SIZE *ovector;
PCRE2_SIZE ovecsave[3];
+pcre2_substitute_callout_block scb;
+
+/* General initialization */
buff_offset = 0;
lengthleft = buff_length = *blength;
*blength = PCRE2_UNSET;
ovecsave[0] = ovecsave[1] = ovecsave[2] = PCRE2_UNSET;
-/* Partial matching is not valid. */
+/* Partial matching is not valid. This must come after setting *blength to
+PCRE2_UNSET, so as not to imply an offset in the replacement. */
if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0)
return PCRE2_ERROR_BADOPTION;
@@ -264,6 +268,13 @@ if (match_data == NULL)
ovector = pcre2_get_ovector_pointer(match_data);
ovector_count = pcre2_get_ovector_count(match_data);
+/* Fixed things in the callout block */
+
+scb.version = 0;
+scb.input = subject;
+scb.output = (PCRE2_SPTR)buffer;
+scb.ovector = ovector;
+
/* Find lengths of zero-terminated strings and the end of the replacement. */
if (length == PCRE2_ZERO_TERMINATED) length = PRIV(strlen)(subject);
@@ -390,7 +401,7 @@ do
rc = PCRE2_ERROR_INTERNAL_DUPMATCH;
goto EXIT;
}
-
+
/* Count substitutions with a paranoid check for integer overflow; surely no
real call to this function would ever hit this! */
@@ -401,11 +412,14 @@ do
}
subs++;
- /* Copy the text leading up to the match. */
+ /* Copy the text leading up to the match, and remember where the insert
+ begins and how many ovector pairs are set. */
if (rc == 0) rc = ovector_count;
fraglength = ovector[0] - start_offset;
CHECKMEMCPY(subject + start_offset, fraglength);
+ scb.output_offsets[0] = buff_offset;
+ scb.oveccount = rc;
/* Process the replacement string. Literal mode is set by \Q, but only in
extended mode when backslashes are being interpreted. In extended mode we
@@ -421,7 +435,7 @@ do
if (ptr >= repend)
{
- if (ptrstackptr <= 0) break; /* End of replacement string */
+ if (ptrstackptr == 0) break; /* End of replacement string */
repend = ptrstack[--ptrstackptr];
ptr = ptrstack[--ptrstackptr];
continue;
@@ -702,7 +716,7 @@ do
{
if (((code->tables + cbits_offset +
((forcecase > 0)? cbit_upper:cbit_lower)
- )[ch/8] & (1 << (ch%8))) == 0)
+ )[ch/8] & (1u << (ch%8))) == 0)
ch = (code->tables + fcc_offset)[ch];
}
forcecase = forcecasereset;
@@ -760,7 +774,7 @@ do
ptr++; /* Point after \ */
rc = PRIV(check_escape)(&ptr, repend, &ch, &errorcode,
- code->overall_options, FALSE, NULL);
+ code->overall_options, code->extra_options, FALSE, NULL);
if (errorcode != 0) goto BADESCAPE;
switch(rc)
@@ -804,7 +818,7 @@ do
{
if (((code->tables + cbits_offset +
((forcecase > 0)? cbit_upper:cbit_lower)
- )[ch/8] & (1 << (ch%8))) == 0)
+ )[ch/8] & (1u << (ch%8))) == 0)
ch = (code->tables + fcc_offset)[ch];
}
forcecase = forcecasereset;
@@ -821,10 +835,37 @@ do
} /* End handling a literal code unit */
} /* End of loop for scanning the replacement. */
- /* The replacement has been copied to the output. Save the details of this
- match. See above for how this data is used. If we matched an empty string, do
- the magic for global matches. Finally, update the start offset to point to
- the rest of the subject string. */
+ /* The replacement has been copied to the output, or its size has been
+ remembered. Do the callout if there is one and we have done an actual
+ replacement. */
+
+ if (!overflowed && mcontext != NULL && mcontext->substitute_callout != NULL)
+ {
+ scb.subscount = subs;
+ scb.output_offsets[1] = buff_offset;
+ rc = mcontext->substitute_callout(&scb, mcontext->substitute_callout_data);
+
+ /* A non-zero return means cancel this substitution. Instead, copy the
+ matched string fragment. */
+
+ if (rc != 0)
+ {
+ PCRE2_SIZE newlength = scb.output_offsets[1] - scb.output_offsets[0];
+ PCRE2_SIZE oldlength = ovector[1] - ovector[0];
+
+ buff_offset -= newlength;
+ lengthleft += newlength;
+ CHECKMEMCPY(subject + ovector[0], oldlength);
+
+ /* A negative return means do not do any more. */
+
+ if (rc < 0) suboptions &= (~PCRE2_SUBSTITUTE_GLOBAL);
+ }
+ }
+
+ /* Save the details of this match. See above for how this data is used. If we
+ matched an empty string, do the magic for global matches. Finally, update the
+ start offset to point to the rest of the subject string. */
ovecsave[0] = ovector[0];
ovecsave[1] = ovector[1];
diff --git a/src/pcre2_tables.c b/src/pcre2_tables.c
index 83d6f9d..25531d9 100644
--- a/src/pcre2_tables.c
+++ b/src/pcre2_tables.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -142,7 +142,7 @@ ucp_gbXX values defined in pcre2_ucp.h. These changed between Unicode versions
code points. The left property selects a word from the table, and the right
property selects a bit from that word like this:
- PRIV(ucp_gbtable)[left-property] & (1 << right-property)
+ PRIV(ucp_gbtable)[left-property] & (1u << right-property)
The value is non-zero if a grapheme break is NOT permitted between the relevant
two code points. The breaking rules are as follows:
@@ -183,25 +183,25 @@ are implementing).
#define ESZ (1< /* For _setmode() */
#include /* For _O_BINARY */
#endif
-#ifdef SUPPORT_PCRE2GREP_CALLOUT
+#if defined(SUPPORT_PCRE2GREP_CALLOUT) && defined(SUPPORT_PCRE2GREP_CALLOUT_FORK)
#ifdef WIN32
#include
#else
@@ -104,12 +110,25 @@ MSVC 10/2010. Except for VC6 (which is missing some fundamentals and fails). */
#define snprintf _snprintf
#endif
+/* VC and older compilers don't support %td or %zu, and even some that claim to
+be C99 don't support it (hence DISABLE_PERCENT_ZT). */
+
+#if defined(_MSC_VER) || !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L || defined(DISABLE_PERCENT_ZT)
+#define PTR_FORM "lu"
+#define SIZ_FORM "lu"
+#define SIZ_CAST (unsigned long int)
+#else
+#define PTR_FORM "td"
+#define SIZ_FORM "zu"
+#define SIZ_CAST
+#endif
+
#define FALSE 0
#define TRUE 1
typedef int BOOL;
-#define OFFSET_SIZE 33
+#define DEFAULT_CAPTURE_MAX 50
#if BUFSIZ > 8192
#define MAXPATLEN BUFSIZ
@@ -236,6 +255,8 @@ static pcre2_compile_context *compile_context;
static pcre2_match_context *match_context;
static pcre2_match_data *match_data;
static PCRE2_SIZE *offsets;
+static uint32_t offset_size;
+static uint32_t capture_max = DEFAULT_CAPTURE_MAX;
static BOOL count_only = FALSE;
static BOOL do_colour = FALSE;
@@ -385,6 +406,7 @@ used to identify them. */
#define N_INCLUDE_FROM (-21)
#define N_OM_SEPARATOR (-22)
#define N_MAX_BUFSIZE (-23)
+#define N_OM_CAPTURE (-24)
static option_item optionlist[] = {
{ OP_NODATA, N_NULL, NULL, "", "terminate options" },
@@ -431,6 +453,7 @@ static option_item optionlist[] = {
{ OP_STRING, 'O', &output_text, "output=text", "show only this text (possibly expanded)" },
{ OP_OP_NUMBERS, 'o', &only_matching_data, "only-matching=n", "show only the part of the line that matched" },
{ OP_STRING, N_OM_SEPARATOR, &om_separator, "om-separator=text", "set separator for multiple -o output" },
+ { OP_U32NUMBER, N_OM_CAPTURE, &capture_max, "om-capture=n", "set capture count for --only-matching" },
{ OP_NODATA, 'q', NULL, "quiet", "suppress output, just set return code" },
{ OP_NODATA, 'r', NULL, "recursive", "recursively scan sub-directories" },
{ OP_PATLIST, N_EXCLUDE,&exclude_patdata, "exclude=pattern","exclude matching files when recursing" },
@@ -445,6 +468,7 @@ static option_item optionlist[] = {
{ OP_NODATA, 's', NULL, "no-messages", "suppress error messages" },
{ OP_NODATA, 't', NULL, "total-count", "print total count of matching lines" },
{ OP_NODATA, 'u', NULL, "utf", "use UTF mode" },
+ { OP_NODATA, 'U', NULL, "utf-allow-invalid", "use UTF mode, allow for invalid code units" },
{ OP_NODATA, 'V', NULL, "version", "print version information and exit" },
{ OP_NODATA, 'v', NULL, "invert-match", "select non-matching lines" },
{ OP_NODATA, 'w', NULL, "word-regex(p)", "force patterns to match only as words" },
@@ -573,8 +597,6 @@ status of 1, which is not helpful. To help with this problem, define a symbol
therein. */
#ifdef __VMS
-#include descrip
-#include lib$routines
char val_buf[4];
$DESCRIPTOR(sym_nam, "PCRE2GREP_RC");
$DESCRIPTOR(sym_val, val_buf);
@@ -1133,7 +1155,11 @@ printf("Search for PATTERN in each FILE or standard input." STDOUT_NL);
printf("PATTERN must be present if neither -e nor -f is used." STDOUT_NL);
#ifdef SUPPORT_PCRE2GREP_CALLOUT
-printf("Callout scripts in patterns are supported." STDOUT_NL);
+#ifdef SUPPORT_PCRE2GREP_CALLOUT_FORK
+printf("All callout scripts in patterns are supported." STDOUT_NL);
+#else
+printf("Non-fork callout scripts in patterns are supported." STDOUT_NL);
+#endif
#else
printf("Callout scripts are not supported in this pcre2grep." STDOUT_NL);
#endif
@@ -1725,6 +1751,15 @@ for (i = 1; p != NULL; p = p->next, i++)
fprintf(stderr, "%s", msg);
FWRITE_IGNORE(matchptr, 1, slen, stderr); /* In case binary zero included */
fprintf(stderr, "\n\n");
+ if (*mrc <= PCRE2_ERROR_UTF8_ERR1 &&
+ *mrc >= PCRE2_ERROR_UTF8_ERR21)
+ {
+ unsigned char mbuffer[256];
+ PCRE2_SIZE startchar = pcre2_get_startchar(match_data);
+ (void)pcre2_get_error_message(*mrc, mbuffer, sizeof(mbuffer));
+ fprintf(stderr, "%s at offset %" SIZ_FORM "\n\n", mbuffer,
+ SIZ_CAST startchar);
+ }
if (*mrc == PCRE2_ERROR_MATCHLIMIT || *mrc == PCRE2_ERROR_DEPTHLIMIT ||
*mrc == PCRE2_ERROR_HEAPLIMIT || *mrc == PCRE2_ERROR_JIT_STACKLIMIT)
resource_error = TRUE;
@@ -2017,10 +2052,10 @@ return printed;
* Parse and execute callout scripts *
*************************************************/
-/* This function parses a callout string block and executes the
-program specified by the string. The string is a list of substrings
-separated by pipe characters. The first substring represents the
-executable name, and the following substrings specify the arguments:
+/* If SUPPORT_PCRE2GREP_CALLOUT_FORK is defined, this function parses a callout
+string block and executes the program specified by the string. The string is a
+list of substrings separated by pipe characters. The first substring represents
+the executable name, and the following substrings specify the arguments:
program_name|param1|param2|...
@@ -2037,8 +2072,9 @@ follows:
dollar or $| replaced by a pipe character.
Alternatively, if string starts with pipe, the remainder is taken as an output
-string, same as --output. In this case, --om-separator is used to separate each
-callout, defaulting to newline.
+string, same as --output. This is the only form that is supported if
+SUPPORT_PCRE2GREP_FORK is not defined. In this case, --om-separator is used to
+separate each callout, defaulting to newline.
Example:
@@ -2066,6 +2102,8 @@ PCRE2_SPTR string = calloutptr->callout_string;
PCRE2_SPTR subject = calloutptr->subject;
PCRE2_SIZE *ovector = calloutptr->offset_vector;
PCRE2_SIZE capture_top = calloutptr->capture_top;
+
+#ifdef SUPPORT_PCRE2GREP_CALLOUT_FORK
PCRE2_SIZE argsvectorlen = 2;
PCRE2_SIZE argslen = 1;
char *args;
@@ -2076,10 +2114,12 @@ char **argsvectorptr;
pid_t pid;
#endif
int result = 0;
+#endif /* SUPPORT_PCRE2GREP_CALLOUT_FORK */
(void)unused; /* Avoid compiler warning */
/* Only callout with strings are supported. */
+
if (string == NULL || length == 0) return 0;
/* If there's no command, output the remainder directly. */
@@ -2092,6 +2132,10 @@ if (*string == '|')
return 0;
}
+#ifndef SUPPORT_PCRE2GREP_CALLOUT_FORK
+return 0;
+#else
+
/* Checking syntax and compute the number of string fragments. Callout strings
are ignored in case of a syntax error. */
@@ -2272,11 +2316,34 @@ while (length > 0)
*argsptr++ = '\0';
*argsvectorptr = NULL;
+/* Running an external command is system-dependent. Handle Windows and VMS as
+necessary, otherwise assume fork(). */
+
#ifdef WIN32
result = _spawnvp(_P_WAIT, argsvector[0], (const char * const *)argsvector);
-#else
-pid = fork();
+#elif defined __VMS
+ {
+ char cmdbuf[500];
+ short i = 0;
+ int flags = CLI$M_NOCLISYM|CLI$M_NOLOGNAM|CLI$M_NOKEYPAD, status, retstat;
+ $DESCRIPTOR(cmd, cmdbuf);
+
+ cmdbuf[0] = 0;
+ while (argsvector[i])
+ {
+ strcat(cmdbuf, argsvector[i]);
+ strcat(cmdbuf, " ");
+ i++;
+ }
+ cmd.dsc$w_length = strlen(cmdbuf) - 1;
+ status = lib$spawn(&cmd, 0,0, &flags, 0,0, &retstat);
+ if (!(status & 1)) result = 0;
+ else result = retstat & 1 ? 0 : 1;
+ }
+
+#else /* Neither Windows nor VMS */
+pid = fork();
if (pid == 0)
{
(void)execv(argsvector[0], argsvector);
@@ -2285,7 +2352,7 @@ if (pid == 0)
}
else if (pid > 0)
(void)waitpid(pid, &result, 0);
-#endif
+#endif /* End Windows/VMS/other handling */
free(args);
free(argsvector);
@@ -2294,9 +2361,9 @@ free(argsvector);
continues) or non-zero (match fails). */
return result != 0;
+#endif /* SUPPORT_PCRE2GREP_CALLOUT_FORK */
}
-
-#endif
+#endif /* SUPPORT_PCRE2GREP_CALLOUT */
@@ -2528,7 +2595,7 @@ while (ptr < endptr)
for (i = 0; i < jfriedl_XR; i++)
match = (pcre_exec(patterns->compiled, patterns->hint, ptr, length, 0,
- PCRE2_NOTEMPTY, offsets, OFFSET_SIZE) >= 0);
+ PCRE2_NOTEMPTY, offsets, offset_size) >= 0);
if (gettimeofday(&end_time, &dummy) != 0)
perror("bad gettimeofday");
@@ -2648,7 +2715,7 @@ while (ptr < endptr)
for (om = only_matching; om != NULL; om = om->next)
{
int n = om->groupnum;
- if (n < mrc)
+ if (n == 0 || n < mrc)
{
int plen = offsets[2*n + 1] - offsets[2*n];
if (plen > 0)
@@ -3361,6 +3428,7 @@ switch(letter)
case 's': silent = TRUE; break;
case 't': show_total_count = TRUE; break;
case 'u': options |= PCRE2_UTF; utf = TRUE; break;
+ case 'U': options |= PCRE2_UTF|PCRE2_MATCH_INVALID_UTF; utf = TRUE; break;
case 'v': invert = TRUE; break;
case 'w': extra_options |= PCRE2_EXTRA_MATCH_WORD; break;
case 'x': extra_options |= PCRE2_EXTRA_MATCH_LINE; break;
@@ -3599,6 +3667,7 @@ int rc = 1;
BOOL only_one_at_top;
patstr *cp;
fnstr *fn;
+omstr *om;
const char *locale_from = "--locale";
#ifdef SUPPORT_PCRE2GREP_JIT
@@ -3615,20 +3684,6 @@ must use STDOUT_NL to terminate lines. */
_setmode(_fileno(stdout), _O_BINARY);
#endif
-/* Set up a default compile and match contexts and a match data block. */
-
-compile_context = pcre2_compile_context_create(NULL);
-match_context = pcre2_match_context_create(NULL);
-match_data = pcre2_match_data_create(OFFSET_SIZE, NULL);
-offsets = pcre2_get_ovector_pointer(match_data);
-
-/* If string (script) callouts are supported, set up the callout processing
-function. */
-
-#ifdef SUPPORT_PCRE2GREP_CALLOUT
-pcre2_set_callout(match_context, pcre2grep_callout, NULL);
-#endif
-
/* Process the options */
for (i = 1; i < argc; i++)
@@ -3975,12 +4030,40 @@ if (only_matching_count > 1)
pcre2grep_exit(usage(2));
}
+/* Check that there is a big enough ovector for all -o settings. */
+
+for (om = only_matching; om != NULL; om = om->next)
+ {
+ int n = om->groupnum;
+ if (n > (int)capture_max)
+ {
+ fprintf(stderr, "pcre2grep: Requested group %d cannot be captured.\n", n);
+ fprintf(stderr, "pcre2grep: Use --om-capture to increase the size of the capture vector.\n");
+ goto EXIT2;
+ }
+ }
+
/* Check the text supplied to --output for errors. */
if (output_text != NULL &&
!syntax_check_output_text((PCRE2_SPTR)output_text, FALSE))
goto EXIT2;
+/* Set up default compile and match contexts and a match data block. */
+
+offset_size = capture_max + 1;
+compile_context = pcre2_compile_context_create(NULL);
+match_context = pcre2_match_context_create(NULL);
+match_data = pcre2_match_data_create(offset_size, NULL);
+offsets = pcre2_get_ovector_pointer(match_data);
+
+/* If string (script) callouts are supported, set up the callout processing
+function. */
+
+#ifdef SUPPORT_PCRE2GREP_CALLOUT
+pcre2_set_callout(match_context, pcre2grep_callout, NULL);
+#endif
+
/* Put limits into the match data block. */
if (heap_limit != PCRE2_UNSET) pcre2_set_heap_limit(match_context, heap_limit);
@@ -4302,11 +4385,12 @@ if (show_total_count && counts_printed != 1 && filenames != FN_NOMATCH_ONLY)
EXIT:
#ifdef SUPPORT_PCRE2GREP_JIT
+pcre2_jit_free_unused_memory(NULL);
if (jit_stack != NULL) pcre2_jit_stack_free(jit_stack);
#endif
free(main_buffer);
-free((void *)character_tables);
+if (character_tables != NULL) pcre2_maketables_free(NULL, character_tables);
pcre2_compile_context_free(compile_context);
pcre2_match_context_free(match_context);
diff --git a/src/pcre2posix.c b/src/pcre2posix.c
index 7b9f477..b24620a 100644
--- a/src/pcre2posix.c
+++ b/src/pcre2posix.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,12 @@ POSSIBILITY OF SUCH DAMAGE.
/* This module is a wrapper that provides a POSIX API to the underlying PCRE2
-functions. */
+functions. The operative functions are called pcre2_regcomp(), etc., with
+wrappers that use the plain POSIX names. In addition, pcre2posix.h defines the
+POSIX names as macros for the pcre2_xxx functions, so any program that includes
+it and uses the POSIX names will call the base functions directly. This makes
+it easier for an application to be sure it gets the PCRE2 versions in the
+presence of other POSIX regex libraries. */
#ifdef HAVE_CONFIG_H
@@ -170,13 +175,59 @@ static const char *const pstring[] = {
+/*************************************************
+* Wrappers with traditional POSIX names *
+*************************************************/
+
+/* Keep defining them to preseve the ABI for applications linked to the pcre2
+POSIX library before these names were changed into macros in pcre2posix.h.
+This also ensures that the POSIX names are callable from languages that do not
+include pcre2posix.h. It is vital to #undef the macro definitions from
+pcre2posix.h! */
+
+#undef regerror
+PCRE2POSIX_EXP_DECL size_t regerror(int, const regex_t *, char *, size_t);
+PCRE2POSIX_EXP_DEFN size_t PCRE2_CALL_CONVENTION
+regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
+{
+return pcre2_regerror(errcode, preg, errbuf, errbuf_size);
+}
+
+#undef regfree
+PCRE2POSIX_EXP_DECL void regfree(regex_t *);
+PCRE2POSIX_EXP_DEFN void PCRE2_CALL_CONVENTION
+regfree(regex_t *preg)
+{
+pcre2_regfree(preg);
+}
+
+#undef regcomp
+PCRE2POSIX_EXP_DECL int regcomp(regex_t *, const char *, int);
+PCRE2POSIX_EXP_DEFN int PCRE2_CALL_CONVENTION
+regcomp(regex_t *preg, const char *pattern, int cflags)
+{
+return pcre2_regcomp(preg, pattern, cflags);
+}
+
+#undef regexec
+PCRE2POSIX_EXP_DECL int regexec(const regex_t *, const char *, size_t,
+ regmatch_t *, int);
+PCRE2POSIX_EXP_DEFN int PCRE2_CALL_CONVENTION
+regexec(const regex_t *preg, const char *string, size_t nmatch,
+ regmatch_t pmatch[], int eflags)
+{
+return pcre2_regexec(preg, string, nmatch, pmatch, eflags);
+}
+
+
/*************************************************
* Translate error code to string *
*************************************************/
PCRE2POSIX_EXP_DEFN size_t PCRE2_CALL_CONVENTION
-regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
+pcre2_regerror(int errcode, const regex_t *preg, char *errbuf,
+ size_t errbuf_size)
{
int used;
const char *message;
@@ -199,13 +250,12 @@ return used + 1;
-
/*************************************************
* Free store held by a regex *
*************************************************/
PCRE2POSIX_EXP_DEFN void PCRE2_CALL_CONVENTION
-regfree(regex_t *preg)
+pcre2_regfree(regex_t *preg)
{
pcre2_match_data_free(preg->re_match_data);
pcre2_code_free(preg->re_pcre2_code);
@@ -213,7 +263,6 @@ pcre2_code_free(preg->re_pcre2_code);
-
/*************************************************
* Compile a regular expression *
*************************************************/
@@ -229,7 +278,7 @@ Returns: 0 on success
*/
PCRE2POSIX_EXP_DEFN int PCRE2_CALL_CONVENTION
-regcomp(regex_t *preg, const char *pattern, int cflags)
+pcre2_regcomp(regex_t *preg, const char *pattern, int cflags)
{
PCRE2_SIZE erroffset;
PCRE2_SIZE patlen;
@@ -274,6 +323,7 @@ if (preg->re_pcre2_code == NULL)
PCRE2_INFO_CAPTURECOUNT, &re_nsub);
preg->re_nsub = (size_t)re_nsub;
preg->re_match_data = pcre2_match_data_create(re_nsub + 1, NULL);
+preg->re_erroffset = (size_t)(-1); /* No meaning after successful compile */
if (preg->re_match_data == NULL)
{
@@ -296,7 +346,7 @@ for each match. If REG_NOSUB was specified at compile time, the nmatch and
pmatch arguments are ignored, and the only result is yes/no/error. */
PCRE2POSIX_EXP_DEFN int PCRE2_CALL_CONVENTION
-regexec(const regex_t *preg, const char *string, size_t nmatch,
+pcre2_regexec(const regex_t *preg, const char *string, size_t nmatch,
regmatch_t pmatch[], int eflags)
{
int rc, so, eo;
@@ -307,8 +357,6 @@ if ((eflags & REG_NOTBOL) != 0) options |= PCRE2_NOTBOL;
if ((eflags & REG_NOTEOL) != 0) options |= PCRE2_NOTEOL;
if ((eflags & REG_NOTEMPTY) != 0) options |= PCRE2_NOTEMPTY;
-((regex_t *)preg)->re_erroffset = (size_t)(-1); /* Only has meaning after compile */
-
/* When REG_NOSUB was specified, or if no vector has been passed in which to
put captured strings, ensure that nmatch is zero. This will stop any attempt to
write to pmatch. */
diff --git a/src/pcre2posix.h b/src/pcre2posix.h
index 4ae1d3c..3a663b9 100644
--- a/src/pcre2posix.h
+++ b/src/pcre2posix.h
@@ -3,11 +3,13 @@
*************************************************/
/* PCRE2 is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
+and semantics are as close as possible to those of the Perl 5 language. This is
+the public header file to be #included by applications that call PCRE2 via the
+POSIX wrapper interface.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -136,13 +138,30 @@ file. */
# endif
#endif
-/* The functions */
+/* The functions. The actual code is in functions with pcre2_xxx names for
+uniqueness. POSIX names are provided as macros for API compatibility with POSIX
+regex functions. It's done this way to ensure to they are always linked from
+the PCRE2 library and not by accident from elsewhere (regex_t differs in size
+elsewhere). */
-PCRE2POSIX_EXP_DECL int regcomp(regex_t *, const char *, int);
-PCRE2POSIX_EXP_DECL int regexec(const regex_t *, const char *, size_t,
+PCRE2POSIX_EXP_DECL int pcre2_regcomp(regex_t *, const char *, int);
+PCRE2POSIX_EXP_DECL int pcre2_regexec(const regex_t *, const char *, size_t,
regmatch_t *, int);
-PCRE2POSIX_EXP_DECL size_t regerror(int, const regex_t *, char *, size_t);
-PCRE2POSIX_EXP_DECL void regfree(regex_t *);
+PCRE2POSIX_EXP_DECL size_t pcre2_regerror(int, const regex_t *, char *, size_t);
+PCRE2POSIX_EXP_DECL void pcre2_regfree(regex_t *);
+
+#define regcomp pcre2_regcomp
+#define regexec pcre2_regexec
+#define regerror pcre2_regerror
+#define regfree pcre2_regfree
+
+/* Debian had a patch that used different names. These are now here to save
+them having to maintain their own patch, but are not documented by PCRE2. */
+
+#define PCRE2regcomp pcre2_regcomp
+#define PCRE2regexec pcre2_regexec
+#define PCRE2regerror pcre2_regerror
+#define PCRE2regfree pcre2_regfree
#ifdef __cplusplus
} /* extern "C" */
diff --git a/src/pcre2test.c b/src/pcre2test.c
index 8cfb8e9..57bd110 100644
--- a/src/pcre2test.c
+++ b/src/pcre2test.c
@@ -11,7 +11,7 @@ hacked-up (non-) design had also run out of steam.
Written by Philip Hazel
Original code Copyright (c) 1997-2012 University of Cambridge
- Rewritten code Copyright (c) 2016-2018 University of Cambridge
+ Rewritten code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -157,14 +157,24 @@ patterns. */
#endif
#endif
+/* VMS-specific code was included as suggested by a VMS user [1]. Another VMS
+user [2] provided alternative code which worked better for him. I have
+commented out the original, but kept it around just in case. */
+
#ifdef __VMS
#include
-void vms_setsymbol( char *, char *, int );
+/* These two includes came from [2]. */
+#include descrip
+#include lib$routines
+/* void vms_setsymbol( char *, char *, int ); Original code from [1]. */
#endif
-/* VC and older compilers don't support %td or %zu. */
+/* VC and older compilers don't support %td or %zu, and even some that claim to
+be C99 don't support it (hence DISABLE_PERCENT_ZT). There are some non-C99
+environments where %lu gives a warning with 32-bit pointers. As there doesn't
+seem to be an easy way round this, just live with it (the cases are rare). */
-#if defined(_MSC_VER) || !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
+#if defined(_MSC_VER) || !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L || defined(DISABLE_PERCENT_ZT)
#define PTR_FORM "lu"
#define SIZ_FORM "lu"
#define SIZ_CAST (unsigned long int)
@@ -204,6 +214,12 @@ void vms_setsymbol( char *, char *, int );
#define REPLACE_MODSIZE 100 /* Field for reading 8-bit replacement */
#define VERSION_SIZE 64 /* Size of buffer for the version strings */
+/* Default JIT compile options */
+
+#define JIT_DEFAULT (PCRE2_JIT_COMPLETE|\
+ PCRE2_JIT_PARTIAL_SOFT|\
+ PCRE2_JIT_PARTIAL_HARD)
+
/* Make sure the buffer into which replacement strings are copied is big enough
to hold them as 32-bit code units. */
@@ -484,13 +500,15 @@ so many of them that they are split into two fields. */
/* Second control word */
-#define CTL2_SUBSTITUTE_EXTENDED 0x00000001u
-#define CTL2_SUBSTITUTE_OVERFLOW_LENGTH 0x00000002u
-#define CTL2_SUBSTITUTE_UNKNOWN_UNSET 0x00000004u
-#define CTL2_SUBSTITUTE_UNSET_EMPTY 0x00000008u
-#define CTL2_SUBJECT_LITERAL 0x00000010u
-#define CTL2_CALLOUT_NO_WHERE 0x00000020u
-#define CTL2_CALLOUT_EXTRA 0x00000040u
+#define CTL2_SUBSTITUTE_CALLOUT 0x00000001u
+#define CTL2_SUBSTITUTE_EXTENDED 0x00000002u
+#define CTL2_SUBSTITUTE_OVERFLOW_LENGTH 0x00000004u
+#define CTL2_SUBSTITUTE_UNKNOWN_UNSET 0x00000008u
+#define CTL2_SUBSTITUTE_UNSET_EMPTY 0x00000010u
+#define CTL2_SUBJECT_LITERAL 0x00000020u
+#define CTL2_CALLOUT_NO_WHERE 0x00000040u
+#define CTL2_CALLOUT_EXTRA 0x00000080u
+#define CTL2_ALLVECTOR 0x00000100u
#define CTL2_NL_SET 0x40000000u /* Informational */
#define CTL2_BSR_SET 0x80000000u /* Informational */
@@ -510,22 +528,26 @@ different things in the two cases. */
CTL_STARTCHAR|\
CTL_UTF8_INPUT)
-#define CTL2_ALLPD (CTL2_SUBSTITUTE_EXTENDED|\
+#define CTL2_ALLPD (CTL2_SUBSTITUTE_CALLOUT|\
+ CTL2_SUBSTITUTE_EXTENDED|\
CTL2_SUBSTITUTE_OVERFLOW_LENGTH|\
CTL2_SUBSTITUTE_UNKNOWN_UNSET|\
- CTL2_SUBSTITUTE_UNSET_EMPTY)
+ CTL2_SUBSTITUTE_UNSET_EMPTY|\
+ CTL2_ALLVECTOR)
/* Structures for holding modifier information for patterns and subject strings
(data). Fields containing modifiers that can be set either for a pattern or a
subject must be at the start and in the same order in both cases so that the
same offset in the big table below works for both. */
-typedef struct patctl { /* Structure for pattern modifiers. */
- uint32_t options; /* Must be in same position as datctl */
- uint32_t control; /* Must be in same position as datctl */
- uint32_t control2; /* Must be in same position as datctl */
- uint32_t jitstack; /* Must be in same position as datctl */
+typedef struct patctl { /* Structure for pattern modifiers. */
+ uint32_t options; /* Must be in same position as datctl */
+ uint32_t control; /* Must be in same position as datctl */
+ uint32_t control2; /* Must be in same position as datctl */
+ uint32_t jitstack; /* Must be in same position as datctl */
uint8_t replacement[REPLACE_MODSIZE]; /* So must this */
+ uint32_t substitute_skip; /* Must be in same position as patctl */
+ uint32_t substitute_stop; /* Must be in same position as patctl */
uint32_t jit;
uint32_t stackguard_test;
uint32_t tables_id;
@@ -540,12 +562,14 @@ typedef struct patctl { /* Structure for pattern modifiers. */
#define MAXCPYGET 10
#define LENCPYGET 64
-typedef struct datctl { /* Structure for data line modifiers. */
- uint32_t options; /* Must be in same position as patctl */
- uint32_t control; /* Must be in same position as patctl */
- uint32_t control2; /* Must be in same position as patctl */
- uint32_t jitstack; /* Must be in same position as patctl */
+typedef struct datctl { /* Structure for data line modifiers. */
+ uint32_t options; /* Must be in same position as patctl */
+ uint32_t control; /* Must be in same position as patctl */
+ uint32_t control2; /* Must be in same position as patctl */
+ uint32_t jitstack; /* Must be in same position as patctl */
uint8_t replacement[REPLACE_MODSIZE]; /* So must this */
+ uint32_t substitute_skip; /* Must be in same position as patctl */
+ uint32_t substitute_stop; /* Must be in same position as patctl */
uint32_t startend[2];
uint32_t cerror[2];
uint32_t cfail[2];
@@ -592,6 +616,7 @@ static modstruct modlist[] = {
{ "allow_empty_class", MOD_PAT, MOD_OPT, PCRE2_ALLOW_EMPTY_CLASS, PO(options) },
{ "allow_surrogate_escapes", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES, CO(extra_options) },
{ "allusedtext", MOD_PNDP, MOD_CTL, CTL_ALLUSEDTEXT, PO(control) },
+ { "allvector", MOD_PND, MOD_CTL, CTL2_ALLVECTOR, PO(control2) },
{ "alt_bsux", MOD_PAT, MOD_OPT, PCRE2_ALT_BSUX, PO(options) },
{ "alt_circumflex", MOD_PAT, MOD_OPT, PCRE2_ALT_CIRCUMFLEX, PO(options) },
{ "alt_verbnames", MOD_PAT, MOD_OPT, PCRE2_ALT_VERBNAMES, PO(options) },
@@ -615,6 +640,7 @@ static modstruct modlist[] = {
{ "convert_glob_separator", MOD_PAT, MOD_CHR, 0, PO(convert_glob_separator) },
{ "convert_length", MOD_PAT, MOD_INT, 0, PO(convert_length) },
{ "copy", MOD_DAT, MOD_NN, DO(copy_numbers), DO(copy_names) },
+ { "copy_matched_subject", MOD_DAT, MOD_OPT, PCRE2_COPY_MATCHED_SUBJECT, DO(options) },
{ "debug", MOD_PAT, MOD_CTL, CTL_DEBUG, PO(control) },
{ "depth_limit", MOD_CTM, MOD_INT, 0, MO(depth_limit) },
{ "dfa", MOD_DAT, MOD_CTL, CTL_DFA, DO(control) },
@@ -624,9 +650,11 @@ static modstruct modlist[] = {
{ "dotall", MOD_PATP, MOD_OPT, PCRE2_DOTALL, PO(options) },
{ "dupnames", MOD_PATP, MOD_OPT, PCRE2_DUPNAMES, PO(options) },
{ "endanchored", MOD_PD, MOD_OPT, PCRE2_ENDANCHORED, PD(options) },
+ { "escaped_cr_is_lf", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ESCAPED_CR_IS_LF, CO(extra_options) },
{ "expand", MOD_PAT, MOD_CTL, CTL_EXPAND, PO(control) },
{ "extended", MOD_PATP, MOD_OPT, PCRE2_EXTENDED, PO(options) },
{ "extended_more", MOD_PATP, MOD_OPT, PCRE2_EXTENDED_MORE, PO(options) },
+ { "extra_alt_bsux", MOD_CTC, MOD_OPT, PCRE2_EXTRA_ALT_BSUX, CO(extra_options) },
{ "find_limits", MOD_DAT, MOD_CTL, CTL_FINDLIMITS, DO(control) },
{ "firstline", MOD_PAT, MOD_OPT, PCRE2_FIRSTLINE, PO(options) },
{ "framesize", MOD_PAT, MOD_CTL, CTL_FRAMESIZE, PO(control) },
@@ -644,6 +672,7 @@ static modstruct modlist[] = {
{ "literal", MOD_PAT, MOD_OPT, PCRE2_LITERAL, PO(options) },
{ "locale", MOD_PAT, MOD_STR, LOCALESIZE, PO(locale) },
{ "mark", MOD_PNDP, MOD_CTL, CTL_MARK, PO(control) },
+ { "match_invalid_utf", MOD_PAT, MOD_OPT, PCRE2_MATCH_INVALID_UTF, PO(options) },
{ "match_limit", MOD_CTM, MOD_INT, 0, MO(match_limit) },
{ "match_line", MOD_CTC, MOD_OPT, PCRE2_EXTRA_MATCH_LINE, CO(extra_options) },
{ "match_unset_backref", MOD_PAT, MOD_OPT, PCRE2_MATCH_UNSET_BACKREF, PO(options) },
@@ -687,8 +716,11 @@ static modstruct modlist[] = {
{ "startchar", MOD_PND, MOD_CTL, CTL_STARTCHAR, PO(control) },
{ "startoffset", MOD_DAT, MOD_INT, 0, DO(offset) },
{ "subject_literal", MOD_PATP, MOD_CTL, CTL2_SUBJECT_LITERAL, PO(control2) },
+ { "substitute_callout", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_CALLOUT, PO(control2) },
{ "substitute_extended", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_EXTENDED, PO(control2) },
{ "substitute_overflow_length", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_OVERFLOW_LENGTH, PO(control2) },
+ { "substitute_skip", MOD_PND, MOD_INT, 0, PO(substitute_skip) },
+ { "substitute_stop", MOD_PND, MOD_INT, 0, PO(substitute_stop) },
{ "substitute_unknown_unset", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_UNKNOWN_UNSET, PO(control2) },
{ "substitute_unset_empty", MOD_PND, MOD_CTL, CTL2_SUBSTITUTE_UNSET_EMPTY, PO(control2) },
{ "tables", MOD_PAT, MOD_INT, 0, PO(tables_id) },
@@ -888,6 +920,7 @@ static uint32_t forbid_utf = 0;
static uint32_t maxlookbehind;
static uint32_t max_oveccount;
static uint32_t callout_count;
+static uint32_t maxcapcount;
static uint16_t local_newline_default = 0;
@@ -1351,15 +1384,26 @@ are supported. */
else \
pcre2_set_parens_nest_limit_32(G(a,32),b)
+#define PCRE2_SET_SUBSTITUTE_CALLOUT(a,b,c) \
+ if (test_mode == PCRE8_MODE) \
+ pcre2_set_substitute_callout_8(G(a,8), \
+ (int (*)(pcre2_substitute_callout_block_8 *, void *))b,c); \
+ else if (test_mode == PCRE16_MODE) \
+ pcre2_set_substitute_callout_16(G(a,16), \
+ (int (*)(pcre2_substitute_callout_block_16 *, void *))b,c); \
+ else \
+ pcre2_set_substitute_callout_32(G(a,32), \
+ (int (*)(pcre2_substitute_callout_block_32 *, void *))b,c)
+
#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \
if (test_mode == PCRE8_MODE) \
- a = pcre2_substitute_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),G(h,8), \
+ a = pcre2_substitute_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h, \
(PCRE2_SPTR8)i,j,(PCRE2_UCHAR8 *)k,l); \
else if (test_mode == PCRE16_MODE) \
- a = pcre2_substitute_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),G(h,16), \
+ a = pcre2_substitute_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h, \
(PCRE2_SPTR16)i,j,(PCRE2_UCHAR16 *)k,l); \
else \
- a = pcre2_substitute_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),G(h,32), \
+ a = pcre2_substitute_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h, \
(PCRE2_SPTR32)i,j,(PCRE2_UCHAR32 *)k,l)
#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \
@@ -1820,14 +1864,22 @@ the three different cases. */
else \
G(pcre2_set_parens_nest_limit_,BITTWO)(G(a,BITTWO),b)
+#define PCRE2_SET_SUBSTITUTE_CALLOUT(a,b,c) \
+ if (test_mode == G(G(PCRE,BITONE),_MODE)) \
+ G(pcre2_set_substitute_callout_,BITONE)(G(a,BITONE), \
+ (int (*)(G(pcre2_substitute_callout_block_,BITONE) *, void *))b,c); \
+ else \
+ G(pcre2_set_substitute_callout_,BITTWO)(G(a,BITTWO), \
+ (int (*)(G(pcre2_substitute_callout_block_,BITTWO) *, void *))b,c)
+
#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \
if (test_mode == G(G(PCRE,BITONE),_MODE)) \
a = G(pcre2_substitute_,BITONE)(G(b,BITONE),(G(PCRE2_SPTR,BITONE))c,d,e,f, \
- G(g,BITONE),G(h,BITONE),(G(PCRE2_SPTR,BITONE))i,j, \
+ G(g,BITONE),h,(G(PCRE2_SPTR,BITONE))i,j, \
(G(PCRE2_UCHAR,BITONE) *)k,l); \
else \
a = G(pcre2_substitute_,BITTWO)(G(b,BITTWO),(G(PCRE2_SPTR,BITTWO))c,d,e,f, \
- G(g,BITTWO),G(h,BITTWO),(G(PCRE2_SPTR,BITTWO))i,j, \
+ G(g,BITTWO),h,(G(PCRE2_SPTR,BITTWO))i,j, \
(G(PCRE2_UCHAR,BITTWO) *)k,l)
#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \
@@ -2021,8 +2073,11 @@ the three different cases. */
#define PCRE2_SET_MAX_PATTERN_LENGTH(a,b) pcre2_set_max_pattern_length_8(G(a,8),b)
#define PCRE2_SET_OFFSET_LIMIT(a,b) pcre2_set_offset_limit_8(G(a,8),b)
#define PCRE2_SET_PARENS_NEST_LIMIT(a,b) pcre2_set_parens_nest_limit_8(G(a,8),b)
+#define PCRE2_SET_SUBSTITUTE_CALLOUT(a,b,c) \
+ pcre2_set_substitute_callout_8(G(a,8), \
+ (int (*)(pcre2_substitute_callout_block_8 *, void *))b,c)
#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \
- a = pcre2_substitute_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),G(h,8), \
+ a = pcre2_substitute_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),h, \
(PCRE2_SPTR8)i,j,(PCRE2_UCHAR8 *)k,l)
#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \
a = pcre2_substring_copy_byname_8(G(b,8),G(c,8),(PCRE2_UCHAR8 *)d,e)
@@ -2125,8 +2180,11 @@ the three different cases. */
#define PCRE2_SET_MAX_PATTERN_LENGTH(a,b) pcre2_set_max_pattern_length_16(G(a,16),b)
#define PCRE2_SET_OFFSET_LIMIT(a,b) pcre2_set_offset_limit_16(G(a,16),b)
#define PCRE2_SET_PARENS_NEST_LIMIT(a,b) pcre2_set_parens_nest_limit_16(G(a,16),b)
+#define PCRE2_SET_SUBSTITUTE_CALLOUT(a,b,c) \
+ pcre2_set_substitute_callout_16(G(a,16), \
+ (int (*)(pcre2_substitute_callout_block_16 *, void *))b,c)
#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \
- a = pcre2_substitute_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),G(h,16), \
+ a = pcre2_substitute_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),h, \
(PCRE2_SPTR16)i,j,(PCRE2_UCHAR16 *)k,l)
#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \
a = pcre2_substring_copy_byname_16(G(b,16),G(c,16),(PCRE2_UCHAR16 *)d,e)
@@ -2217,7 +2275,7 @@ the three different cases. */
#define PCRE2_SERIALIZE_GET_NUMBER_OF_CODES(r,a) \
r = pcre2_serialize_get_number_of_codes_32(a)
#define PCRE2_SET_CALLOUT(a,b,c) \
- pcre2_set_callout_32(G(a,32),(int (*)(pcre2_callout_block_32 *, void *))b,c);
+ pcre2_set_callout_32(G(a,32),(int (*)(pcre2_callout_block_32 *, void *))b,c)
#define PCRE2_SET_CHARACTER_TABLES(a,b) pcre2_set_character_tables_32(G(a,32),b)
#define PCRE2_SET_COMPILE_RECURSION_GUARD(a,b,c) \
pcre2_set_compile_recursion_guard_32(G(a,32),b,c)
@@ -2229,8 +2287,11 @@ the three different cases. */
#define PCRE2_SET_MAX_PATTERN_LENGTH(a,b) pcre2_set_max_pattern_length_32(G(a,32),b)
#define PCRE2_SET_OFFSET_LIMIT(a,b) pcre2_set_offset_limit_32(G(a,32),b)
#define PCRE2_SET_PARENS_NEST_LIMIT(a,b) pcre2_set_parens_nest_limit_32(G(a,32),b)
+#define PCRE2_SET_SUBSTITUTE_CALLOUT(a,b,c) \
+ pcre2_set_substitute_callout_32(G(a,32), \
+ (int (*)(pcre2_substitute_callout_block_32 *, void *))b,c)
#define PCRE2_SUBSTITUTE(a,b,c,d,e,f,g,h,i,j,k,l) \
- a = pcre2_substitute_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),G(h,32), \
+ a = pcre2_substitute_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),h, \
(PCRE2_SPTR32)i,j,(PCRE2_UCHAR32 *)k,l)
#define PCRE2_SUBSTRING_COPY_BYNAME(a,b,c,d,e) \
a = pcre2_substring_copy_byname_32(G(b,32),G(c,32),(PCRE2_UCHAR32 *)d,e)
@@ -2998,13 +3059,14 @@ return yield;
-#ifdef SUPPORT_PCRE2_8
/*************************************************
* Convert character value to UTF-8 *
*************************************************/
/* This function takes an integer value in the range 0 - 0x7fffffff
-and encodes it as a UTF-8 character in 0 to 6 bytes.
+and encodes it as a UTF-8 character in 0 to 6 bytes. It is needed even when the
+8-bit library is not supported, to generate UTF-8 output for non-ASCII
+characters.
Arguments:
cvalue the character value
@@ -3030,7 +3092,6 @@ for (j = i; j > 0; j--)
*utf8bytes = utf8_table2[i] | cvalue;
return i + 1;
}
-#endif /* SUPPORT_PCRE2_8 */
@@ -3210,6 +3271,11 @@ return 0;
+/* This function is no longer used. Keep it around for a while, just in case it
+needs to be re-instated. */
+
+#ifdef NEVERNEVERNEVER
+
/*************************************************
* Move back by so many characters *
*************************************************/
@@ -3254,6 +3320,7 @@ else /* 16-bit mode */
return pp - (PCRE2_SPTR16)subject;
}
}
+#endif /* NEVERNEVERNEVER */
@@ -4018,12 +4085,13 @@ Returns: nothing
static void
show_controls(uint32_t controls, uint32_t controls2, const char *before)
{
-fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
before,
((controls & CTL_AFTERTEXT) != 0)? " aftertext" : "",
((controls & CTL_ALLAFTERTEXT) != 0)? " allaftertext" : "",
((controls & CTL_ALLCAPTURES) != 0)? " allcaptures" : "",
((controls & CTL_ALLUSEDTEXT) != 0)? " allusedtext" : "",
+ ((controls2 & CTL2_ALLVECTOR) != 0)? " allvector" : "",
((controls & CTL_ALTGLOBAL) != 0)? " altglobal" : "",
((controls & CTL_BINCODE) != 0)? " bincode" : "",
((controls2 & CTL2_BSR_SET) != 0)? " bsr" : "",
@@ -4053,6 +4121,7 @@ fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s
((controls & CTL_PUSHCOPY) != 0)? " pushcopy" : "",
((controls & CTL_PUSHTABLESCOPY) != 0)? " pushtablescopy" : "",
((controls & CTL_STARTCHAR) != 0)? " startchar" : "",
+ ((controls2 & CTL2_SUBSTITUTE_CALLOUT) != 0)? " substitute_callout" : "",
((controls2 & CTL2_SUBSTITUTE_EXTENDED) != 0)? " substitute_extended" : "",
((controls2 & CTL2_SUBSTITUTE_OVERFLOW_LENGTH) != 0)? " substitute_overflow_length" : "",
((controls2 & CTL2_SUBSTITUTE_UNKNOWN_UNSET) != 0)? " substitute_unknown_unset" : "",
@@ -4082,7 +4151,7 @@ static void
show_compile_options(uint32_t options, const char *before, const char *after)
{
if (options == 0) fprintf(outfile, "%s %s", before, after);
-else fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+else fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
before,
((options & PCRE2_ALT_BSUX) != 0)? " alt_bsux" : "",
((options & PCRE2_ALT_CIRCUMFLEX) != 0)? " alt_circumflex" : "",
@@ -4099,6 +4168,7 @@ else fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%
((options & PCRE2_EXTENDED_MORE) != 0)? " extended_more" : "",
((options & PCRE2_FIRSTLINE) != 0)? " firstline" : "",
((options & PCRE2_LITERAL) != 0)? " literal" : "",
+ ((options & PCRE2_MATCH_INVALID_UTF) != 0)? " match_invalid_utf" : "",
((options & PCRE2_MATCH_UNSET_BACKREF) != 0)? " match_unset_backref" : "",
((options & PCRE2_MULTILINE) != 0)? " multiline" : "",
((options & PCRE2_NEVER_BACKSLASH_C) != 0)? " never_backslash_c" : "",
@@ -4136,12 +4206,14 @@ show_compile_extra_options(uint32_t options, const char *before,
const char *after)
{
if (options == 0) fprintf(outfile, "%s %s", before, after);
-else fprintf(outfile, "%s%s%s%s%s%s",
+else fprintf(outfile, "%s%s%s%s%s%s%s%s",
before,
((options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) != 0)? " allow_surrogate_escapes" : "",
((options & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) != 0)? " bad_escape_is_literal" : "",
+ ((options & PCRE2_EXTRA_ALT_BSUX) != 0)? " extra_alt_bsux" : "",
((options & PCRE2_EXTRA_MATCH_WORD) != 0)? " match_word" : "",
((options & PCRE2_EXTRA_MATCH_LINE) != 0)? " match_line" : "",
+ ((options & PCRE2_EXTRA_ESCAPED_CR_IS_LF) != 0)? " escaped_cr_is_lf" : "",
after);
}
@@ -4157,11 +4229,13 @@ else fprintf(outfile, "%s%s%s%s%s%s",
static void
show_match_options(uint32_t options)
{
-fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s",
+fprintf(outfile, "%s%s%s%s%s%s%s%s%s%s%s%s%s",
((options & PCRE2_ANCHORED) != 0)? " anchored" : "",
+ ((options & PCRE2_COPY_MATCHED_SUBJECT) != 0)? " copy_matched_subject" : "",
((options & PCRE2_DFA_RESTART) != 0)? " dfa_restart" : "",
((options & PCRE2_DFA_SHORTEST) != 0)? " dfa_shortest" : "",
((options & PCRE2_ENDANCHORED) != 0)? " endanchored" : "",
+ ((options & PCRE2_NO_JIT) != 0)? " no_jit" : "",
((options & PCRE2_NO_UTF_CHECK) != 0)? " no_utf_check" : "",
((options & PCRE2_NOTBOL) != 0)? " notbol" : "",
((options & PCRE2_NOTEMPTY) != 0)? " notempty" : "",
@@ -4318,6 +4392,7 @@ static int
show_pattern_info(void)
{
uint32_t compile_options, overall_options, extra_options;
+BOOL utf = (FLD(compiled_code, overall_options) & PCRE2_UTF) != 0;
if ((pat_patctl.control & (CTL_BINCODE|CTL_FULLBINCODE)) != 0)
{
@@ -4407,7 +4482,7 @@ if ((pat_patctl.control & CTL_INFO) != 0)
!= 0)
return PR_ABEND;
- fprintf(outfile, "Capturing subpattern count = %d\n", capture_count);
+ fprintf(outfile, "Capture group count = %d\n", capture_count);
if (backrefmax > 0)
fprintf(outfile, "Max back reference = %d\n", backrefmax);
@@ -4426,14 +4501,60 @@ if ((pat_patctl.control & CTL_INFO) != 0)
if (namecount > 0)
{
- fprintf(outfile, "Named capturing subpatterns:\n");
+ fprintf(outfile, "Named capture groups:\n");
for (; namecount > 0; namecount--)
{
int imm2_size = test_mode == PCRE8_MODE ? 2 : 1;
uint32_t length = (uint32_t)STRLEN(nametable + imm2_size);
fprintf(outfile, " ");
- PCHARSV(nametable, imm2_size, length, FALSE, outfile);
+
+ /* In UTF mode the name may be a UTF string containing non-ASCII
+ letters and digits. We must output it as a UTF-8 string. In non-UTF mode,
+ use the normal string printing functions, which use escapes for all
+ non-ASCII characters. */
+
+ if (utf)
+ {
+#ifdef SUPPORT_PCRE2_32
+ if (test_mode == PCRE32_MODE)
+ {
+ PCRE2_SPTR32 nameptr = (PCRE2_SPTR32)nametable + imm2_size;
+ while (*nameptr != 0)
+ {
+ uint8_t u8buff[6];
+ int len = ord2utf8(*nameptr++, u8buff);
+ fprintf(outfile, "%.*s", len, u8buff);
+ }
+ }
+#endif
+#ifdef SUPPORT_PCRE2_16
+ if (test_mode == PCRE16_MODE)
+ {
+ PCRE2_SPTR16 nameptr = (PCRE2_SPTR16)nametable + imm2_size;
+ while (*nameptr != 0)
+ {
+ int len;
+ uint8_t u8buff[6];
+ uint32_t c = *nameptr++ & 0xffff;
+ if (c >= 0xD800 && c < 0xDC00)
+ c = ((c & 0x3ff) << 10) + (*nameptr++ & 0x3ff) + 0x10000;
+ len = ord2utf8(c, u8buff);
+ fprintf(outfile, "%.*s", len, u8buff);
+ }
+ }
+#endif
+#ifdef SUPPORT_PCRE2_8
+ if (test_mode == PCRE8_MODE)
+ fprintf(outfile, "%s", (PCRE2_SPTR8)nametable + imm2_size);
+#endif
+ }
+ else /* Not UTF mode */
+ {
+ PCHARSV(nametable, imm2_size, length, FALSE, outfile);
+ }
+
while (length++ < nameentrysize - imm2_size) putc(' ', outfile);
+
#ifdef SUPPORT_PCRE2_32
if (test_mode == PCRE32_MODE)
fprintf(outfile, "%3d\n", (int)(((PCRE2_SPTR32)nametable)[0]));
@@ -4447,6 +4568,7 @@ if ((pat_patctl.control & CTL_INFO) != 0)
fprintf(outfile, "%3d\n", (int)(
((((PCRE2_SPTR8)nametable)[0]) << 8) | ((PCRE2_SPTR8)nametable)[1]));
#endif
+
nametable = (void*)((PCRE2_SPTR8)nametable + nameentrysize * code_unit_size);
}
}
@@ -4553,7 +4675,7 @@ if ((pat_patctl.control & CTL_INFO) != 0)
fprintf(outfile, "Starting code units: ");
for (i = 0; i < 256; i++)
{
- if ((start_bits[i/8] & (1<<(i&7))) != 0)
+ if ((start_bits[i/8] & (1u << (i&7))) != 0)
{
if (c > 75)
{
@@ -4590,7 +4712,8 @@ if ((pat_patctl.control & CTL_INFO) != 0)
}
}
- fprintf(outfile, "Subject length lower bound = %d\n", minlength);
+ if ((FLD(compiled_code, overall_options) & PCRE2_NO_START_OPTIMIZE) == 0)
+ fprintf(outfile, "Subject length lower bound = %d\n", minlength);
if (pat_patctl.jit != 0 && (pat_patctl.control & CTL_JITVERIFY) != 0)
{
@@ -4761,7 +4884,7 @@ switch(cmd)
case CMD_PATTERN:
(void)decode_modifiers(argptr, CTX_DEFPAT, &def_patctl, NULL);
if (def_patctl.jit == 0 && (def_patctl.control & CTL_JITVERIFY) != 0)
- def_patctl.jit = 7;
+ def_patctl.jit = JIT_DEFAULT;
break;
/* Set default subject modifiers */
@@ -5008,7 +5131,11 @@ patlen = p - buffer - 2;
/* Look for modifiers and options after the final delimiter. */
if (!decode_modifiers(p, CTX_PAT, &pat_patctl, NULL)) return PR_SKIP;
-utf = (pat_patctl.options & PCRE2_UTF) != 0;
+
+/* Note that the match_invalid_utf option also sets utf when passed to
+pcre2_compile(). */
+
+utf = (pat_patctl.options & (PCRE2_UTF|PCRE2_MATCH_INVALID_UTF)) != 0;
/* The utf8_input modifier is not allowed in 8-bit mode, and is mutually
exclusive with the utf modifier. */
@@ -5055,7 +5182,7 @@ specified. */
if (pat_patctl.jit == 0 &&
(pat_patctl.control & (CTL_JITVERIFY|CTL_JITFAST)) != 0)
- pat_patctl.jit = 7;
+ pat_patctl.jit = JIT_DEFAULT;
/* Now copy the pattern to pbuffer8 for use in 8-bit testing and for reflecting
in callouts. Convert from hex if requested (literal strings in quotes may be
@@ -5638,6 +5765,7 @@ if (TEST(compiled_code, !=, NULL) && pat_patctl.jit != 0)
{
int i;
clock_t time_taken = 0;
+
for (i = 0; i < timeit; i++)
{
clock_t start_time;
@@ -5646,7 +5774,7 @@ if (TEST(compiled_code, !=, NULL) && pat_patctl.jit != 0)
pat_patctl.options|use_forbid_utf, &errorcode, &erroroffset,
use_pat_context);
start_time = clock();
- PCRE2_JIT_COMPILE(jitrc,compiled_code, pat_patctl.jit);
+ PCRE2_JIT_COMPILE(jitrc, compiled_code, pat_patctl.jit);
time_taken += clock() - start_time;
}
total_jit_compile_time += time_taken;
@@ -5717,6 +5845,11 @@ if (forbid_utf != 0)
if (pattern_info(PCRE2_INFO_MAXLOOKBEHIND, &maxlookbehind, FALSE) != 0)
return PR_ABEND;
+/* Remember the number of captures. */
+
+if (pattern_info(PCRE2_INFO_CAPTURECOUNT, &maxcapcount, FALSE) < 0)
+ return PR_ABEND;
+
/* If an explicit newline modifier was given, set the information flag in the
pattern so that it is preserved over push/pop. */
@@ -5886,6 +6019,58 @@ return capcount;
+/*************************************************
+* Substitute callout function *
+*************************************************/
+
+/* Called from pcre2_substitute() when the substitute_callout modifier is set.
+Print out the data that is passed back. The substitute callout block is
+identical for all code unit widths, so we just pick one.
+
+Arguments:
+ scb pointer to substitute callout block
+ data_ptr callout data
+
+Returns: nothing
+*/
+
+static int
+substitute_callout_function(pcre2_substitute_callout_block_8 *scb,
+ void *data_ptr)
+{
+int yield = 0;
+BOOL utf = (FLD(compiled_code, overall_options) & PCRE2_UTF) != 0;
+(void)data_ptr; /* Not used */
+
+fprintf(outfile, "%2d(%d) Old %" SIZ_FORM " %" SIZ_FORM " \"",
+ scb->subscount, scb->oveccount,
+ SIZ_CAST scb->ovector[0], SIZ_CAST scb->ovector[1]);
+
+PCHARSV(scb->input, scb->ovector[0], scb->ovector[1] - scb->ovector[0],
+ utf, outfile);
+
+fprintf(outfile, "\" New %" SIZ_FORM " %" SIZ_FORM " \"",
+ SIZ_CAST scb->output_offsets[0], SIZ_CAST scb->output_offsets[1]);
+
+PCHARSV(scb->output, scb->output_offsets[0],
+ scb->output_offsets[1] - scb->output_offsets[0], utf, outfile);
+
+if (scb->subscount == dat_datctl.substitute_stop)
+ {
+ yield = -1;
+ fprintf(outfile, " STOPPED");
+ }
+else if (scb->subscount == dat_datctl.substitute_skip)
+ {
+ yield = +1;
+ fprintf(outfile, " SKIPPED");
+ }
+
+fprintf(outfile, "\"\n");
+return yield;
+}
+
+
/*************************************************
* Callout function *
*************************************************/
@@ -5897,8 +6082,11 @@ callout block for different code unit widths are that the pointers to the
subject, the most recent MARK, and a callout argument string point to strings
of the appropriate width. Casts can be used to deal with this.
-Argument: a pointer to a callout block
-Return:
+Arguments:
+ cb a pointer to a callout block
+ callout_data_ptr the provided callout data
+
+Returns: 0 or 1 or an error, as determined by settings
*/
static int
@@ -6317,6 +6505,42 @@ return TRUE;
+/*************************************************
+* Show an entire ovector *
+*************************************************/
+
+/* This function is called after partial matching or match failure, when the
+"allvector" modifier is set. It is a means of checking the contents of the
+entire ovector, to ensure no modification of fields that should be unchanged.
+
+Arguments:
+ ovector points to the ovector
+ oveccount number of pairs
+
+Returns: nothing
+*/
+
+static void
+show_ovector(PCRE2_SIZE *ovector, uint32_t oveccount)
+{
+uint32_t i;
+for (i = 0; i < 2*oveccount; i += 2)
+ {
+ PCRE2_SIZE start = ovector[i];
+ PCRE2_SIZE end = ovector[i+1];
+
+ fprintf(outfile, "%2d: ", i/2);
+ if (start == PCRE2_UNSET && end == PCRE2_UNSET)
+ fprintf(outfile, "\n");
+ else if (start == JUNK_OFFSET && end == JUNK_OFFSET)
+ fprintf(outfile, "\n");
+ else
+ fprintf(outfile, "%ld %ld\n", (unsigned long int)start,
+ (unsigned long int)end);
+ }
+}
+
+
/*************************************************
* Process a data line *
*************************************************/
@@ -6342,7 +6566,10 @@ size_t needlen;
void *use_dat_context;
BOOL utf;
BOOL subject_literal;
+
+PCRE2_SIZE *ovector;
PCRE2_SIZE ovecsave[3];
+uint32_t oveccount;
#ifdef SUPPORT_PCRE2_8
uint8_t *q8 = NULL;
@@ -6369,6 +6596,11 @@ dat_datctl.control2 |= (pat_patctl.control2 & CTL2_ALLPD);
strcpy((char *)dat_datctl.replacement, (char *)pat_patctl.replacement);
if (dat_datctl.jitstack == 0) dat_datctl.jitstack = pat_patctl.jitstack;
+if (dat_datctl.substitute_skip == 0)
+ dat_datctl.substitute_skip = pat_patctl.substitute_skip;
+if (dat_datctl.substitute_stop == 0)
+ dat_datctl.substitute_stop = pat_patctl.substitute_stop;
+
/* Initialize for scanning the data line. */
#ifdef SUPPORT_PCRE2_8
@@ -6651,7 +6883,7 @@ while ((c = *p++) != 0)
fprintf(outfile, "** Truncation will probably give the wrong "
"result.\n");
}
- *q8++ = c;
+ *q8++ = (uint8_t)c;
}
}
#endif
@@ -6685,7 +6917,7 @@ while ((c = *p++) != 0)
"result.\n");
}
- *q16++ = c;
+ *q16++ = (uint16_t)c;
}
}
#endif
@@ -6708,6 +6940,11 @@ arg_ulen = ulen; /* Value to use in match arg */
if (p[-1] != 0 && !decode_modifiers(p, CTX_DAT, NULL, &dat_datctl))
return PR_OK;
+/* Setting substitute_{skip,fail} implies a substitute callout. */
+
+if (dat_datctl.substitute_skip != 0 || dat_datctl.substitute_stop != 0)
+ dat_datctl.control2 |= CTL2_SUBSTITUTE_CALLOUT;
+
/* Check for mutually exclusive modifiers. At present, these are all in the
first control word. */
@@ -6722,11 +6959,25 @@ for (k = 0; k < sizeof(exclusive_dat_controls)/sizeof(uint32_t); k++)
}
}
-if (pat_patctl.replacement[0] != 0 &&
- (dat_datctl.control & CTL_NULLCONTEXT) != 0)
+if (pat_patctl.replacement[0] != 0)
{
- fprintf(outfile, "** Replacement text is not supported with null_context.\n");
- return PR_OK;
+ if ((dat_datctl.control2 & CTL2_SUBSTITUTE_CALLOUT) != 0 &&
+ (dat_datctl.control & CTL_NULLCONTEXT) != 0)
+ {
+ fprintf(outfile, "** Replacement callouts are not supported with null_context.\n");
+ return PR_OK;
+ }
+
+ if ((dat_datctl.control & CTL_ALLCAPTURES) != 0)
+ fprintf(outfile, "** Ignored with replacement text: allcaptures\n");
+ }
+
+/* Warn for modifiers that are ignored for DFA. */
+
+if ((dat_datctl.control & CTL_DFA) != 0)
+ {
+ if ((dat_datctl.control & CTL_ALLCAPTURES) != 0)
+ fprintf(outfile, "** Ignored after DFA matching: allcaptures\n");
}
/* We now have the subject in dbuffer, with len containing the byte length, and
@@ -6955,6 +7206,9 @@ if (CASTVAR(void *, match_data) == NULL)
return PR_OK;
}
+ovector = FLD(match_data, ovector);
+PCRE2_GET_OVECTOR_COUNT(oveccount, match_data);
+
/* Replacement processing is ignored for DFA matching. */
if (dat_datctl.replacement[0] != 0 && (dat_datctl.control & CTL_DFA) != 0)
@@ -6974,7 +7228,7 @@ if (dat_datctl.replacement[0] != 0)
uint8_t rbuffer[REPLACE_BUFFSIZE];
uint8_t nbuffer[REPLACE_BUFFSIZE];
uint32_t xoptions;
- PCRE2_SIZE rlen, nsize, erroroffset;
+ PCRE2_SIZE j, rlen, nsize, erroroffset;
BOOL badutf = FALSE;
#ifdef SUPPORT_PCRE2_8
@@ -6987,6 +7241,11 @@ if (dat_datctl.replacement[0] != 0)
uint32_t *r32 = NULL;
#endif
+ /* Fill the ovector with junk to detect elements that do not get set
+ when they should be (relevant only when "allvector" is specified). */
+
+ for (j = 0; j < 2*oveccount; j++) ovector[j] = JUNK_OFFSET;
+
if (timeitm)
fprintf(outfile, "** Timing is not supported with replace: ignored\n");
@@ -7089,8 +7348,18 @@ if (dat_datctl.replacement[0] != 0)
rlen = PCRE2_ZERO_TERMINATED;
else
rlen = (CASTVAR(uint8_t *, r) - rbuffer)/code_unit_size;
+
+ if ((dat_datctl.control2 & CTL2_SUBSTITUTE_CALLOUT) != 0)
+ {
+ PCRE2_SET_SUBSTITUTE_CALLOUT(dat_context, substitute_callout_function, NULL);
+ }
+ else
+ {
+ PCRE2_SET_SUBSTITUTE_CALLOUT(dat_context, NULL, NULL); /* No callout */
+ }
+
PCRE2_SUBSTITUTE(rc, compiled_code, pp, arg_ulen, dat_datctl.offset,
- dat_datctl.options|xoptions, match_data, dat_context,
+ dat_datctl.options|xoptions, match_data, use_dat_context,
rbuffer, rlen, nbuffer, &nsize);
if (rc < 0)
@@ -7112,6 +7381,12 @@ if (dat_datctl.replacement[0] != 0)
fprintf(outfile, "\n");
show_memory = FALSE;
+
+ /* Show final ovector contents if requested. */
+
+ if ((dat_datctl.control2 & CTL2_ALLVECTOR) != 0)
+ show_ovector(ovector, oveccount);
+
return PR_OK;
} /* End of substitution handling */
@@ -7125,14 +7400,11 @@ for (gmatched = 0;; gmatched++)
{
PCRE2_SIZE j;
int capcount;
- PCRE2_SIZE *ovector;
-
- ovector = FLD(match_data, ovector);
/* Fill the ovector with junk to detect elements that do not get set
when they should be. */
- for (j = 0; j < 2*dat_datctl.oveccount; j++) ovector[j] = JUNK_OFFSET;
+ for (j = 0; j < 2*oveccount; j++) ovector[j] = JUNK_OFFSET;
/* When matching is via pcre2_match(), we will detect the use of JIT via the
stack callback function. */
@@ -7280,12 +7552,8 @@ for (gmatched = 0;; gmatched++)
if (capcount >= 0)
{
int i;
- uint32_t oveccount;
-
- /* This is a check against a lunatic return value. */
- PCRE2_GET_OVECTOR_COUNT(oveccount, match_data);
- if (capcount > (int)oveccount)
+ if (capcount > (int)oveccount) /* Check for lunatic return value */
{
fprintf(outfile,
"** PCRE2 error: returned count %d is too big for ovector count %d\n",
@@ -7298,6 +7566,25 @@ for (gmatched = 0;; gmatched++)
}
}
+ /* If PCRE2_COPY_MATCHED_SUBJECT was set, check that things are as they
+ should be, but not for fast JIT, where it isn't supported. */
+
+ if ((dat_datctl.options & PCRE2_COPY_MATCHED_SUBJECT) != 0 &&
+ (pat_patctl.control & CTL_JITFAST) == 0)
+ {
+ if ((FLD(match_data, flags) & PCRE2_MD_COPIED_SUBJECT) == 0)
+ fprintf(outfile,
+ "** PCRE2 error: flag not set after copy_matched_subject\n");
+
+ if (CASTFLD(void *, match_data, subject) == pp)
+ fprintf(outfile,
+ "** PCRE2 error: copy_matched_subject has not copied\n");
+
+ if (memcmp(CASTFLD(void *, match_data, subject), pp, ulen) != 0)
+ fprintf(outfile,
+ "** PCRE2 error: copy_matched_subject mismatch\n");
+ }
+
/* If this is not the first time round a global loop, check that the
returned string has changed. If it has not, check for an empty string match
at different starting offset from the previous match. This is a failed test
@@ -7325,24 +7612,18 @@ for (gmatched = 0;; gmatched++)
/* "allcaptures" requests showing of all captures in the pattern, to check
unset ones at the end. It may be set on the pattern or the data. Implement
by setting capcount to the maximum. This is not relevant for DFA matching,
- so ignore it. */
+ so ignore it (warning given above). */
- if ((dat_datctl.control & CTL_ALLCAPTURES) != 0)
+ if ((dat_datctl.control & (CTL_ALLCAPTURES|CTL_DFA)) == CTL_ALLCAPTURES)
{
- uint32_t maxcapcount;
- if ((dat_datctl.control & CTL_DFA) != 0)
- {
- fprintf(outfile, "** Ignored after DFA matching: allcaptures\n");
- }
- else
- {
- if (pattern_info(PCRE2_INFO_CAPTURECOUNT, &maxcapcount, FALSE) < 0)
- return PR_SKIP;
- capcount = maxcapcount + 1; /* Allow for full match */
- if (capcount > (int)oveccount) capcount = oveccount;
- }
+ capcount = maxcapcount + 1; /* Allow for full match */
+ if (capcount > (int)oveccount) capcount = oveccount;
}
+ /* "allvector" request showing the entire ovector. */
+
+ if ((dat_datctl.control2 & CTL2_ALLVECTOR) != 0) capcount = oveccount;
+
/* Output the captured substrings. Note that, for the matched string,
the use of \K in an assertion can make the start later than the end. */
@@ -7364,19 +7645,26 @@ for (gmatched = 0;; gmatched++)
/* Check for an unset group */
- if (start == PCRE2_UNSET)
+ if (start == PCRE2_UNSET && end == PCRE2_UNSET)
{
fprintf(outfile, "\n");
continue;
}
/* Check for silly offsets, in particular, values that have not been
- set when they should have been. */
+ set when they should have been. However, if we are past the end of the
+ captures for this pattern ("allvector" causes this), or if we are DFA
+ matching, it isn't an error if the entry is unchanged. */
if (start > ulen || end > ulen)
{
- fprintf(outfile, "ERROR: bad value(s) for offset(s): 0x%lx 0x%lx\n",
- (unsigned long int)start, (unsigned long int)end);
+ if (((dat_datctl.control & CTL_DFA) != 0 ||
+ i >= (int)(2*maxcapcount + 2)) &&
+ start == JUNK_OFFSET && end == JUNK_OFFSET)
+ fprintf(outfile, "\n");
+ else
+ fprintf(outfile, "ERROR: bad value(s) for offset(s): 0x%lx 0x%lx\n",
+ (unsigned long int)start, (unsigned long int)end);
continue;
}
@@ -7481,14 +7769,22 @@ for (gmatched = 0;; gmatched++)
} /* End of handling a successful match */
/* There was a partial match. The value of ovector[0] is the bumpalong point,
- that is, startchar, not any \K point that might have been passed. */
+ that is, startchar, not any \K point that might have been passed. When JIT is
+ not in use, "allusedtext" may be set, in which case we indicate the leftmost
+ consulted character. */
else if (capcount == PCRE2_ERROR_PARTIAL)
{
- PCRE2_SIZE poffset;
+ PCRE2_SIZE leftchar;
int backlength;
int rubriclength = 0;
+ if ((dat_datctl.control & CTL_ALLUSEDTEXT) != 0)
+ {
+ leftchar = FLD(match_data, leftchar);
+ }
+ else leftchar = ovector[0];
+
fprintf(outfile, "Partial match");
if ((dat_datctl.control & CTL_MARK) != 0 &&
TESTFLD(match_data, mark, !=, NULL))
@@ -7501,8 +7797,7 @@ for (gmatched = 0;; gmatched++)
fprintf(outfile, ": ");
rubriclength += 15;
- poffset = backchars(pp, ovector[0], maxlookbehind, utf);
- PCHARS(backlength, pp, poffset, ovector[0] - poffset, utf, outfile);
+ PCHARS(backlength, pp, leftchar, ovector[0] - leftchar, utf, outfile);
PCHARSV(pp, ovector[0], ulen - ovector[0], utf, outfile);
if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)
@@ -7517,10 +7812,19 @@ for (gmatched = 0;; gmatched++)
fprintf(outfile, "\n");
}
+ if (ulen != ovector[1])
+ fprintf(outfile, "** ovector[1] is not equal to the subject length: "
+ "%ld != %ld\n", (unsigned long int)ovector[1], (unsigned long int)ulen);
+
/* Process copy/get strings */
if (!copy_and_get(utf, 1)) return PR_ABEND;
+ /* "allvector" outputs the entire vector */
+
+ if ((dat_datctl.control2 & CTL2_ALLVECTOR) != 0)
+ show_ovector(ovector, oveccount);
+
break; /* Out of the /g loop */
} /* End of handling partial match */
@@ -7590,6 +7894,11 @@ for (gmatched = 0;; gmatched++)
if ((pat_patctl.control & CTL_JITVERIFY) != 0 && jit_was_used)
fprintf(outfile, " (JIT)");
fprintf(outfile, "\n");
+
+ /* "allvector" outputs the entire vector */
+
+ if ((dat_datctl.control2 & CTL2_ALLVECTOR) != 0)
+ show_ovector(ovector, oveccount);
}
break;
@@ -7771,7 +8080,7 @@ Returns: nothing
static void
print_newline_config(uint32_t optval, BOOL isc)
{
-if (!isc) printf(" Newline sequence is ");
+if (!isc) printf(" Default newline sequence is ");
if (optval < sizeof(newlines)/sizeof(char *))
printf("%s\n", newlines[optval]);
else
@@ -7827,6 +8136,7 @@ printf(" -error show messages for error numbers, then exit\n");
printf(" -help show usage information\n");
printf(" -i set default pattern modifier 'info'\n");
printf(" -jit set default pattern modifier 'jit'\n");
+printf(" -jitfast set default pattern modifier 'jitfast'\n");
printf(" -jitverify set default pattern modifier 'jitverify'\n");
printf(" -LM list pattern and subject modifiers, then exit\n");
printf(" -q quiet: do not output PCRE2 version number at start\n");
@@ -7901,9 +8211,13 @@ if (arg != NULL && arg[0] != CHAR_MINUS)
break;
}
-/* For VMS, return the value by setting a symbol, for certain values only. */
+/* For VMS, return the value by setting a symbol, for certain values only. This
+is contributed code which the PCRE2 developers have no means of testing. */
#ifdef __VMS
+
+/* This is the original code provided by the first VMS contributor. */
+#ifdef NEVER
if (copytlist[i].type == CONF_FIX || coptlist[i].type == CONF_INT)
{
char ucname[16];
@@ -7913,6 +8227,22 @@ if (arg != NULL && arg[0] != CHAR_MINUS)
}
#endif
+/* This is the new code, provided by a second VMS contributor. */
+
+ if (coptlist[i].type == CONF_FIX || coptlist[i].type == CONF_INT)
+ {
+ char nam_buf[22], val_buf[4];
+ $DESCRIPTOR(nam, nam_buf);
+ $DESCRIPTOR(val, val_buf);
+
+ strcpy(nam_buf, coptlist[i].name);
+ nam.dsc$w_length = strlen(nam_buf);
+ sprintf(val_buf, "%d", yield);
+ val.dsc$w_length = strlen(val_buf);
+ lib$set_symbol(&nam, &val);
+ }
+#endif /* __VMS */
+
return yield;
}
@@ -7971,11 +8301,20 @@ printf(" Internal link size = %d\n", optval);
(void)PCRE2_CONFIG(PCRE2_CONFIG_PARENSLIMIT, &optval);
printf(" Parentheses nest limit = %d\n", optval);
(void)PCRE2_CONFIG(PCRE2_CONFIG_HEAPLIMIT, &optval);
-printf(" Default heap limit = %d\n", optval);
+printf(" Default heap limit = %d kibibytes\n", optval);
(void)PCRE2_CONFIG(PCRE2_CONFIG_MATCHLIMIT, &optval);
printf(" Default match limit = %d\n", optval);
(void)PCRE2_CONFIG(PCRE2_CONFIG_DEPTHLIMIT, &optval);
printf(" Default depth limit = %d\n", optval);
+
+#if defined SUPPORT_LIBREADLINE
+printf(" pcre2test has libreadline support\n");
+#elif defined SUPPORT_LIBEDIT
+printf(" pcre2test has libedit support\n");
+#else
+printf(" pcre2test has neither libreadline nor libedit support\n");
+#endif
+
return 0;
}
@@ -8312,13 +8651,15 @@ while (argc > 1 && argv[op][0] == '-' && argv[op][1] != 0)
else if (strcmp(arg, "-d") == 0) def_patctl.control |= CTL_DEBUG;
else if (strcmp(arg, "-dfa") == 0) def_datctl.control |= CTL_DFA;
else if (strcmp(arg, "-i") == 0) def_patctl.control |= CTL_INFO;
- else if (strcmp(arg, "-jit") == 0 || strcmp(arg, "-jitverify") == 0)
+ else if (strcmp(arg, "-jit") == 0 || strcmp(arg, "-jitverify") == 0 ||
+ strcmp(arg, "-jitfast") == 0)
{
- if (arg[4] != 0) def_patctl.control |= CTL_JITVERIFY;
- def_patctl.jit = 7; /* full & partial */
+ if (arg[4] == 'v') def_patctl.control |= CTL_JITVERIFY;
+ else if (arg[4] == 'f') def_patctl.control |= CTL_JITFAST;
+ def_patctl.jit = JIT_DEFAULT; /* full & partial */
#ifndef SUPPORT_JIT
fprintf(stderr, "** Warning: JIT support is not available: "
- "-jit[verify] calls functions that do nothing.\n");
+ "-jit[fast|verify] calls functions that do nothing.\n");
#endif
}
@@ -8331,6 +8672,11 @@ while (argc > 1 && argv[op][0] == '-' && argv[op][1] != 0)
showtotaltimes = arg[1] == 'T';
if (argc > 2 && (uli = strtoul(argv[op+1], &endptr, 10), *endptr == 0))
{
+ if (uli == 0)
+ {
+ fprintf(stderr, "** Argument for %s must not be zero\n", arg);
+ exit(1);
+ }
if (U32OVERFLOW(uli))
{
fprintf(stderr, "** Argument for %s is too big\n", arg);
@@ -8488,8 +8834,8 @@ least 128 code units, because it is used for retrieving error messages. */
} /* End of -error handling */
/* Initialize things that cannot be done until we know which test mode we are
-running in. Exercise the general context copying function, which is not
-otherwise used. */
+running in. Exercise the general context copying and match data size functions,
+which are not otherwise used. */
code_unit_size = test_mode/8;
max_oveccount = DEFAULT_OVECCOUNT;
@@ -8511,7 +8857,9 @@ max_oveccount = DEFAULT_OVECCOUNT;
(void)G(pcre2_set_compile_extra_options_,BITS)(G(pat_context,BITS), 0); \
(void)G(pcre2_set_max_pattern_length_,BITS)(G(pat_context,BITS), 0); \
(void)G(pcre2_set_offset_limit_,BITS)(G(dat_context,BITS), 0); \
- (void)G(pcre2_set_recursion_memory_management_,BITS)(G(dat_context,BITS), my_malloc, my_free, NULL)
+ (void)G(pcre2_set_recursion_memory_management_,BITS)(G(dat_context,BITS), my_malloc, my_free, NULL); \
+ (void)G(pcre2_get_match_data_size_,BITS)(G(match_data,BITS))
+
/* Call the appropriate functions for the current mode, and exercise some
functions that are not otherwise called. */
diff --git a/src/sljit/sljitConfigInternal.h b/src/sljit/sljitConfigInternal.h
index f5703e8..acba9da 100644
--- a/src/sljit/sljitConfigInternal.h
+++ b/src/sljit/sljitConfigInternal.h
@@ -214,6 +214,10 @@
#define SLJIT_MEMCPY(dest, src, len) memcpy(dest, src, len)
#endif
+#ifndef SLJIT_MEMMOVE
+#define SLJIT_MEMMOVE(dest, src, len) memmove(dest, src, len)
+#endif
+
#ifndef SLJIT_ZEROMEM
#define SLJIT_ZEROMEM(dest, len) memset(dest, 0, len)
#endif
@@ -530,7 +534,7 @@ typedef double sljit_f64;
#endif /* !SLJIT_FUNC */
#ifndef SLJIT_INDIRECT_CALL
-#if ((defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) && (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN)) \
+#if ((defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) && (!defined _CALL_ELF || _CALL_ELF == 1)) \
|| ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && defined _AIX)
/* It seems certain ppc compilers use an indirect addressing for functions
which makes things complicated. */
diff --git a/src/sljit/sljitExecAllocator.c b/src/sljit/sljitExecAllocator.c
index 7c18578..92ddb94 100644
--- a/src/sljit/sljitExecAllocator.c
+++ b/src/sljit/sljitExecAllocator.c
@@ -94,28 +94,88 @@ static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
#else
+#ifdef __APPLE__
+/* Configures TARGET_OS_OSX when appropriate */
+#include
+
+#if TARGET_OS_OSX && defined(MAP_JIT)
+#include
+#endif /* TARGET_OS_OSX && MAP_JIT */
+
+#ifdef MAP_JIT
+
+static SLJIT_INLINE int get_map_jit_flag()
+{
+#if TARGET_OS_OSX
+ /* On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a version
+ of macOS where it's OK to have more than one JIT block. On non-macOS systems, returns
+ MAP_JIT if it is defined. */
+ static int map_jit_flag = -1;
+
+ /* The following code is thread safe because multiple initialization
+ sets map_jit_flag to the same value and the code has no side-effects.
+ Changing the kernel version witout system restart is (very) unlikely. */
+ if (map_jit_flag == -1) {
+ struct utsname name;
+
+ map_jit_flag = 0;
+ uname(&name);
+
+ /* Kernel version for 10.14.0 (Mojave) */
+ if (atoi(name.release) >= 18) {
+ /* Only use MAP_JIT if a hardened runtime is used, because MAP_JIT is incompatible with fork(). */
+ void *ptr = mmap(NULL, getpagesize(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+
+ if (ptr == MAP_FAILED) {
+ map_jit_flag = MAP_JIT;
+ } else {
+ munmap(ptr, getpagesize());
+ }
+ }
+ }
+
+ return map_jit_flag;
+#else /* !TARGET_OS_OSX */
+ return MAP_JIT;
+#endif /* TARGET_OS_OSX */
+}
+
+#endif /* MAP_JIT */
+
+#endif /* __APPLE__ */
+
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
{
void *retval;
+ const int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
#ifdef MAP_ANON
int flags = MAP_PRIVATE | MAP_ANON;
#ifdef MAP_JIT
- flags |= MAP_JIT;
+ flags |= get_map_jit_flag();
#endif
- retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, flags, -1, 0);
-#else
+ retval = mmap(NULL, size, prot, flags, -1, 0);
+#else /* !MAP_ANON */
if (dev_zero < 0) {
if (open_dev_zero())
return NULL;
}
- retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, dev_zero, 0);
-#endif
+ retval = mmap(NULL, size, prot, MAP_PRIVATE, dev_zero, 0);
+#endif /* MAP_ANON */
+
+ if (retval == MAP_FAILED)
+ retval = NULL;
+ else {
+ if (mprotect(retval, size, prot) < 0) {
+ munmap(retval, size);
+ retval = NULL;
+ }
+ }
- return (retval != MAP_FAILED) ? retval : NULL;
+ return retval;
}
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
diff --git a/src/sljit/sljitLir.c b/src/sljit/sljitLir.c
index 5bdddc1..9bab0c3 100644
--- a/src/sljit/sljitLir.c
+++ b/src/sljit/sljitLir.c
@@ -144,6 +144,7 @@
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
# define PATCH_MD 0x10
#endif
+# define TYPE_SHIFT 13
#endif
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
@@ -201,15 +202,16 @@
# define IS_CALL 0x010
# define IS_BIT26_COND 0x020
# define IS_BIT16_COND 0x040
+# define IS_BIT23_COND 0x080
-# define IS_COND (IS_BIT26_COND | IS_BIT16_COND)
+# define IS_COND (IS_BIT26_COND | IS_BIT16_COND | IS_BIT23_COND)
-# define PATCH_B 0x080
-# define PATCH_J 0x100
+# define PATCH_B 0x100
+# define PATCH_J 0x200
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
-# define PATCH_ABS32 0x200
-# define PATCH_ABS48 0x400
+# define PATCH_ABS32 0x400
+# define PATCH_ABS48 0x800
#endif
/* instruction types */
@@ -520,6 +522,12 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
}
}
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label)
+{
+ if (SLJIT_LIKELY(!!put_label))
+ put_label->label = label;
+}
+
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags)
{
SLJIT_UNUSED_ARG(compiler);
@@ -619,6 +627,30 @@ static SLJIT_INLINE sljit_s32 get_arg_count(sljit_s32 arg_types)
return arg_count;
}
+#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+
+static SLJIT_INLINE sljit_uw compute_next_addr(struct sljit_label *label, struct sljit_jump *jump,
+ struct sljit_const *const_, struct sljit_put_label *put_label)
+{
+ sljit_uw result = ~(sljit_uw)0;
+
+ if (label)
+ result = label->size;
+
+ if (jump && jump->addr < result)
+ result = jump->addr;
+
+ if (const_ && const_->addr < result)
+ result = const_->addr;
+
+ if (put_label && put_label->addr < result)
+ result = put_label->addr;
+
+ return result;
+}
+
+#endif /* !SLJIT_CONFIG_X86 */
+
static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler,
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
@@ -686,6 +718,19 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
compiler->last_const = const_;
}
+static SLJIT_INLINE void set_put_label(struct sljit_put_label *put_label, struct sljit_compiler *compiler, sljit_uw offset)
+{
+ put_label->next = NULL;
+ put_label->label = NULL;
+ put_label->addr = compiler->size - offset;
+ put_label->flags = 0;
+ if (compiler->last_put_label)
+ compiler->last_put_label->next = put_label;
+ else
+ compiler->put_labels = put_label;
+ compiler->last_put_label = put_label;
+}
+
#define ADDRESSING_DEPENDS_ON(exp, reg) \
(((exp) & SLJIT_MEM) && (((exp) & REG_MASK) == reg || OFFS_REG(exp) == reg))
@@ -1904,6 +1949,21 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compil
CHECK_RETURN_OK;
}
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ FUNCTION_CHECK_DST(dst, dstw, 0);
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " put_label ");
+ sljit_verbose_param(compiler, dst, dstw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif
+ CHECK_RETURN_OK;
+}
+
#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */
#define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \
@@ -2580,6 +2640,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
return NULL;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(dst);
+ SLJIT_UNUSED_ARG(dstw);
+ return NULL;
+}
+
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
SLJIT_UNUSED_ARG(addr);
@@ -2596,4 +2664,4 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
SLJIT_UNREACHABLE();
}
-#endif
+#endif /* !SLJIT_CONFIG_UNSUPPORTED */
diff --git a/src/sljit/sljitLir.h b/src/sljit/sljitLir.h
index e71890c..836d25c 100644
--- a/src/sljit/sljitLir.h
+++ b/src/sljit/sljitLir.h
@@ -348,13 +348,20 @@ struct sljit_label {
struct sljit_jump {
struct sljit_jump *next;
sljit_uw addr;
- sljit_sw flags;
+ sljit_uw flags;
union {
sljit_uw target;
- struct sljit_label* label;
+ struct sljit_label *label;
} u;
};
+struct sljit_put_label {
+ struct sljit_put_label *next;
+ struct sljit_label *label;
+ sljit_uw addr;
+ sljit_uw flags;
+};
+
struct sljit_const {
struct sljit_const *next;
sljit_uw addr;
@@ -366,10 +373,12 @@ struct sljit_compiler {
struct sljit_label *labels;
struct sljit_jump *jumps;
+ struct sljit_put_label *put_labels;
struct sljit_const *consts;
struct sljit_label *last_label;
struct sljit_jump *last_jump;
struct sljit_const *last_const;
+ struct sljit_put_label *last_put_label;
void *allocator_data;
struct sljit_memory_fragment *buf;
@@ -1314,10 +1323,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
Flags: - (may destroy flags) */
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset);
-/* The constant can be changed runtime (see: sljit_set_const)
+/* Store a value that can be changed runtime (see: sljit_get_const_addr / sljit_set_const)
Flags: - (does not modify flags) */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value);
+/* Store the value of a label (see: sljit_set_put_label)
+ Flags: - (does not modify flags) */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw);
+
+/* Set the value stored by put_label to this label. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label);
+
/* After the code generation the address for label, jump and const instructions
are computed. Since these structures are freed by sljit_free_compiler, the
addresses must be preserved by the user program elsewere. */
diff --git a/src/sljit/sljitNativeARM_32.c b/src/sljit/sljitNativeARM_32.c
index 6d61eed..71f7bcd 100644
--- a/src/sljit/sljitNativeARM_32.c
+++ b/src/sljit/sljitNativeARM_32.c
@@ -583,8 +583,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_uw *buf_end;
sljit_uw size;
sljit_uw word_count;
+ sljit_uw next_addr;
sljit_sw executable_offset;
- sljit_sw jump_addr;
+ sljit_sw addr;
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
sljit_uw cpool_size;
sljit_uw cpool_skip_alignment;
@@ -597,6 +598,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
+ struct sljit_put_label *put_label;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_generate_code(compiler));
@@ -625,11 +627,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
word_count = 0;
+ next_addr = 1;
executable_offset = SLJIT_EXEC_OFFSET(code);
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+ put_label = compiler->put_labels;
if (label && label->size == 0) {
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
@@ -669,35 +673,45 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
else if ((*buf_ptr & 0xff000000) != PUSH_POOL) {
#endif
*code_ptr = *buf_ptr++;
+ if (next_addr == word_count) {
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+ SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
+
/* These structures are ordered by their address. */
- SLJIT_ASSERT(!label || label->size >= word_count);
- SLJIT_ASSERT(!jump || jump->addr >= word_count);
- SLJIT_ASSERT(!const_ || const_->addr >= word_count);
- if (jump && jump->addr == word_count) {
+ if (jump && jump->addr == word_count) {
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
- if (detect_jump_type(jump, code_ptr, code, executable_offset))
- code_ptr--;
- jump->addr = (sljit_uw)code_ptr;
+ if (detect_jump_type(jump, code_ptr, code, executable_offset))
+ code_ptr--;
+ jump->addr = (sljit_uw)code_ptr;
#else
- jump->addr = (sljit_uw)(code_ptr - 2);
- if (detect_jump_type(jump, code_ptr, code, executable_offset))
- code_ptr -= 2;
+ jump->addr = (sljit_uw)(code_ptr - 2);
+ if (detect_jump_type(jump, code_ptr, code, executable_offset))
+ code_ptr -= 2;
#endif
- jump = jump->next;
- }
- if (label && label->size == word_count) {
- /* code_ptr can be affected above. */
- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr + 1, executable_offset);
- label->size = (code_ptr + 1) - code;
- label = label->next;
- }
- if (const_ && const_->addr == word_count) {
+ jump = jump->next;
+ }
+ if (label && label->size == word_count) {
+ /* code_ptr can be affected above. */
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr + 1, executable_offset);
+ label->size = (code_ptr + 1) - code;
+ label = label->next;
+ }
+ if (const_ && const_->addr == word_count) {
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
- const_->addr = (sljit_uw)code_ptr;
+ const_->addr = (sljit_uw)code_ptr;
#else
- const_->addr = (sljit_uw)(code_ptr - 1);
+ const_->addr = (sljit_uw)(code_ptr - 1);
#endif
- const_ = const_->next;
+ const_ = const_->next;
+ }
+ if (put_label && put_label->addr == word_count) {
+ SLJIT_ASSERT(put_label->label);
+ put_label->addr = (sljit_uw)code_ptr;
+ put_label = put_label->next;
+ }
+ next_addr = compute_next_addr(label, jump, const_, put_label);
}
code_ptr++;
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
@@ -725,6 +739,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(!put_label);
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
SLJIT_ASSERT(cpool_size == 0);
@@ -755,15 +770,15 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
buf_ptr = (sljit_uw *)jump->addr;
if (jump->flags & PATCH_B) {
- jump_addr = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset);
+ addr = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset);
if (!(jump->flags & JUMP_ADDR)) {
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
- SLJIT_ASSERT(((sljit_sw)jump->u.label->addr - jump_addr) <= 0x01ffffff && ((sljit_sw)jump->u.label->addr - jump_addr) >= -0x02000000);
- *buf_ptr |= (((sljit_sw)jump->u.label->addr - jump_addr) >> 2) & 0x00ffffff;
+ SLJIT_ASSERT(((sljit_sw)jump->u.label->addr - addr) <= 0x01ffffff && ((sljit_sw)jump->u.label->addr - addr) >= -0x02000000);
+ *buf_ptr |= (((sljit_sw)jump->u.label->addr - addr) >> 2) & 0x00ffffff;
}
else {
- SLJIT_ASSERT(((sljit_sw)jump->u.target - jump_addr) <= 0x01ffffff && ((sljit_sw)jump->u.target - jump_addr) >= -0x02000000);
- *buf_ptr |= (((sljit_sw)jump->u.target - jump_addr) >> 2) & 0x00ffffff;
+ SLJIT_ASSERT(((sljit_sw)jump->u.target - addr) <= 0x01ffffff && ((sljit_sw)jump->u.target - addr) >= -0x02000000);
+ *buf_ptr |= (((sljit_sw)jump->u.target - addr) >> 2) & 0x00ffffff;
}
}
else if (jump->flags & SLJIT_REWRITABLE_JUMP) {
@@ -813,6 +828,22 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
}
#endif
+ put_label = compiler->put_labels;
+ while (put_label) {
+ addr = put_label->label->addr;
+ buf_ptr = (sljit_uw*)put_label->addr;
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+ SLJIT_ASSERT((buf_ptr[0] & 0xffff0000) == 0xe59f0000);
+ buf_ptr[((buf_ptr[0] & 0xfff) >> 2) + 2] = addr;
+#else
+ SLJIT_ASSERT((buf_ptr[-1] & 0xfff00000) == MOVW && (buf_ptr[0] & 0xfff00000) == MOVT);
+ buf_ptr[-1] |= ((addr << 4) & 0xf0000) | (addr & 0xfff);
+ buf_ptr[0] |= ((addr >> 12) & 0xf0000) | ((addr >> 16) & 0xfff);
+#endif
+ put_label = put_label->next;
+ }
+
SLJIT_ASSERT(code_ptr - code <= (sljit_s32)size);
compiler->error = SLJIT_ERR_COMPILED;
@@ -2639,28 +2670,55 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
{
struct sljit_const *const_;
- sljit_s32 reg;
+ sljit_s32 dst_r;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
+ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG2;
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), init_value));
+ compiler->patches++;
+#else
+ PTR_FAIL_IF(emit_imm(compiler, dst_r, init_value));
+#endif
+
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
PTR_FAIL_IF(!const_);
+ set_const(const_, compiler);
- reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));
+ return const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_put_label *put_label;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG2;
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
- PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), init_value));
+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), 0));
compiler->patches++;
#else
- PTR_FAIL_IF(emit_imm(compiler, reg, init_value));
+ PTR_FAIL_IF(emit_imm(compiler, dst_r, 0));
#endif
- set_const(const_, compiler);
+
+ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
+ PTR_FAIL_IF(!put_label);
+ set_put_label(put_label, compiler, 0);
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));
- return const_;
+ return put_label;
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
diff --git a/src/sljit/sljitNativeARM_64.c b/src/sljit/sljitNativeARM_64.c
index 27af741..e15b345 100644
--- a/src/sljit/sljitNativeARM_64.c
+++ b/src/sljit/sljitNativeARM_64.c
@@ -51,7 +51,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
0, 0, 1, 2, 3, 4, 5, 6, 7
};
-#define W_OP (1 << 31)
+#define W_OP (1u << 31)
#define RD(rd) (reg_map[rd])
#define RT(rt) (reg_map[rt])
#define RN(rn) (reg_map[rn] << 5)
@@ -161,7 +161,7 @@ static SLJIT_INLINE void modify_imm64_const(sljit_ins* inst, sljit_uw new_imm)
inst[3] = MOVK | dst | ((new_imm >> 48) << 5) | (3 << 21);
}
-static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
+static SLJIT_INLINE sljit_sw detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
{
sljit_sw diff;
sljit_uw target_addr;
@@ -196,14 +196,14 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in
return 4;
}
- if (target_addr <= 0xffffffffl) {
+ if (target_addr < 0x100000000l) {
if (jump->flags & IS_COND)
code_ptr[-5] -= (2 << 5);
code_ptr[-2] = code_ptr[0];
return 2;
}
- if (target_addr <= 0xffffffffffffl) {
+ if (target_addr < 0x1000000000000l) {
if (jump->flags & IS_COND)
code_ptr[-5] -= (1 << 5);
jump->flags |= PATCH_ABS48;
@@ -215,6 +215,22 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in
return 0;
}
+static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
+{
+ if (max_label < 0x100000000l) {
+ put_label->flags = 0;
+ return 2;
+ }
+
+ if (max_label < 0x1000000000000l) {
+ put_label->flags = 1;
+ return 1;
+ }
+
+ put_label->flags = 2;
+ return 0;
+}
+
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
{
struct sljit_memory_fragment *buf;
@@ -223,6 +239,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_ins *buf_ptr;
sljit_ins *buf_end;
sljit_uw word_count;
+ sljit_uw next_addr;
sljit_sw executable_offset;
sljit_uw addr;
sljit_s32 dst;
@@ -230,6 +247,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
+ struct sljit_put_label *put_label;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_generate_code(compiler));
@@ -241,34 +259,47 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
word_count = 0;
+ next_addr = 0;
executable_offset = SLJIT_EXEC_OFFSET(code);
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+ put_label = compiler->put_labels;
do {
buf_ptr = (sljit_ins*)buf->memory;
buf_end = buf_ptr + (buf->used_size >> 2);
do {
*code_ptr = *buf_ptr++;
- /* These structures are ordered by their address. */
- SLJIT_ASSERT(!label || label->size >= word_count);
- SLJIT_ASSERT(!jump || jump->addr >= word_count);
- SLJIT_ASSERT(!const_ || const_->addr >= word_count);
- if (label && label->size == word_count) {
- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
- label = label->next;
- }
- if (jump && jump->addr == word_count) {
- jump->addr = (sljit_uw)(code_ptr - 4);
- code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
- jump = jump->next;
- }
- if (const_ && const_->addr == word_count) {
- const_->addr = (sljit_uw)code_ptr;
- const_ = const_->next;
+ if (next_addr == word_count) {
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+ SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
+
+ /* These structures are ordered by their address. */
+ if (label && label->size == word_count) {
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+ if (jump && jump->addr == word_count) {
+ jump->addr = (sljit_uw)(code_ptr - 4);
+ code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
+ jump = jump->next;
+ }
+ if (const_ && const_->addr == word_count) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ }
+ if (put_label && put_label->addr == word_count) {
+ SLJIT_ASSERT(put_label->label);
+ put_label->addr = (sljit_uw)(code_ptr - 3);
+ code_ptr -= put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
+ put_label = put_label->next;
+ }
+ next_addr = compute_next_addr(label, jump, const_, put_label);
}
code_ptr ++;
word_count ++;
@@ -286,6 +317,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(!put_label);
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
jump = compiler->jumps;
@@ -323,6 +355,23 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = jump->next;
}
+ put_label = compiler->put_labels;
+ while (put_label) {
+ addr = put_label->label->addr;
+ buf_ptr = (sljit_ins *)put_label->addr;
+
+ buf_ptr[0] |= (addr & 0xffff) << 5;
+ buf_ptr[1] |= ((addr >> 16) & 0xffff) << 5;
+
+ if (put_label->flags >= 1)
+ buf_ptr[2] |= ((addr >> 32) & 0xffff) << 5;
+
+ if (put_label->flags >= 2)
+ buf_ptr[3] |= ((addr >> 48) & 0xffff) << 5;
+
+ put_label = put_label->next;
+ }
+
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
@@ -560,7 +609,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
/* dst must be register, TMP_REG1
arg1 must be register, TMP_REG1, imm
arg2 must be register, TMP_REG2, imm */
- sljit_ins inv_bits = (flags & INT_OP) ? (1 << 31) : 0;
+ sljit_ins inv_bits = (flags & INT_OP) ? W_OP : 0;
sljit_ins inst_bits;
sljit_s32 op = (flags & 0xffff);
sljit_s32 reg;
@@ -710,7 +759,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(arg2));
case SLJIT_MOV_U8:
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
- return push_inst(compiler, (UBFM ^ (1 << 31)) | RD(dst) | RN(arg2) | (7 << 10));
+ return push_inst(compiler, (UBFM ^ W_OP) | RD(dst) | RN(arg2) | (7 << 10));
case SLJIT_MOV_S8:
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
if (!(flags & INT_OP))
@@ -718,7 +767,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (7 << 10));
case SLJIT_MOV_U16:
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
- return push_inst(compiler, (UBFM ^ (1 << 31)) | RD(dst) | RN(arg2) | (15 << 10));
+ return push_inst(compiler, (UBFM ^ W_OP) | RD(dst) | RN(arg2) | (15 << 10));
case SLJIT_MOV_S16:
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
if (!(flags & INT_OP))
@@ -728,7 +777,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
if ((flags & INT_OP) && dst == arg2)
return SLJIT_SUCCESS;
- return push_inst(compiler, (ORR ^ (1 << 31)) | RD(dst) | RN(TMP_ZERO) | RM(arg2));
+ return push_inst(compiler, (ORR ^ W_OP) | RD(dst) | RN(TMP_ZERO) | RM(arg2));
case SLJIT_MOV_S32:
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
if ((flags & INT_OP) && dst == arg2)
@@ -1080,7 +1129,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
{
- sljit_ins inv_bits = (op & SLJIT_I32_OP) ? (1 << 31) : 0;
+ sljit_ins inv_bits = (op & SLJIT_I32_OP) ? W_OP : 0;
CHECK_ERROR();
CHECK(check_sljit_emit_op0(compiler, op));
@@ -1360,7 +1409,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;
if (GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64)
- inv_bits |= (1 << 31);
+ inv_bits |= W_OP;
if (src & SLJIT_MEM) {
emit_fop_mem(compiler, (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE, TMP_FREG1, src, srcw);
@@ -1382,7 +1431,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
- inv_bits |= (1 << 31);
+ inv_bits |= W_OP;
if (src & SLJIT_MEM) {
emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) ? INT_SIZE : WORD_SIZE), TMP_REG1, src, srcw, TMP_REG1);
@@ -1662,7 +1711,7 @@ static SLJIT_INLINE struct sljit_jump* emit_cmp_to0(struct sljit_compiler *compi
sljit_s32 src, sljit_sw srcw)
{
struct sljit_jump *jump;
- sljit_ins inv_bits = (type & SLJIT_I32_OP) ? (1 << 31) : 0;
+ sljit_ins inv_bits = (type & SLJIT_I32_OP) ? W_OP : 0;
SLJIT_ASSERT((type & 0xff) == SLJIT_EQUAL || (type & 0xff) == SLJIT_NOT_EQUAL);
ADJUST_LOCAL_OFFSET(src, srcw);
@@ -1787,7 +1836,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
sljit_s32 dst_reg,
sljit_s32 src, sljit_sw srcw)
{
- sljit_ins inv_bits = (dst_reg & SLJIT_I32_OP) ? (1 << 31) : 0;
+ sljit_ins inv_bits = (dst_reg & SLJIT_I32_OP) ? W_OP : 0;
sljit_ins cc;
CHECK_ERROR();
@@ -1947,6 +1996,28 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
return const_;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_put_label *put_label;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, 0));
+
+ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
+ PTR_FAIL_IF(!put_label);
+ set_put_label(put_label, compiler, 1);
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));
+
+ return put_label;
+}
+
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
sljit_ins* inst = (sljit_ins*)addr;
diff --git a/src/sljit/sljitNativeARM_T2_32.c b/src/sljit/sljitNativeARM_T2_32.c
index d7024b6..cdfe4a4 100644
--- a/src/sljit/sljitNativeARM_T2_32.c
+++ b/src/sljit/sljitNativeARM_T2_32.c
@@ -365,11 +365,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_u16 *buf_ptr;
sljit_u16 *buf_end;
sljit_uw half_count;
+ sljit_uw next_addr;
sljit_sw executable_offset;
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
+ struct sljit_put_label *put_label;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_generate_code(compiler));
@@ -381,34 +383,46 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
half_count = 0;
+ next_addr = 0;
executable_offset = SLJIT_EXEC_OFFSET(code);
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+ put_label = compiler->put_labels;
do {
buf_ptr = (sljit_u16*)buf->memory;
buf_end = buf_ptr + (buf->used_size >> 1);
do {
*code_ptr = *buf_ptr++;
- /* These structures are ordered by their address. */
- SLJIT_ASSERT(!label || label->size >= half_count);
- SLJIT_ASSERT(!jump || jump->addr >= half_count);
- SLJIT_ASSERT(!const_ || const_->addr >= half_count);
- if (label && label->size == half_count) {
- label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;
- label->size = code_ptr - code;
- label = label->next;
- }
- if (jump && jump->addr == half_count) {
- jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_COND) ? 10 : 8);
- code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
- jump = jump->next;
- }
- if (const_ && const_->addr == half_count) {
- const_->addr = (sljit_uw)code_ptr;
- const_ = const_->next;
+ if (next_addr == half_count) {
+ SLJIT_ASSERT(!label || label->size >= half_count);
+ SLJIT_ASSERT(!jump || jump->addr >= half_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= half_count);
+ SLJIT_ASSERT(!put_label || put_label->addr >= half_count);
+
+ /* These structures are ordered by their address. */
+ if (label && label->size == half_count) {
+ label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+ if (jump && jump->addr == half_count) {
+ jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_COND) ? 10 : 8);
+ code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
+ jump = jump->next;
+ }
+ if (const_ && const_->addr == half_count) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ }
+ if (put_label && put_label->addr == half_count) {
+ SLJIT_ASSERT(put_label->label);
+ put_label->addr = (sljit_uw)code_ptr;
+ put_label = put_label->next;
+ }
+ next_addr = compute_next_addr(label, jump, const_, put_label);
}
code_ptr ++;
half_count ++;
@@ -426,6 +440,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(!put_label);
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
jump = compiler->jumps;
@@ -434,6 +449,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = jump->next;
}
+ put_label = compiler->put_labels;
+ while (put_label) {
+ modify_imm32_const((sljit_u16 *)put_label->addr, put_label->label->addr);
+ put_label = put_label->next;
+ }
+
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
compiler->executable_size = (code_ptr - code) * sizeof(sljit_u16);
@@ -2311,6 +2332,27 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
return const_;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_put_label *put_label;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
+ PTR_FAIL_IF(!put_label);
+ set_put_label(put_label, compiler, 0);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, 0));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));
+ return put_label;
+}
+
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
sljit_u16 *inst = (sljit_u16*)addr;
diff --git a/src/sljit/sljitNativeMIPS_32.c b/src/sljit/sljitNativeMIPS_32.c
index 094c992..16dec05 100644
--- a/src/sljit/sljitNativeMIPS_32.c
+++ b/src/sljit/sljitNativeMIPS_32.c
@@ -368,16 +368,21 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
SLJIT_ASSERT(!(flags & SRC2_IMM));
if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
-#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
+#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) || (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
-#else
+#else /* !SLJIT_MIPS_R1 && !SLJIT_MIPS_R6 */
FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
return push_inst(compiler, MFLO | D(dst), DR(dst));
-#endif
+#endif /* SLJIT_MIPS_R1 || SLJIT_MIPS_R6 */
}
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+ FAIL_IF(push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)));
+ FAIL_IF(push_inst(compiler, MUH | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+#else /* !SLJIT_MIPS_R6 */
FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
+#endif /* SLJIT_MIPS_R6 */
FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
return push_inst(compiler, SUBU | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
@@ -420,6 +425,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
{
sljit_ins *inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);
inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
@@ -430,6 +436,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
{
sljit_ins *inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
diff --git a/src/sljit/sljitNativeMIPS_64.c b/src/sljit/sljitNativeMIPS_64.c
index f841aef..a6a2bcc 100644
--- a/src/sljit/sljitNativeMIPS_64.c
+++ b/src/sljit/sljitNativeMIPS_64.c
@@ -459,19 +459,26 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
SLJIT_ASSERT(!(flags & SRC2_IMM));
if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
-#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+ return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst));
+#elif (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
if (op & SLJIT_I32_OP)
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
return push_inst(compiler, MFLO | D(dst), DR(dst));
-#else
+#else /* !SLJIT_MIPS_R6 && !SLJIT_MIPS_R1 */
FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
return push_inst(compiler, MFLO | D(dst), DR(dst));
-#endif
+#endif /* SLJIT_MIPS_R6 */
}
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+#else /* !SLJIT_MIPS_R6 */
FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
+#endif /* SLJIT_MIPS_R6 */
FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
diff --git a/src/sljit/sljitNativeMIPS_common.c b/src/sljit/sljitNativeMIPS_common.c
index 894e213..7d1d087 100644
--- a/src/sljit/sljitNativeMIPS_common.c
+++ b/src/sljit/sljitNativeMIPS_common.c
@@ -27,17 +27,31 @@
/* Latest MIPS architecture. */
/* Automatically detect SLJIT_MIPS_R1 */
+#if (defined __mips_isa_rev) && (__mips_isa_rev >= 6)
+#define SLJIT_MIPS_R6 1
+#endif
+
SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
{
-#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ return "MIPS32-R6" SLJIT_CPUINFO;
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ return "MIPS64-R6" SLJIT_CPUINFO;
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
+#elif (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
+
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
return "MIPS32-R1" SLJIT_CPUINFO;
-#else
+#else /* !SLJIT_CONFIG_MIPS_32 */
return "MIPS64-R1" SLJIT_CPUINFO;
-#endif
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
#else /* SLJIT_MIPS_R1 */
return "MIPS III" SLJIT_CPUINFO;
-#endif
+#endif /* SLJIT_MIPS_R6 */
}
/* Length of an instruction word
@@ -62,6 +76,7 @@ typedef sljit_u32 sljit_ins;
#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
+#define TMP_FREG3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3)
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 4, 25, 31
@@ -69,14 +84,14 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
- 0, 0, 14, 2, 4, 6, 8, 12, 10
+static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
+ 0, 0, 14, 2, 4, 6, 8, 12, 10, 16
};
#else
-static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
- 0, 0, 13, 14, 15, 16, 17, 12, 18
+static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
+ 0, 0, 13, 14, 15, 16, 17, 12, 18, 10
};
#endif
@@ -102,6 +117,11 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define FR(dr) (freg_map[dr])
#define HI(opcode) ((opcode) << 26)
#define LO(opcode) (opcode)
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+/* CMP.cond.fmt */
+/* S = (20 << 21) D = (21 << 21) */
+#define CMP_FMT_S (20 << 21)
+#endif /* SLJIT_MIPS_R6 */
/* S = (16 << 21) D = (17 << 21) */
#define FMT_S (16 << 21)
#define FMT_D (17 << 21)
@@ -114,8 +134,13 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define ANDI (HI(12))
#define B (HI(4))
#define BAL (HI(1) | (17 << 16))
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+#define BC1EQZ (HI(17) | (9 << 21) | FT(TMP_FREG3))
+#define BC1NEZ (HI(17) | (13 << 21) | FT(TMP_FREG3))
+#else /* !SLJIT_MIPS_R6 */
#define BC1F (HI(17) | (8 << 21))
#define BC1T (HI(17) | (8 << 21) | (1 << 16))
+#endif /* SLJIT_MIPS_R6 */
#define BEQ (HI(4))
#define BGEZ (HI(1) | (1 << 16))
#define BGTZ (HI(7))
@@ -124,20 +149,42 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define BNE (HI(5))
#define BREAK (HI(0) | LO(13))
#define CFC1 (HI(17) | (2 << 21))
-#define C_UN_S (HI(17) | FMT_S | LO(49))
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+#define C_UEQ_S (HI(17) | CMP_FMT_S | LO(3))
+#define C_ULE_S (HI(17) | CMP_FMT_S | LO(7))
+#define C_ULT_S (HI(17) | CMP_FMT_S | LO(5))
+#define C_UN_S (HI(17) | CMP_FMT_S | LO(1))
+#define C_FD (FD(TMP_FREG3))
+#else /* !SLJIT_MIPS_R6 */
#define C_UEQ_S (HI(17) | FMT_S | LO(51))
#define C_ULE_S (HI(17) | FMT_S | LO(55))
#define C_ULT_S (HI(17) | FMT_S | LO(53))
+#define C_UN_S (HI(17) | FMT_S | LO(49))
+#define C_FD (0)
+#endif /* SLJIT_MIPS_R6 */
#define CVT_S_S (HI(17) | FMT_S | LO(32))
#define DADDIU (HI(25))
#define DADDU (HI(0) | LO(45))
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+#define DDIV (HI(0) | (2 << 6) | LO(30))
+#define DDIVU (HI(0) | (2 << 6) | LO(31))
+#define DMOD (HI(0) | (3 << 6) | LO(30))
+#define DMODU (HI(0) | (3 << 6) | LO(31))
+#define DIV (HI(0) | (2 << 6) | LO(26))
+#define DIVU (HI(0) | (2 << 6) | LO(27))
+#define DMUH (HI(0) | (3 << 6) | LO(28))
+#define DMUHU (HI(0) | (3 << 6) | LO(29))
+#define DMUL (HI(0) | (2 << 6) | LO(28))
+#define DMULU (HI(0) | (2 << 6) | LO(29))
+#else /* !SLJIT_MIPS_R6 */
#define DDIV (HI(0) | LO(30))
#define DDIVU (HI(0) | LO(31))
#define DIV (HI(0) | LO(26))
#define DIVU (HI(0) | LO(27))
-#define DIV_S (HI(17) | FMT_S | LO(3))
#define DMULT (HI(0) | LO(28))
#define DMULTU (HI(0) | LO(29))
+#endif /* SLJIT_MIPS_R6 */
+#define DIV_S (HI(17) | FMT_S | LO(3))
#define DSLL (HI(0) | LO(56))
#define DSLL32 (HI(0) | LO(60))
#define DSLLV (HI(0) | LO(20))
@@ -151,18 +198,34 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define J (HI(2))
#define JAL (HI(3))
#define JALR (HI(0) | LO(9))
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+#define JR (HI(0) | LO(9))
+#else /* !SLJIT_MIPS_R6 */
#define JR (HI(0) | LO(8))
+#endif /* SLJIT_MIPS_R6 */
#define LD (HI(55))
#define LUI (HI(15))
#define LW (HI(35))
#define MFC1 (HI(17))
+#if !(defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
#define MFHI (HI(0) | LO(16))
#define MFLO (HI(0) | LO(18))
+#else /* SLJIT_MIPS_R6 */
+#define MOD (HI(0) | (3 << 6) | LO(26))
+#define MODU (HI(0) | (3 << 6) | LO(27))
+#endif /* !SLJIT_MIPS_R6 */
#define MOV_S (HI(17) | FMT_S | LO(6))
#define MTC1 (HI(17) | (4 << 21))
-#define MUL_S (HI(17) | FMT_S | LO(2))
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+#define MUH (HI(0) | (3 << 6) | LO(24))
+#define MUHU (HI(0) | (3 << 6) | LO(25))
+#define MUL (HI(0) | (2 << 6) | LO(24))
+#define MULU (HI(0) | (2 << 6) | LO(25))
+#else /* !SLJIT_MIPS_R6 */
#define MULT (HI(0) | LO(24))
#define MULTU (HI(0) | LO(25))
+#endif /* SLJIT_MIPS_R6 */
+#define MUL_S (HI(17) | FMT_S | LO(2))
#define NEG_S (HI(17) | FMT_S | LO(7))
#define NOP (HI(0) | LO(0))
#define NOR (HI(0) | LO(39))
@@ -188,14 +251,18 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define XOR (HI(0) | LO(38))
#define XORI (HI(14))
-#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
+#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) || (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
#define CLZ (HI(28) | LO(32))
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+#define DCLZ (LO(18))
+#else /* !SLJIT_MIPS_R6 */
#define DCLZ (HI(28) | LO(36))
#define MOVF (HI(0) | (0 << 16) | LO(1))
#define MOVN (HI(0) | LO(11))
#define MOVT (HI(0) | (1 << 16) | LO(1))
#define MOVZ (HI(0) | LO(10))
#define MUL (HI(28) | LO(2))
+#endif /* SLJIT_MIPS_R6 */
#define PREF (HI(51))
#define PREFX (HI(19) | LO(15))
#define SEB (HI(31) | (16 << 6) | LO(32))
@@ -234,7 +301,13 @@ static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit
static SLJIT_INLINE sljit_ins invert_branch(sljit_s32 flags)
{
- return (flags & IS_BIT26_COND) ? (1 << 26) : (1 << 16);
+ if (flags & IS_BIT26_COND)
+ return (1 << 26);
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+ if (flags & IS_BIT23_COND)
+ return (1 << 23);
+#endif /* SLJIT_MIPS_R6 */
+ return (1 << 16);
}
static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
@@ -376,6 +449,55 @@ static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_
}
#endif
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+
+static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
+{
+ if (max_label < 0x80000000l) {
+ put_label->flags = 0;
+ return 1;
+ }
+
+ if (max_label < 0x800000000000l) {
+ put_label->flags = 1;
+ return 3;
+ }
+
+ put_label->flags = 2;
+ return 5;
+}
+
+static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)
+{
+ sljit_uw addr = put_label->label->addr;
+ sljit_ins *inst = (sljit_ins *)put_label->addr;
+ sljit_s32 reg = *inst;
+
+ if (put_label->flags == 0) {
+ SLJIT_ASSERT(addr < 0x80000000l);
+ inst[0] = LUI | T(reg) | IMM(addr >> 16);
+ }
+ else if (put_label->flags == 1) {
+ SLJIT_ASSERT(addr < 0x800000000000l);
+ inst[0] = LUI | T(reg) | IMM(addr >> 32);
+ inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
+ inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
+ inst += 2;
+ }
+ else {
+ inst[0] = LUI | T(reg) | IMM(addr >> 48);
+ inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff);
+ inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
+ inst[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
+ inst[4] = DSLL | T(reg) | D(reg) | SH_IMM(16);
+ inst += 4;
+ }
+
+ inst[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff);
+}
+
+#endif
+
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
{
struct sljit_memory_fragment *buf;
@@ -384,12 +506,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_ins *buf_ptr;
sljit_ins *buf_end;
sljit_uw word_count;
+ sljit_uw next_addr;
sljit_sw executable_offset;
sljit_uw addr;
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
+ struct sljit_put_label *put_label;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_generate_code(compiler));
@@ -401,39 +525,54 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
word_count = 0;
+ next_addr = 0;
executable_offset = SLJIT_EXEC_OFFSET(code);
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+ put_label = compiler->put_labels;
do {
buf_ptr = (sljit_ins*)buf->memory;
buf_end = buf_ptr + (buf->used_size >> 2);
do {
*code_ptr = *buf_ptr++;
- SLJIT_ASSERT(!label || label->size >= word_count);
- SLJIT_ASSERT(!jump || jump->addr >= word_count);
- SLJIT_ASSERT(!const_ || const_->addr >= word_count);
- /* These structures are ordered by their address. */
- if (label && label->size == word_count) {
- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
- label = label->next;
- }
- if (jump && jump->addr == word_count) {
+ if (next_addr == word_count) {
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+ SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
+
+ /* These structures are ordered by their address. */
+ if (label && label->size == word_count) {
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+ if (jump && jump->addr == word_count) {
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
- jump->addr = (sljit_uw)(code_ptr - 3);
+ jump->addr = (sljit_uw)(code_ptr - 3);
#else
- jump->addr = (sljit_uw)(code_ptr - 7);
+ jump->addr = (sljit_uw)(code_ptr - 7);
#endif
- code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
- jump = jump->next;
- }
- if (const_ && const_->addr == word_count) {
- /* Just recording the address. */
- const_->addr = (sljit_uw)code_ptr;
- const_ = const_->next;
+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
+ jump = jump->next;
+ }
+ if (const_ && const_->addr == word_count) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ }
+ if (put_label && put_label->addr == word_count) {
+ SLJIT_ASSERT(put_label->label);
+ put_label->addr = (sljit_uw)code_ptr;
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
+ word_count += 5;
+#endif
+ put_label = put_label->next;
+ }
+ next_addr = compute_next_addr(label, jump, const_, put_label);
}
code_ptr ++;
word_count ++;
@@ -451,6 +590,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(!put_label);
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
jump = compiler->jumps;
@@ -498,6 +638,21 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = jump->next;
}
+ put_label = compiler->put_labels;
+ while (put_label) {
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ addr = put_label->label->addr;
+ buf_ptr = (sljit_ins *)put_label->addr;
+
+ SLJIT_ASSERT((buf_ptr[0] & 0xffe00000) == LUI && (buf_ptr[1] & 0xfc000000) == ORI);
+ buf_ptr[0] |= (addr >> 16) & 0xffff;
+ buf_ptr[1] |= addr & 0xffff;
+#else
+ put_label_set(put_label);
+#endif
+ put_label = put_label->next;
+ }
+
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
@@ -1075,34 +1230,62 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
return push_inst(compiler, NOP, UNMOVABLE_INS);
case SLJIT_LMUL_UW:
case SLJIT_LMUL_SW:
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
+#else /* !SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULU : MUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MUHU : MUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
+#endif /* SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
+ return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
+#else /* !SLJIT_MIPS_R6 */
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
-#else
+#else /* !SLJIT_CONFIG_MIPS_64 */
FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
-#endif
+#endif /* SLJIT_CONFIG_MIPS_64 */
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
+#endif /* SLJIT_MIPS_R6 */
case SLJIT_DIVMOD_UW:
case SLJIT_DIVMOD_SW:
case SLJIT_DIV_UW:
case SLJIT_DIV_SW:
SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (int_op) {
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
+ }
+ else {
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DMODU : DMOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
+ }
+#else /* !SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
+#endif /* SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
+ return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
+#else /* !SLJIT_MIPS_R6 */
#if !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
-#endif
-
+#endif /* !SLJIT_MIPS_R1 */
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
if (int_op)
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
else
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
-#else
+#else /* !SLJIT_CONFIG_MIPS_64 */
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
-#endif
-
+#endif /* SLJIT_CONFIG_MIPS_64 */
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
+#endif /* SLJIT_MIPS_R6 */
}
return SLJIT_SUCCESS;
@@ -1408,8 +1591,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile
inst = C_UN_S;
break;
}
-
- return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1), UNMOVABLE_INS);
+ return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1) | C_FD, UNMOVABLE_INS);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
@@ -1608,16 +1790,30 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
flags = IS_BIT26_COND; \
delay_check = src;
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+
+#define BR_T() \
+ inst = BC1NEZ; \
+ flags = IS_BIT23_COND; \
+ delay_check = FCSR_FCC;
+#define BR_F() \
+ inst = BC1EQZ; \
+ flags = IS_BIT23_COND; \
+ delay_check = FCSR_FCC;
+
+#else /* !SLJIT_MIPS_R6 */
+
#define BR_T() \
inst = BC1T | JUMP_LENGTH; \
flags = IS_BIT16_COND; \
delay_check = FCSR_FCC;
-
#define BR_F() \
inst = BC1F | JUMP_LENGTH; \
flags = IS_BIT16_COND; \
delay_check = FCSR_FCC;
+#endif /* SLJIT_MIPS_R6 */
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
{
struct sljit_jump *jump;
@@ -1927,7 +2123,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
case SLJIT_GREATER_EQUAL_F64:
case SLJIT_UNORDERED_F64:
case SLJIT_ORDERED_F64:
+#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
+ FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar));
+#else /* !SLJIT_MIPS_R6 */
FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));
+#endif /* SLJIT_MIPS_R6 */
FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar));
FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar));
src_ar = dst_ar;
@@ -2039,7 +2239,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
{
struct sljit_const *const_;
- sljit_s32 reg;
+ sljit_s32 dst_r;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
@@ -2049,11 +2249,38 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
-
- PTR_FAIL_IF(emit_const(compiler, reg, init_value));
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
+
return const_;
}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_put_label *put_label;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
+ PTR_FAIL_IF(!put_label);
+ set_put_label(put_label, compiler, 0);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
+#else
+ PTR_FAIL_IF(push_inst(compiler, dst_r, UNMOVABLE_INS));
+ compiler->size += 5;
+#endif
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
+
+ return put_label;
+}
diff --git a/src/sljit/sljitNativePPC_32.c b/src/sljit/sljitNativePPC_32.c
index fc185f7..3ce7411 100644
--- a/src/sljit/sljitNativePPC_32.c
+++ b/src/sljit/sljitNativePPC_32.c
@@ -259,6 +259,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
{
sljit_ins *inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);
inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
@@ -269,6 +270,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
{
sljit_ins *inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
diff --git a/src/sljit/sljitNativePPC_64.c b/src/sljit/sljitNativePPC_64.c
index 706b2ba..3b73021 100644
--- a/src/sljit/sljitNativePPC_64.c
+++ b/src/sljit/sljitNativePPC_64.c
@@ -35,9 +35,6 @@
#error "Must implement count leading zeroes"
#endif
-#define RLDI(dst, src, sh, mb, type) \
- (HI(30) | S(src) | A(dst) | ((type) << 2) | (((sh) & 0x1f) << 11) | (((sh) & 0x20) >> 4) | (((mb) & 0x1f) << 6) | ((mb) & 0x20))
-
#define PUSH_RLDICR(reg, shift) \
push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1))
diff --git a/src/sljit/sljitNativePPC_common.c b/src/sljit/sljitNativePPC_common.c
index 5ef4ac9..e827514 100644
--- a/src/sljit/sljitNativePPC_common.c
+++ b/src/sljit/sljitNativePPC_common.c
@@ -42,7 +42,7 @@ typedef sljit_u32 sljit_ins;
#include
#endif
-#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
+#if (defined _CALL_ELF && _CALL_ELF == 2)
#define SLJIT_PASS_ENTRY_ADDR_TO_CALL 1
#endif
@@ -231,6 +231,9 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define SIMM_MIN (-0x8000)
#define UIMM_MAX (0xffff)
+#define RLDI(dst, src, sh, mb, type) \
+ (HI(30) | S(src) | A(dst) | ((type) << 2) | (((sh) & 0x1f) << 11) | (((sh) & 0x20) >> 4) | (((mb) & 0x1f) << 6) | ((mb) & 0x20))
+
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func)
{
@@ -324,6 +327,55 @@ keep_address:
return 0;
}
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+
+static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
+{
+ if (max_label < 0x100000000l) {
+ put_label->flags = 0;
+ return 1;
+ }
+
+ if (max_label < 0x1000000000000l) {
+ put_label->flags = 1;
+ return 3;
+ }
+
+ put_label->flags = 2;
+ return 4;
+}
+
+static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)
+{
+ sljit_uw addr = put_label->label->addr;
+ sljit_ins *inst = (sljit_ins *)put_label->addr;
+ sljit_s32 reg = *inst;
+
+ if (put_label->flags == 0) {
+ SLJIT_ASSERT(addr < 0x100000000l);
+ inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 16);
+ }
+ else {
+ if (put_label->flags == 1) {
+ SLJIT_ASSERT(addr < 0x1000000000000l);
+ inst[0] = ORI | S(TMP_ZERO) | A(reg) | IMM(addr >> 32);
+ }
+ else {
+ inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 48);
+ inst[1] = ORI | S(reg) | A(reg) | IMM((addr >> 32) & 0xffff);
+ inst ++;
+ }
+
+ inst[1] = RLDI(reg, reg, 32, 31, 1);
+ inst[2] = ORIS | S(reg) | A(reg) | IMM((addr >> 16) & 0xffff);
+ inst += 2;
+ }
+
+ inst[1] = ORI | S(reg) | A(reg) | IMM(addr & 0xffff);
+}
+
+#endif
+
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
{
struct sljit_memory_fragment *buf;
@@ -332,12 +384,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_ins *buf_ptr;
sljit_ins *buf_end;
sljit_uw word_count;
+ sljit_uw next_addr;
sljit_sw executable_offset;
sljit_uw addr;
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
+ struct sljit_put_label *put_label;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_generate_code(compiler));
@@ -356,71 +410,87 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
word_count = 0;
+ next_addr = 0;
executable_offset = SLJIT_EXEC_OFFSET(code);
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+ put_label = compiler->put_labels;
do {
buf_ptr = (sljit_ins*)buf->memory;
buf_end = buf_ptr + (buf->used_size >> 2);
do {
*code_ptr = *buf_ptr++;
- SLJIT_ASSERT(!label || label->size >= word_count);
- SLJIT_ASSERT(!jump || jump->addr >= word_count);
- SLJIT_ASSERT(!const_ || const_->addr >= word_count);
- /* These structures are ordered by their address. */
- if (label && label->size == word_count) {
- /* Just recording the address. */
- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
- label = label->next;
- }
- if (jump && jump->addr == word_count) {
+ if (next_addr == word_count) {
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+ SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
+
+ /* These structures are ordered by their address. */
+ if (label && label->size == word_count) {
+ /* Just recording the address. */
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+ if (jump && jump->addr == word_count) {
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- jump->addr = (sljit_uw)(code_ptr - 3);
+ jump->addr = (sljit_uw)(code_ptr - 3);
#else
- jump->addr = (sljit_uw)(code_ptr - 6);
+ jump->addr = (sljit_uw)(code_ptr - 6);
#endif
- if (detect_jump_type(jump, code_ptr, code, executable_offset)) {
+ if (detect_jump_type(jump, code_ptr, code, executable_offset)) {
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- code_ptr[-3] = code_ptr[0];
- code_ptr -= 3;
-#else
- if (jump->flags & PATCH_ABS32) {
+ code_ptr[-3] = code_ptr[0];
code_ptr -= 3;
- code_ptr[-1] = code_ptr[2];
- code_ptr[0] = code_ptr[3];
- }
- else if (jump->flags & PATCH_ABS48) {
- code_ptr--;
- code_ptr[-1] = code_ptr[0];
- code_ptr[0] = code_ptr[1];
- /* rldicr rX,rX,32,31 -> rX,rX,16,47 */
- SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6);
- code_ptr[-3] ^= 0x8422;
- /* oris -> ori */
- code_ptr[-2] ^= 0x4000000;
- }
- else {
- code_ptr[-6] = code_ptr[0];
- code_ptr -= 6;
- }
+#else
+ if (jump->flags & PATCH_ABS32) {
+ code_ptr -= 3;
+ code_ptr[-1] = code_ptr[2];
+ code_ptr[0] = code_ptr[3];
+ }
+ else if (jump->flags & PATCH_ABS48) {
+ code_ptr--;
+ code_ptr[-1] = code_ptr[0];
+ code_ptr[0] = code_ptr[1];
+ /* rldicr rX,rX,32,31 -> rX,rX,16,47 */
+ SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6);
+ code_ptr[-3] ^= 0x8422;
+ /* oris -> ori */
+ code_ptr[-2] ^= 0x4000000;
+ }
+ else {
+ code_ptr[-6] = code_ptr[0];
+ code_ptr -= 6;
+ }
#endif
- if (jump->flags & REMOVE_COND) {
- code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);
- code_ptr++;
- jump->addr += sizeof(sljit_ins);
- code_ptr[0] = Bx;
- jump->flags -= IS_COND;
+ if (jump->flags & REMOVE_COND) {
+ code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);
+ code_ptr++;
+ jump->addr += sizeof(sljit_ins);
+ code_ptr[0] = Bx;
+ jump->flags -= IS_COND;
+ }
}
+ jump = jump->next;
}
- jump = jump->next;
- }
- if (const_ && const_->addr == word_count) {
- const_->addr = (sljit_uw)code_ptr;
- const_ = const_->next;
+ if (const_ && const_->addr == word_count) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ }
+ if (put_label && put_label->addr == word_count) {
+ SLJIT_ASSERT(put_label->label);
+ put_label->addr = (sljit_uw)code_ptr;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
+ word_count += 4;
+#endif
+ put_label = put_label->next;
+ }
+ next_addr = compute_next_addr(label, jump, const_, put_label);
}
code_ptr ++;
word_count ++;
@@ -438,6 +508,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(!put_label);
+
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins)));
#else
@@ -503,6 +575,21 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = jump->next;
}
+ put_label = compiler->put_labels;
+ while (put_label) {
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ addr = put_label->label->addr;
+ buf_ptr = (sljit_ins *)put_label->addr;
+
+ SLJIT_ASSERT((buf_ptr[0] & 0xfc1f0000) == ADDIS && (buf_ptr[1] & 0xfc000000) == ORI);
+ buf_ptr[0] |= (addr >> 16) & 0xffff;
+ buf_ptr[1] |= addr & 0xffff;
+#else
+ put_label_set(put_label);
+#endif
+ put_label = put_label->next;
+ }
+
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
@@ -2261,7 +2348,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
{
struct sljit_const *const_;
- sljit_s32 reg;
+ sljit_s32 dst_r;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
@@ -2271,11 +2358,38 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
-
- PTR_FAIL_IF(emit_const(compiler, reg, init_value));
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
+
return const_;
}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_put_label *put_label;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
+ PTR_FAIL_IF(!put_label);
+ set_put_label(put_label, compiler, 0);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
+#else
+ PTR_FAIL_IF(push_inst(compiler, dst_r));
+ compiler->size += 4;
+#endif
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
+
+ return put_label;
+}
diff --git a/src/sljit/sljitNativeSPARC_32.c b/src/sljit/sljitNativeSPARC_32.c
index 0671b13..8079fad 100644
--- a/src/sljit/sljitNativeSPARC_32.c
+++ b/src/sljit/sljitNativeSPARC_32.c
@@ -267,6 +267,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
{
sljit_ins *inst = (sljit_ins *)addr;
+ SLJIT_ASSERT(((inst[0] & 0xc1c00000) == 0x01000000) && ((inst[1] & 0xc1f82000) == 0x80102000));
inst[0] = (inst[0] & 0xffc00000) | ((new_target >> 10) & 0x3fffff);
inst[1] = (inst[1] & 0xfffffc00) | (new_target & 0x3ff);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
@@ -277,6 +278,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
{
sljit_ins *inst = (sljit_ins *)addr;
+ SLJIT_ASSERT(((inst[0] & 0xc1c00000) == 0x01000000) && ((inst[1] & 0xc1f82000) == 0x80102000));
inst[0] = (inst[0] & 0xffc00000) | ((new_constant >> 10) & 0x3fffff);
inst[1] = (inst[1] & 0xfffffc00) | (new_constant & 0x3ff);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
diff --git a/src/sljit/sljitNativeSPARC_common.c b/src/sljit/sljitNativeSPARC_common.c
index 669ecd8..bfa4ece 100644
--- a/src/sljit/sljitNativeSPARC_common.c
+++ b/src/sljit/sljitNativeSPARC_common.c
@@ -298,12 +298,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_ins *buf_ptr;
sljit_ins *buf_end;
sljit_uw word_count;
+ sljit_uw next_addr;
sljit_sw executable_offset;
sljit_uw addr;
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
+ struct sljit_put_label *put_label;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_generate_code(compiler));
@@ -315,40 +317,52 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
word_count = 0;
+ next_addr = 0;
executable_offset = SLJIT_EXEC_OFFSET(code);
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+ put_label = compiler->put_labels;
do {
buf_ptr = (sljit_ins*)buf->memory;
buf_end = buf_ptr + (buf->used_size >> 2);
do {
*code_ptr = *buf_ptr++;
- SLJIT_ASSERT(!label || label->size >= word_count);
- SLJIT_ASSERT(!jump || jump->addr >= word_count);
- SLJIT_ASSERT(!const_ || const_->addr >= word_count);
- /* These structures are ordered by their address. */
- if (label && label->size == word_count) {
- /* Just recording the address. */
- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
- label = label->next;
- }
- if (jump && jump->addr == word_count) {
+ if (next_addr == word_count) {
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+ SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
+
+ /* These structures are ordered by their address. */
+ if (label && label->size == word_count) {
+ /* Just recording the address. */
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+ if (jump && jump->addr == word_count) {
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
- jump->addr = (sljit_uw)(code_ptr - 3);
+ jump->addr = (sljit_uw)(code_ptr - 3);
#else
- jump->addr = (sljit_uw)(code_ptr - 6);
+ jump->addr = (sljit_uw)(code_ptr - 6);
#endif
- code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
- jump = jump->next;
- }
- if (const_ && const_->addr == word_count) {
- /* Just recording the address. */
- const_->addr = (sljit_uw)code_ptr;
- const_ = const_->next;
+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
+ jump = jump->next;
+ }
+ if (const_ && const_->addr == word_count) {
+ /* Just recording the address. */
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ }
+ if (put_label && put_label->addr == word_count) {
+ SLJIT_ASSERT(put_label->label);
+ put_label->addr = (sljit_uw)code_ptr;
+ put_label = put_label->next;
+ }
+ next_addr = compute_next_addr(label, jump, const_, put_label);
}
code_ptr ++;
word_count ++;
@@ -366,6 +380,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(!put_label);
SLJIT_ASSERT(code_ptr - code <= (sljit_s32)compiler->size);
jump = compiler->jumps;
@@ -389,8 +404,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
/* Set the fields of immediate loads. */
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
- buf_ptr[0] = (buf_ptr[0] & 0xffc00000) | ((addr >> 10) & 0x3fffff);
- buf_ptr[1] = (buf_ptr[1] & 0xfffffc00) | (addr & 0x3ff);
+ SLJIT_ASSERT(((buf_ptr[0] & 0xc1cfffff) == 0x01000000) && ((buf_ptr[1] & 0xc1f83fff) == 0x80102000));
+ buf_ptr[0] |= (addr >> 10) & 0x3fffff;
+ buf_ptr[1] |= addr & 0x3ff;
#else
#error "Implementation required"
#endif
@@ -398,6 +414,20 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = jump->next;
}
+ put_label = compiler->put_labels;
+ while (put_label) {
+ addr = put_label->label->addr;
+ buf_ptr = (sljit_ins *)put_label->addr;
+
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+ SLJIT_ASSERT(((buf_ptr[0] & 0xc1cfffff) == 0x01000000) && ((buf_ptr[1] & 0xc1f83fff) == 0x80102000));
+ buf_ptr[0] |= (addr >> 10) & 0x3fffff;
+ buf_ptr[1] |= addr & 0x3ff;
+#else
+#error "Implementation required"
+#endif
+ put_label = put_label->next;
+ }
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
@@ -1465,8 +1495,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
{
- sljit_s32 reg;
struct sljit_const *const_;
+ sljit_s32 dst_r;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
@@ -1476,11 +1506,31 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
-
- PTR_FAIL_IF(emit_const(compiler, reg, init_value));
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
return const_;
}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_put_label *put_label;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
+ PTR_FAIL_IF(!put_label);
+ set_put_label(put_label, compiler, 0);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
+ return put_label;
+}
diff --git a/src/sljit/sljitNativeX86_32.c b/src/sljit/sljitNativeX86_32.c
index 074e64b..34a3a3d 100644
--- a/src/sljit/sljitNativeX86_32.c
+++ b/src/sljit/sljitNativeX86_32.c
@@ -38,8 +38,10 @@ static sljit_s32 emit_do_imm(struct sljit_compiler *compiler, sljit_u8 opcode, s
return SLJIT_SUCCESS;
}
-static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type, sljit_sw executable_offset)
+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset)
{
+ sljit_s32 type = jump->flags >> TYPE_SHIFT;
+
if (type == SLJIT_JUMP) {
*code_ptr++ = JMP_i32;
jump->addr++;
diff --git a/src/sljit/sljitNativeX86_64.c b/src/sljit/sljitNativeX86_64.c
index 8506565..5758711 100644
--- a/src/sljit/sljitNativeX86_64.c
+++ b/src/sljit/sljitNativeX86_64.c
@@ -39,8 +39,10 @@ static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg,
return SLJIT_SUCCESS;
}
-static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type)
+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr)
{
+ sljit_s32 type = jump->flags >> TYPE_SHIFT;
+
int short_addr = !(jump->flags & SLJIT_REWRITABLE_JUMP) && !(jump->flags & JUMP_LABEL) && (jump->u.target <= 0xffffffff);
/* The relative jump below specialized for this case. */
@@ -72,6 +74,56 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_
return code_ptr;
}
+static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, sljit_u8 *code_ptr, sljit_uw max_label)
+{
+ if (max_label > HALFWORD_MAX) {
+ put_label->addr -= put_label->flags;
+ put_label->flags = PATCH_MD;
+ return code_ptr;
+ }
+
+ if (put_label->flags == 0) {
+ /* Destination is register. */
+ code_ptr = (sljit_u8*)put_label->addr - 2 - sizeof(sljit_uw);
+
+ SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);
+ SLJIT_ASSERT((code_ptr[1] & 0xf8) == MOV_r_i32);
+
+ if ((code_ptr[0] & 0x07) != 0) {
+ code_ptr[0] = (sljit_u8)(code_ptr[0] & ~0x08);
+ code_ptr += 2 + sizeof(sljit_s32);
+ }
+ else {
+ code_ptr[0] = code_ptr[1];
+ code_ptr += 1 + sizeof(sljit_s32);
+ }
+
+ put_label->addr = (sljit_uw)code_ptr;
+ return code_ptr;
+ }
+
+ code_ptr -= put_label->flags + (2 + sizeof(sljit_uw));
+ SLJIT_MEMMOVE(code_ptr, code_ptr + (2 + sizeof(sljit_uw)), put_label->flags);
+
+ SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);
+
+ if ((code_ptr[1] & 0xf8) == MOV_r_i32) {
+ code_ptr += 2 + sizeof(sljit_uw);
+ SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);
+ }
+
+ SLJIT_ASSERT(code_ptr[1] == MOV_rm_r);
+
+ code_ptr[0] = (sljit_u8)(code_ptr[0] & ~0x4);
+ code_ptr[1] = MOV_rm_i32;
+ code_ptr[2] = (sljit_u8)(code_ptr[2] & ~(0x7 << 3));
+
+ code_ptr = (sljit_u8*)(put_label->addr - (2 + sizeof(sljit_uw)) + sizeof(sljit_s32));
+ put_label->addr = (sljit_uw)code_ptr;
+ put_label->flags = 0;
+ return code_ptr;
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
diff --git a/src/sljit/sljitNativeX86_common.c b/src/sljit/sljitNativeX86_common.c
index 6f02ee3..6296da5 100644
--- a/src/sljit/sljitNativeX86_common.c
+++ b/src/sljit/sljitNativeX86_common.c
@@ -428,13 +428,15 @@ static sljit_u8 get_jump_code(sljit_s32 type)
}
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type, sljit_sw executable_offset);
+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset);
#else
-static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type);
+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr);
+static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, sljit_u8 *code_ptr, sljit_uw max_label);
#endif
-static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_s32 type, sljit_sw executable_offset)
+static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset)
{
+ sljit_s32 type = jump->flags >> TYPE_SHIFT;
sljit_s32 short_jump;
sljit_uw label_addr;
@@ -447,7 +449,7 @@ static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if ((sljit_sw)(label_addr - (jump->addr + 1)) > HALFWORD_MAX || (sljit_sw)(label_addr - (jump->addr + 1)) < HALFWORD_MIN)
- return generate_far_jump_code(jump, code_ptr, type);
+ return generate_far_jump_code(jump, code_ptr);
#endif
if (type == SLJIT_JUMP) {
@@ -497,6 +499,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
+ struct sljit_put_label *put_label;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_generate_code(compiler));
@@ -511,6 +514,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+ put_label = compiler->put_labels;
executable_offset = SLJIT_EXEC_OFFSET(code);
do {
@@ -525,27 +529,38 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
buf_ptr += len;
}
else {
- if (*buf_ptr >= 2) {
+ switch (*buf_ptr) {
+ case 0:
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = code_ptr - code;
+ label = label->next;
+ break;
+ case 1:
jump->addr = (sljit_uw)code_ptr;
if (!(jump->flags & SLJIT_REWRITABLE_JUMP))
- code_ptr = generate_near_jump_code(jump, code_ptr, code, *buf_ptr - 2, executable_offset);
+ code_ptr = generate_near_jump_code(jump, code_ptr, code, executable_offset);
else {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 2, executable_offset);
+ code_ptr = generate_far_jump_code(jump, code_ptr, executable_offset);
#else
- code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 2);
+ code_ptr = generate_far_jump_code(jump, code_ptr);
#endif
}
jump = jump->next;
- }
- else if (*buf_ptr == 0) {
- label->addr = ((sljit_uw)code_ptr) + executable_offset;
- label->size = code_ptr - code;
- label = label->next;
- }
- else { /* *buf_ptr is 1 */
+ break;
+ case 2:
const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_sw);
const_ = const_->next;
+ break;
+ default:
+ SLJIT_ASSERT(*buf_ptr == 3);
+ SLJIT_ASSERT(put_label->label);
+ put_label->addr = (sljit_uw)code_ptr;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ code_ptr = generate_put_label_code(put_label, code_ptr, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
+#endif
+ put_label = put_label->next;
+ break;
}
buf_ptr++;
}
@@ -557,6 +572,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(!put_label);
+ SLJIT_ASSERT(code_ptr <= code + compiler->size);
jump = compiler->jumps;
while (jump) {
@@ -591,8 +608,24 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = jump->next;
}
- /* Some space may be wasted because of short jumps. */
- SLJIT_ASSERT(code_ptr <= code + compiler->size);
+ put_label = compiler->put_labels;
+ while (put_label) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ sljit_unaligned_store_sw((void*)(put_label->addr - sizeof(sljit_sw)), (sljit_sw)put_label->label->addr);
+#else
+ if (put_label->flags & PATCH_MD) {
+ SLJIT_ASSERT(put_label->label->addr > HALFWORD_MAX);
+ sljit_unaligned_store_sw((void*)(put_label->addr - sizeof(sljit_sw)), (sljit_sw)put_label->label->addr);
+ }
+ else {
+ SLJIT_ASSERT(put_label->label->addr <= HALFWORD_MAX);
+ sljit_unaligned_store_s32((void*)(put_label->addr - sizeof(sljit_s32)), (sljit_s32)put_label->label->addr);
+ }
+#endif
+
+ put_label = put_label->next;
+ }
+
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
compiler->executable_size = code_ptr - code;
@@ -2481,7 +2514,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF_NULL(jump);
- set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ set_jump(jump, compiler, (type & SLJIT_REWRITABLE_JUMP) | ((type & 0xff) << TYPE_SHIFT));
type &= 0xff;
/* Worst case size. */
@@ -2495,7 +2528,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
PTR_FAIL_IF_NULL(inst);
*inst++ = 0;
- *inst++ = type + 2;
+ *inst++ = 1;
return jump;
}
@@ -2513,7 +2546,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
if (src == SLJIT_IMM) {
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
FAIL_IF_NULL(jump);
- set_jump(jump, compiler, JUMP_ADDR);
+ set_jump(jump, compiler, JUMP_ADDR | (type << TYPE_SHIFT));
jump->u.target = srcw;
/* Worst case size. */
@@ -2527,7 +2560,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
FAIL_IF_NULL(inst);
*inst++ = 0;
- *inst++ = type + 2;
+ *inst++ = 1;
}
else {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
@@ -2831,7 +2864,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!inst);
*inst++ = 0;
- *inst++ = 1;
+ *inst++ = 2;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (dst & SLJIT_MEM)
@@ -2842,6 +2875,54 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
return const_;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_put_label *put_label;
+ sljit_u8 *inst;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ sljit_s32 reg;
+ sljit_uw start_size;
+#endif
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ CHECK_EXTRA_REGS(dst, dstw, (void)0);
+
+ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
+ PTR_FAIL_IF(!put_label);
+ set_put_label(put_label, compiler, 0);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 0;
+ reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if (emit_load_imm64(compiler, reg, 0))
+ return NULL;
+#else
+ if (emit_mov(compiler, dst, dstw, SLJIT_IMM, 0))
+ return NULL;
+#endif
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (dst & SLJIT_MEM) {
+ start_size = compiler->size;
+ if (emit_mov(compiler, dst, dstw, TMP_REG1, 0))
+ return NULL;
+ put_label->flags = compiler->size - start_size;
+ }
+#endif
+
+ inst = (sljit_u8*)ensure_buf(compiler, 2);
+ PTR_FAIL_IF(!inst);
+
+ *inst++ = 0;
+ *inst++ = 3;
+
+ return put_label;
+}
+
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
SLJIT_UNUSED_ARG(executable_offset);
diff --git a/src/sljit/sljitUtils.c b/src/sljit/sljitUtils.c
index 5c2a838..857492a 100644
--- a/src/sljit/sljitUtils.c
+++ b/src/sljit/sljitUtils.c
@@ -154,7 +154,13 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void)
#include "windows.h"
#else
/* Provides mmap function. */
+#include
#include
+#ifndef MAP_ANON
+#ifdef MAP_ANONYMOUS
+#define MAP_ANON MAP_ANONYMOUS
+#endif
+#endif
/* For detecting the page size. */
#include
diff --git a/test-driver b/test-driver
index 0218a01..b8521a4 100755
--- a/test-driver
+++ b/test-driver
@@ -1,9 +1,9 @@
#! /bin/sh
# test-driver - basic testsuite driver script.
-scriptversion=2016-01-11.22; # UTC
+scriptversion=2018-03-07.03; # UTC
-# Copyright (C) 2011-2017 Free Software Foundation, Inc.
+# Copyright (C) 2011-2018 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@ scriptversion=2016-01-11.22; # UTC
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
+# along with this program. If not, see .
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -140,7 +140,7 @@ echo ":copy-in-global-log: $gcopy" >> $trs_file
# Local Variables:
# mode: shell-script
# sh-indentation: 2
-# eval: (add-hook 'write-file-hooks 'time-stamp)
+# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
diff --git a/testdata/grepoutput b/testdata/grepoutput
index 2bd69be..a9297e1 100644
--- a/testdata/grepoutput
+++ b/testdata/grepoutput
@@ -949,3 +949,10 @@ RC=0
---------------------------- Test 126 -----------------------------
ABC XYZ
RC=0
+---------------------------- Test 127 -----------------------------
+pattern
+RC=0
+---------------------------- Test 128 -----------------------------
+pcre2grep: Requested group 1 cannot be captured.
+pcre2grep: Use --om-capture to increase the size of the capture vector.
+RC=2
diff --git a/testdata/grepoutput8 b/testdata/grepoutput8
index aaed6ae..1bac20b 100644
--- a/testdata/grepoutput8
+++ b/testdata/grepoutput8
@@ -18,3 +18,14 @@ RC=0
22:6,2
22:8,2
RC=0
+---------------------------- Test U4 ------------------------------
+pcre2grep: pcre2_match() gave error -22 while matching this text:
+
+AáCDâZ
+
+UTF-8 error: isolated byte with 0x80 bit set at offset 4
+
+RC=1
+---------------------------- Test U5 ------------------------------
+CDâZ
+RC=0
diff --git a/testdata/grepoutputCN b/testdata/grepoutputCN
new file mode 100644
index 0000000..5217b5a
--- /dev/null
+++ b/testdata/grepoutputCN
@@ -0,0 +1,30 @@
+The quick brown
+This time it jumps and jumps and jumps.
+This line contains \E and (regex) *meta* [characters].
+The word is cat in this line
+The caterpillar sat on the mat
+The snowcat is not an animal
+The quick brown
+This time it jumps and jumps and jumps.
+This line contains \E and (regex) *meta* [characters].
+The word is cat in this line
+The caterpillar sat on the mat
+The snowcat is not an animal
+0:T
+The quick brown
+0:T
+This time it jumps and jumps and jumps.
+0:T
+This line contains \E and (regex) *meta* [characters].
+0:T
+The word is cat in this line
+0:T
+The caterpillar sat on the mat
+0:T
+The snowcat is not an animal
+T
+T
+T
+T
+T
+T
diff --git a/testdata/testinput1 b/testdata/testinput1
index d8615ee..f5159d6 100644
--- a/testdata/testinput1
+++ b/testdata/testinput1
@@ -1,6 +1,6 @@
# This set of tests is for features that are compatible with all versions of
# Perl >= 5.10, in non-UTF mode. It should run clean for the 8-bit, 16-bit, and
-# 32-bit PCRE libraries, and also using the perltest.pl script.
+# 32-bit PCRE libraries, and also using the perltest.sh script.
#forbid_utf
#newline_default lf any anycrlf
@@ -6263,4 +6263,127 @@ ef) x/x,mark
aBCDEF
AbCDe f
+/(*pla:foo).{6}/
+ abcfoobarxyz
+\= Expect no match
+ abcfooba
+
+/(*positive_lookahead:foo).{6}/
+ abcfoobarxyz
+
+/(?(*pla:foo).{6}|a..)/
+ foobarbaz
+ abcfoobar
+
+/(?(*positive_lookahead:foo).{6}|a..)/
+ foobarbaz
+ abcfoobar
+
+/(*plb:foo)bar/
+ abcfoobar
+\= Expect no match
+ abcbarfoo
+
+/(*positive_lookbehind:foo)bar/
+ abcfoobar
+\= Expect no match
+ abcbarfoo
+
+/(?(*plb:foo)bar|baz)/
+ abcfoobar
+ bazfoobar
+ abcbazfoobar
+ foobazfoobar
+
+/(?(*positive_lookbehind:foo)bar|baz)/
+ abcfoobar
+ bazfoobar
+ abcbazfoobar
+ foobazfoobar
+
+/(*nlb:foo)bar/
+ abcbarfoo
+\= Expect no match
+ abcfoobar
+
+/(*negative_lookbehind:foo)bar/
+ abcbarfoo
+\= Expect no match
+ abcfoobar
+
+/(?(*nlb:foo)bar|baz)/
+ abcfoobaz
+ abcbarbaz
+\= Expect no match
+ abcfoobar
+
+/(?(*negative_lookbehind:foo)bar|baz)/
+ abcfoobaz
+ abcbarbaz
+\= Expect no match
+ abcfoobar
+
+/(*atomic:a+)\w/
+ aaab
+\= Expect no match
+ aaaa
+
+/ (? \w+ )* \. /xi
+ pokus.
+
+/(?(DEFINE) (? \w+ ) ) (?&word)* \./xi
+ pokus.
+
+/(?(DEFINE) (? \w+ ) ) ( (?&word)* ) \./xi
+ pokus.
+
+/(?&word)* (?(DEFINE) (? \w+ ) ) \./xi
+ pokus.
+
+/(?&word)* \. (? \w+ )/xi
+ pokus.hokus
+
+/a(?(?=(*:2)b).)/mark
+ abc
+ acb
+
+/a(?(?!(*:2)b).)/mark
+ acb
+ abc
+
+/(?:a|ab){1}+c/
+\= Expect no match
+ abc
+
+/(a|ab){1}+c/
+ abc
+
+/(a+){1}+a/
+\= Expect no match
+ aaaa
+
+/(?(DEFINE)(a|ab))(?1){1}+c/
+ abc
+
+/(?:a|(?=b)|.)*\z/
+ abc
+
+/(?:a|(?=b)|.)*/
+ abc
+
+/(?<=a(*SKIP)x)|c/
+ abcd
+
+/(?<=a(*SKIP)x)|d/
+ abcd
+
+/(?<=(?=.(?<=x)))/aftertext
+ abx
+
+/(?<=(?=(?<=a)))b/
+ ab
+
+/^(?a)(?()b)((?<=b).*)$/
+ abc
+
# End of testinput1
diff --git a/testdata/testinput10 b/testdata/testinput10
index 93d2560..3813709 100644
--- a/testdata/testinput10
+++ b/testdata/testinput10
@@ -1,7 +1,7 @@
# This set of tests is for UTF-8 support and Unicode property support, with
# relevance only for the 8-bit library.
-# The next 4 patterns have UTF-8 errors
+# The next 5 patterns have UTF-8 errors
/[Ã]/utf
@@ -11,6 +11,8 @@
/ÃÃ/utf
+/ÃÃ/match_invalid_utf
+
# Now test subjects
/badutf/utf
@@ -475,5 +477,112 @@
\x{100}
\= Expect no match
aaa
+
+# Offsets are different in 8-bit mode.
+
+/(?<=abc)(|def)/g,utf,replace=<$0>,substitute_callout
+ 123abcáyzabcdef789abcá´qr
+
+# Check name length with non-ASCII characters
+
+/(?'ABáC678901234567890123456789012'...)/utf
+
+/(?'ABáC6789012345678901234567890123'...)/utf
+
+/(?'ABZC6789012345678901234567890123'...)/utf
+
+/(?(n/utf
+
+/(?(á/utf
+
+# Invalid UTF-8 tests
+
+/.../g,match_invalid_utf
+ abcd\x80wxzy\x80pqrs
+ abcd\x{80}wxzy\x80pqrs
+
+/abc/match_invalid_utf
+ ab\x80ab\=ph
+\= Expect no match
+ ab\x80cdef\=ph
+
+/ab$/match_invalid_utf
+ ab\x80cdeab
+\= Expect no match
+ ab\x80cde
+
+/.../g,match_invalid_utf
+ abcd\x{80}wxzy\x80pqrs
+
+/(?<=x)../g,match_invalid_utf
+ abcd\x{80}wxzy\x80pqrs
+ abcd\x{80}wxzy\x80xpqrs
+
+/X$/match_invalid_utf
+\= Expect no match
+ X\xc4
+
+/(?<=..)X/match_invalid_utf,aftertext
+ AB\x80AQXYZ
+ AB\x80AQXYZ\=offset=5
+ AB\x80\x80AXYZXC\=offset=5
+\= Expect no match
+ AB\x80XYZ
+ AB\x80XYZ\=offset=3
+ AB\xfeXYZ
+ AB\xffXYZ\=offset=3
+ AB\x80AXYZ
+ AB\x80AXYZ\=offset=4
+ AB\x80\x80AXYZ\=offset=5
+
+/.../match_invalid_utf
+ AB\xc4CCC
+\= Expect no match
+ A\x{d800}B
+ A\x{110000}B
+ A\xc4B
+
+/\bX/match_invalid_utf
+ A\x80X
+
+/\BX/match_invalid_utf
+\= Expect no match
+ A\x80X
+
+/(?<=...)X/match_invalid_utf
+ AAA\x80BBBXYZ
+\= Expect no match
+ AAA\x80BXYZ
+ AAA\x80BBXYZ
+
+# -------------------------------------
+
+/(*UTF)(?=\x{123})/I
+
+/[\x{c1}\x{e1}]X[\x{145}\x{146}]/I,utf
+
+/[ó¿¾,]/BI,utf
+
+/[\x{fff4}-\x{ffff8}]/I,utf
+
+/[\x{fff4}-\x{afff8}\x{10ffff}]/I,utf
+
+/[\xff\x{ffff}]/I,utf
+
+/[\xff\x{ff}]/I,utf
+
+/[\xff\x{ff}]/I
+
+/[Ss]/I
+
+/[Ss]/I,utf
+
+/(?:\x{ff}|\x{3000})/I,utf
+
+/x/utf
+ abxyz
+ \x80\=startchar
+ abc\x80\=startchar
+ abc\x80\=startchar,offset=3
# End of testinput10
diff --git a/testdata/testinput12 b/testdata/testinput12
index b0ab909..bed00a5 100644
--- a/testdata/testinput12
+++ b/testdata/testinput12
@@ -381,5 +381,86 @@
\x{100}
\= Expect no match
aaa
+
+# Offsets are different in 8-bit mode.
+
+/(?<=abc)(|def)/g,utf,replace=<$0>,substitute_callout
+ 123abcáyzabcdef789abcá´qr
+
+# A few script run tests in non-UTF mode (but they need Unicode support)
+
+/^(*script_run:.{4})/
+ \x{3041}\x{30a1}\x{3007}\x{3007} Hiragana Katakana Han Han
+ \x{30a1}\x{3041}\x{3007}\x{3007} Katakana Hiragana Han Han
+ \x{1100}\x{2e80}\x{2e80}\x{1101} Hangul Han Han Hangul
+
+/^(*sr:.*)/utf,allow_surrogate_escapes
+ \x{2e80}\x{3105}\x{2e80}\x{30a1} Han Bopomofo Han Katakana
+ \x{d800}\x{dfff} Surrogates (Unknown) \=no_utf_check
+
+/(?(n/utf
+
+/(?(á/utf
+
+# Invalid UTF-16/32 tests.
+
+/.../g,match_invalid_utf
+ abcd\x{df00}wxzy\x{df00}pqrs
+ abcd\x{80}wxzy\x{df00}pqrs
+
+/abc/match_invalid_utf
+ ab\x{df00}ab\=ph
+\= Expect no match
+ ab\x{df00}cdef\=ph
+
+/ab$/match_invalid_utf
+ ab\x{df00}cdeab
+\= Expect no match
+ ab\x{df00}cde
+
+/.../g,match_invalid_utf
+ abcd\x{80}wxzy\x{df00}pqrs
+
+/(?<=x)../g,match_invalid_utf
+ abcd\x{80}wxzy\x{df00}pqrs
+ abcd\x{80}wxzy\x{df00}xpqrs
+
+/X$/match_invalid_utf
+\= Expect no match
+ X\x{df00}
+
+/(?<=..)X/match_invalid_utf,aftertext
+ AB\x{df00}AQXYZ
+ AB\x{df00}AQXYZ\=offset=5
+ AB\x{df00}\x{df00}AXYZXC\=offset=5
+\= Expect no match
+ AB\x{df00}XYZ
+ AB\x{df00}XYZ\=offset=3
+ AB\x{df00}AXYZ
+ AB\x{df00}AXYZ\=offset=4
+ AB\x{df00}\x{df00}AXYZ\=offset=5
+
+/.../match_invalid_utf
+\= Expect no match
+ A\x{d800}B
+ A\x{110000}B
+
+# ----------------------------------------------------
+
+/(*UTF)(?=\x{123})/I
+
+/[\x{c1}\x{e1}]X[\x{145}\x{146}]/I,utf
+
+/[\xff\x{ffff}]/I,utf
+
+/[\xff\x{ff}]/I,utf
+
+/[\xff\x{ff}]/I
+
+/[Ss]/I
+
+/[Ss]/I,utf
+
+/(?:\x{ff}|\x{3000})/I,utf
# End of testinput12
diff --git a/testdata/testinput15 b/testdata/testinput15
index 2ef6672..5dd6897 100644
--- a/testdata/testinput15
+++ b/testdata/testinput15
@@ -16,14 +16,14 @@
/^(?>a)++/
aa\=find_limits
aaaaaaaaa\=find_limits
-
+
/(a)(?1)++/
aa\=find_limits
aaaaaaaaa\=find_limits
/a(?:.)*?a/ims
abbbbbbbbbbbbbbbbbbbbba\=find_limits
-
+
/a(?:.(*THEN))*?a/ims
abbbbbbbbbbbbbbbbbbbbba\=find_limits
@@ -86,9 +86,9 @@
aaaaaaaaaaaaaz
\= Expect limit exceeded
aaaaaaaaaaaaaz\=depth_limit=10
-
-# These three have infinitely nested recursions.
-
+
+# These three have infinitely nested recursions.
+
/((?2))((?1))/
abc
@@ -97,21 +97,21 @@
/(?(R)a*(?1)|((?R))b)/
aaaabcde
-
+
# The allusedtext modifier does not work with JIT, which does not maintain
# the leftchar/rightchar data.
/abc(?=xyz)/allusedtext
abcxyzpqr
abcxyzpqr\=aftertext
-
+
/(?<=pqr)abc(?=xyz)/allusedtext
xyzpqrabcxyzpqr
xyzpqrabcxyzpqr\=aftertext
-
+
/a\b/
a.\=allusedtext
- a\=allusedtext
+ a\=allusedtext
/abc\Kxyz/
abcxyz\=allusedtext
@@ -121,7 +121,57 @@
/abc(?=abcde)(?=ab)/allusedtext
abcabcdefg
-
+
+#subject allusedtext
+
+/(?<=abc)123/
+ xyzabc123pqr
+ xyzabc12\=ps
+ xyzabc12\=ph
+
+/\babc\b/
+ +++abc+++
+ +++ab\=ps
+ +++ab\=ph
+
+/(?<=abc)def/
+ abc\=ph
+
+/(?<=123)(*MARK:xx)abc/mark
+ xxxx123a\=ph
+ xxxx123a\=ps
+
+/(?<=(?<=a)b)c.*/I
+ abc\=ph
+\= Expect no match
+ xbc\=ph
+
+/(?<=ab)c.*/I
+ abc\=ph
+\= Expect no match
+ xbc\=ph
+
+/abc(?<=bc)def/
+ xxxabcd\=ph
+
+/(?<=ab)cdef/
+ xxabcd\=ph
+
+/(?<=(?<=(?<=a)b)c)./I
+ 123abcXYZ
+
+/(?<=ab(cd(?<=...)))./I
+ abcdX
+
+/(?<=ab((?<=...)cd))./I
+ ZabcdX
+
+/(?<=((?<=(?<=ab).))(?1)(?1))./I
+ abxZ
+
+#subject
+# -------------------------------------------------------------------
+
# These tests provoke recursion loops, which give a different error message
# when JIT is used.
@@ -130,26 +180,26 @@
/(a|(?R))/I
abcd
- defg
+ defg
/(ab|(bc|(de|(?R))))/I
abcd
- fghi
+ fghi
/(ab|(bc|(de|(?1))))/I
abcd
- fghi
+ fghi
/x(ab|(bc|(de|(?1)x)x)x)/I
xab123
- xfghi
+ xfghi
/(?!\w)(?R)/
abcd
- =abc
+ =abc
/(?=\w)(?R)/
- =abc
+ =abc
abcd
/(?
+ abcdefabcpqr\=ovector=4
+ abxyz\=ovector=4
+ abcdefxyz\=ovector=4
+
+/a(b)c|xyz/allvector
+ abcdef\=ovector=4
+ abxyz\=ovector=4
+
+/a(b)c|xyz/g,replace=<$0>,substitute_callout
+ abcdefabcpqr
+ abxyzpqrabcxyz
+ 12abc34xyz99abc55\=substitute_stop=2
+ 12abc34xyz99abc55\=substitute_skip=1
+ 12abc34xyz99abc55\=substitute_skip=2
+
+/a(b)c|xyz/g,replace=<$0>
+ abcdefabcpqr
+ abxyzpqrabcxyz
+ 12abc34xyz\=substitute_stop=2
+ 12abc34xyz\=substitute_skip=1
+
+/a(b)c|xyz/replace=<$0>
+ abcdefabcpqr
+ 12abc34xyz\=substitute_skip=1
+ 12abc34xyz\=substitute_stop=1
+
+/abc\rdef/
+ abc\ndef
+
+/abc\rdef\x{0d}xyz/escaped_cr_is_lf
+ abc\ndef\rxyz
+\= Expect no match
+ abc\ndef\nxyz
+
+/(?(*ACCEPT)xxx)/
+
+/(?(*atomic:xx)xxx)/
+
+/(?(*script_run:xxx)zzz)/
+
+/foobar/
+ the foobar thing\=copy_matched_subject
+ the foobar thing\=copy_matched_subject,zero_terminate
+
+/foobar/g
+ the foobar thing foobar again\=copy_matched_subject
+
+/(*:XX)^abc/I
+
+/(*COMMIT:XX)^abc/I
+
+/(*ACCEPT:XX)^abc/I
+
+/abc/replace=xyz
+ abc\=null_context
+
+/abc/replace=xyz,substitute_callout
+ abc
+\= Expect error message
+ abc\=null_context
+
+/\[()]{65535}()/expand
+
+/\[()]{65535}(?)/expand
+
+/a(?:(*ACCEPT))??bc/
+ abc
+ axy
+
+/a(*ACCEPT)??bc/
+ abc
+ axy
+
+/a(*ACCEPT:XX)??bc/mark
+ abc
+ axy
+
+/(*:\)?/
+
+/(*:\Q \E){5}/alt_verbnames
+
+/(?=abc)/I
+
+/(?|(X)|(XY))\1abc/I
+
+/(?|(a)|(bcde))(c)\2/I
+
+/(?|(a)|(bcde))(c)\1/I
+
+/(?|(?'A'a)|(?'A'bcde))(?'B'c)\k'B'(?'A')/I,dupnames
+
+/(?|(?'A'a)|(?'A'bcde))(?'B'c)\k'A'(?'A')/I,dupnames
+
+/((a|)+)+Z/I
+
+/((?=a))[abcd]/I
+
+/A(?:(*ACCEPT))?B/info
+
+/(A(*ACCEPT)??B)C/
+ ABC
+ AXY
+
+/(?<=(?<=a)b)c.*/I
+ abc\=ph
+\= Expect no match
+ xbc\=ph
+
+/(?<=ab)c.*/I
+ abc\=ph
+\= Expect no match
+ xbc\=ph
+
+/(?<=a(?<=a|a)c)/I
+
+/(?<=a(?<=a|ba)c)/I
+
+/(?<=(?<=a)b)(?.*?\b\1\b){3}/
+ word1 word3 word1 word2 word3 word2 word2 word1 word3 word4
+
+/\A(*napla:.*\b(\w++))(?>.*?\b\1\b){3}/
+ word1 word3 word1 word2 word3 word2 word2 word1 word3 word4
+
+/(*plb:(.)..|(.)...)(\1|\2)/
+ abcdb\=offset=4
+ abcda\=offset=4
+
+/(*naplb:(.)..|(.)...)(\1|\2)/
+ abcdb\=offset=4
+ abcda\=offset=4
+
+/(*non_atomic_positive_lookahead:ab)/B
+
+/(*non_atomic_positive_lookbehind:ab)/B
+
+/(*pla:ab+)/B
+
+/(*napla:ab+)/B
+
+/(*napla:)+/
+
+/(*naplb:)+/
+
+/(*napla:^x|^y)/I
+
+/(*napla:abc|abd)/I
+
+/(*napla:a|(.)(*ACCEPT)zz)\1../
+ abcd
+
+/(*napla:a(*ACCEPT)zz|(.))\1../
+ abcd
+
+/(*napla:a|(*COMMIT)(.))\1\1/
+ aabc
+\= Expect no match
+ abbc
+
+/(*napla:a|(.))\1\1/
+ aabc
+ abbc
+
+# ----
+
+# Expect error (recursion => not fixed length)
+/(\2)((?=(?<=\1)))/
+
+/c*+(?<=[bc])/
+ abc\=ph
+ ab\=ph
+ abc\=ps
+ ab\=ps
+
+/c++(?<=[bc])/
+ abc\=ph
+ ab\=ph
+
+/(?<=(?=.(?<=x)))/
+ abx
+ ab\=ph
+ bxyz
+ xyz
+
+/\z/
+ abc\=ph
+ abc\=ps
+
+/\Z/
+ abc\=ph
+ abc\=ps
+ abc\n\=ph
+ abc\n\=ps
+
+/(?![ab]).*/
+ ab\=ph
+
+/c*+/
+ ab\=ph,offset=2
+
+/\A\s*(a|(?:[^`]{28500}){4})/I
+ a
+
+/\A\s*((?:[^`]{28500}){4})/I
+
+/\A\s*((?:[^`]{28500}){4}|a)/I
+ a
+
+/(?a)(?()b)((?<=b).*)/B
+
+/(?(1)b)((?<=b).*)/B
+
+/(?(R1)b)((?<=b).*)/B
+
+/(?(DEFINE)b)((?<=b).*)/B
+
+/(?(VERSION=10.4)b)((?<=b).*)/B
+
+/[aA]b[cC]/IB
+
+/[cc]abcd/I
+
+/[Cc]abcd/I
+
+/[c]abcd/I
+
+/(?:c|C)abcd/I
+
+/(a)?a/I
+ manm
+
# End of testinput2
diff --git a/testdata/testinput4 b/testdata/testinput4
index a27b6af..0871835 100644
--- a/testdata/testinput4
+++ b/testdata/testinput4
@@ -2317,5 +2317,178 @@
/[^\x{100}-\x{ffff}]*[\x80-\xff]/i,utf
\x{99}\x{99}\x{99}
+
+# Script run tests
+
+/^(*script_run:.{4})/utf
+ abcd Latin x4
+ \x{2e80}\x{2fa1d}\x{3041}\x{30a1} Han Han Hiragana Katakana
+ \x{3041}\x{30a1}\x{3007}\x{3007} Hiragana Katakana Han Han
+ \x{30a1}\x{3041}\x{3007}\x{3007} Katakana Hiragana Han Han
+ \x{1100}\x{2e80}\x{2e80}\x{1101} Hangul Han Han Hangul
+ \x{2e80}\x{3105}\x{2e80}\x{3105} Han Bopomofo Han Bopomofo
+ \x{02ea}\x{2e80}\x{2e80}\x{3105} Bopomofo-Sk Han Han Bopomofo
+ \x{3105}\x{2e80}\x{2e80}\x{3105} Bopomofo Han Han Bopomofo
+ \x{0300}cd! Inherited Latin Latin Common
+ \x{0391}12\x{03a9} Greek Common-digits Greek
+ \x{0400}12\x{fe2f} Cyrillic Common-digits Cyrillic
+ \x{0531}12\x{fb17} Armenian Common-digits Armenian
+ \x{0591}12\x{fb4f} Hebrew Common-digits Hebrew
+ \x{0600}12\x{1eef1} Arabic Common-digits Arabic
+ \x{0600}\x{0660}\x{0669}\x{1eef1} Arabic Arabic-digits Arabic
+ \x{0700}12\x{086a} Syriac Common-digits Syriac
+ \x{1200}12\x{ab2e} Ethiopic Common-digits Ethiopic
+ \x{1680}12\x{169c} Ogham Common-digits Ogham
+ \x{3041}12\x{3041} Hiragana Common-digits Hiragana
+ \x{0980}\x{09e6}\x{09e7}\x{0993} Bengali Bengali-digits Bengali
+ !cde Common Latin Latin Latin
+ A..B Latin Common Common Latin
+ 0abc Ascii-digit Latin Latin Latin
+ 1\x{0700}\x{0700}\x{0700} Ascii-digit Syriac x 3
+ \x{1A80}\x{1A80}\x{1a40}\x{1a41} Tai Tham Hora digits, letters
+\= Expect no match
+ a\x{370}bcd Latin Greek Latin Latin
+ \x{1100}\x{02ea}\x{02ea}\x{02ea} Hangul Bopomofo x3
+ \x{02ea}\x{02ea}\x{02ea}\x{1100} Bopomofo x3 Hangul
+ \x{1100}\x{2e80}\x{3041}\x{1101} Hangul Han Hiragana Hangul
+ \x{0391}\x{09e6}\x{09e7}\x{03a9} Greek Bengali digits Greek
+ \x{0600}7\x{0669}\x{1eef1} Arabic ascii-digit Arabic-digit Arabic
+ \x{0600}\x{0669}7\x{1eef1} Arabic Arabic-digit ascii-digit Arabic
+ A5\x{ff19}B Latin Common-ascii/notascii-digits Latin
+ \x{0300}cd\x{0391} Inherited Latin Latin Greek
+ !cd\x{0391} Common Latin Latin Greek
+ \x{1A80}\x{1A90}\x{1a40}\x{1a41} Tai Tham Hora digit, Tham digit, letters
+ A\x{1d7ce}\x{1d7ff}B Common fancy-common-2-sets-digits Common
+ \x{2e80}\x{3105}\x{2e80}\x{30a1} Han Bopomofo Han Katakana
+
+/^(*sr:.{4}|..)/utf
+ \x{2e80}\x{3105}\x{2e80}\x{30a1} Han Bopomofo Han Katakana
+
+/^(*atomic_script_run:.{4}|..)/utf
+\= Expect no match
+ \x{2e80}\x{3105}\x{2e80}\x{30a1} Han Bopomofo Han Katakana
+
+/^(*asr:.*)/utf
+\= Expect no match
+ \x{2e80}\x{3105}\x{2e80}\x{30a1} Han Bopomofo Han Katakana
+
+/^(?>(*sr:.*))/utf
+ \x{2e80}\x{3105}\x{2e80}\x{30a1} Han Bopomofo Han Katakana
+
+/^(*sr:.*)/utf
+ \x{2e80}\x{3105}\x{2e80}\x{30a1} Han Bopomofo Han Katakana
+ \x{10fffd}\x{10fffd}\x{10fffd} Private use (Unknown)
+
+/^(*sr:\x{2e80}*)/utf
+ \x{2e80}\x{2e80}\x{3105} Han Han Bopomofo
+
+/^(*sr:\x{2e80}*)\x{2e80}/utf
+ \x{2e80}\x{2e80}\x{3105} Han Han Bopomofo
+
+/^(*sr:.*)Test/utf
+ Test script run on an empty string
+
+/^(*sr:(.{2})){2}/utf
+ \x{0600}7\x{0669}\x{1eef1} Arabic ascii-digit Arabic-digit Arabic
+ \x{1A80}\x{1A80}\x{1a40}\x{1a41} Tai Tham Hora digits, letters
+ \x{1A80}\x{1a40}\x{1A90}\x{1a41} Tai Tham Hora digit, letter, Tham digit, letter
+\= Expect no match
+ \x{1100}\x{2e80}\x{3041}\x{1101} Hangul Han Hiragana Hangul
+
+/^(*sr:\S*)/utf
+ \x{1cf4}\x{20f0}\x{900}\x{11305} [Dev,Gran,Kan] [Dev,Gran,Lat] Dev Gran
+ \x{1cf4}\x{20f0}\x{11305}\x{900} [Dev,Gran,Kan] [Dev,Gran,Lat] Gran Dev
+ \x{1cf4}\x{20f0}\x{900}ABC [Dev,Gran,Kan] [Dev,Gran,Lat] Dev Lat
+ \x{1cf4}\x{20f0}ABC [Dev,Gran,Kan] [Dev,Gran,Lat] Lat
+ \x{20f0}ABC [Dev,Gran,Lat] Lat
+ XYZ\x{20f0}ABC Lat [Dev,Gran,Lat] Lat
+ \x{a36}\x{a33}\x{900} [Dev,...] [Dev,...] Dev
+ \x{3001}\x{2e80}\x{3041}\x{30a1} [Bopo, Han, etc] Han Hira Kata
+ \x{3001}\x{30a1}\x{2e80}\x{3041} [Bopo, Han, etc] Kata Han Hira
+ \x{3001}\x{3105}\x{2e80}\x{1101} [Bopo, Han, etc] Bopomofo Han Hangul
+ \x{3105}\x{3001}\x{2e80}\x{1101} Bopomofo [Bopo, Han, etc] Han Hangul
+ \x{3031}\x{3041}\x{30a1}\x{2e80} [Hira Kata] Hira Kata Han
+ \x{060c}\x{06d4}\x{0600}\x{10d00}\x{0700} [Arab Rohg Syrc Thaa] [Arab Rohg] Arab Rohg Syrc
+ \x{060c}\x{06d4}\x{0700}\x{0600}\x{10d00} [Arab Rohg Syrc Thaa] [Arab Rohg] Syrc Arab Rohg
+ \x{2e80}\x{3041}\x{3001}\x{3031}\x{2e80} Han Hira [Bopo, Han, etc] [Hira Kata] Han
+
+/(?=0)^B0W)/
+ B0W-W0W
+\= Expect no match
+ 0
+
+/(?(VERSION>=1000)^B0W|W0W)/
+ B0W-W0W
+\= Expect no match
+ 0
+
+/(?<=pqr)abc(?=xyz)/
+ 123pqrabcxy\=ps,allusedtext
+ 123pqrabcxyz\=ps,allusedtext
+
+/(?>a+b)/
+ aaaa\=ps
+ aaaab\=ps
+
+/(abc)(?1)/
+ abca\=ps
+ abcabc\=ps
+
+/(?(?=abc).*|Z)/
+ ab\=ps
+ abcxyz\=ps
+
+/(abc)++x/
+ abcab\=ps
+ abc\=ps
+ ab\=ps
+ abcx
+
+/\z/
+ abc\=ph
+ abc\=ps
+
+/\Z/
+ abc\=ph
+ abc\=ps
+ abc\n\=ph
+ abc\n\=ps
+
+/c*+(?<=[bc])/
+ abc\=ph
+ ab\=ph
+ abc\=ps
+ ab\=ps
+
+/c++(?<=[bc])/
+ abc\=ph
+ ab\=ph
+
+/(?<=(?=.(?<=x)))/
+ abx
+ ab\=ph
+ bxyz
+ xyz
+
+/(?![ab]).*/
+ ab\=ph
+
+/c*+/
+ ab\=ph,offset=2
+
# End of testinput6
diff --git a/testdata/testinput8 b/testdata/testinput8
index 2627454..550631d 100644
--- a/testdata/testinput8
+++ b/testdata/testinput8
@@ -182,4 +182,8 @@
/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))/-fullbincode
+#pattern -fullbincode
+
+/\[()]{65535}/expand
+
# End of testinput8
diff --git a/testdata/testoutput1 b/testdata/testoutput1
index 77b9ff0..ad2175b 100644
--- a/testdata/testoutput1
+++ b/testdata/testoutput1
@@ -1,6 +1,6 @@
# This set of tests is for features that are compatible with all versions of
# Perl >= 5.10, in non-UTF mode. It should run clean for the 8-bit, 16-bit, and
-# 32-bit PCRE libraries, and also using the perltest.pl script.
+# 32-bit PCRE libraries, and also using the perltest.sh script.
#forbid_utf
#newline_default lf any anycrlf
@@ -9929,4 +9929,187 @@ No match
AbCDe f
No match
+/(*pla:foo).{6}/
+ abcfoobarxyz
+ 0: foobar
+\= Expect no match
+ abcfooba
+No match
+
+/(*positive_lookahead:foo).{6}/
+ abcfoobarxyz
+ 0: foobar
+
+/(?(*pla:foo).{6}|a..)/
+ foobarbaz
+ 0: foobar
+ abcfoobar
+ 0: abc
+
+/(?(*positive_lookahead:foo).{6}|a..)/
+ foobarbaz
+ 0: foobar
+ abcfoobar
+ 0: abc
+
+/(*plb:foo)bar/
+ abcfoobar
+ 0: bar
+\= Expect no match
+ abcbarfoo
+No match
+
+/(*positive_lookbehind:foo)bar/
+ abcfoobar
+ 0: bar
+\= Expect no match
+ abcbarfoo
+No match
+
+/(?(*plb:foo)bar|baz)/
+ abcfoobar
+ 0: bar
+ bazfoobar
+ 0: baz
+ abcbazfoobar
+ 0: baz
+ foobazfoobar
+ 0: bar
+
+/(?(*positive_lookbehind:foo)bar|baz)/
+ abcfoobar
+ 0: bar
+ bazfoobar
+ 0: baz
+ abcbazfoobar
+ 0: baz
+ foobazfoobar
+ 0: bar
+
+/(*nlb:foo)bar/
+ abcbarfoo
+ 0: bar
+\= Expect no match
+ abcfoobar
+No match
+
+/(*negative_lookbehind:foo)bar/
+ abcbarfoo
+ 0: bar
+\= Expect no match
+ abcfoobar
+No match
+
+/(?(*nlb:foo)bar|baz)/
+ abcfoobaz
+ 0: baz
+ abcbarbaz
+ 0: bar
+\= Expect no match
+ abcfoobar
+No match
+
+/(?(*negative_lookbehind:foo)bar|baz)/
+ abcfoobaz
+ 0: baz
+ abcbarbaz
+ 0: bar
+\= Expect no match
+ abcfoobar
+No match
+
+/(*atomic:a+)\w/
+ aaab
+ 0: aaab
+\= Expect no match
+ aaaa
+No match
+
+/ (? \w+ )* \. /xi
+ pokus.
+ 0: pokus.
+ 1: pokus
+
+/(?(DEFINE) (? \w+ ) ) (?&word)* \./xi
+ pokus.
+ 0: pokus.
+
+/(?(DEFINE) (? \w+ ) ) ( (?&word)* ) \./xi
+ pokus.
+ 0: pokus.
+ 1:
+ 2: pokus
+
+/(?&word)* (?(DEFINE) (? \w+ ) ) \./xi
+ pokus.
+ 0: pokus.
+
+/(?&word)* \. (? \w+ )/xi
+ pokus.hokus
+ 0: pokus.hokus
+ 1: hokus
+
+/a(?(?=(*:2)b).)/mark
+ abc
+ 0: ab
+MK: 2
+ acb
+ 0: a
+
+/a(?(?!(*:2)b).)/mark
+ acb
+ 0: ac
+ abc
+ 0: a
+MK: 2
+
+/(?:a|ab){1}+c/
+\= Expect no match
+ abc
+No match
+
+/(a|ab){1}+c/
+ abc
+No match
+
+/(a+){1}+a/
+\= Expect no match
+ aaaa
+No match
+
+/(?(DEFINE)(a|ab))(?1){1}+c/
+ abc
+No match
+
+/(?:a|(?=b)|.)*\z/
+ abc
+ 0: abc
+
+/(?:a|(?=b)|.)*/
+ abc
+ 0: a
+
+/(?<=a(*SKIP)x)|c/
+ abcd
+No match
+
+/(?<=a(*SKIP)x)|d/
+ abcd
+ 0: d
+
+/(?<=(?=.(?<=x)))/aftertext
+ abx
+ 0:
+ 0+ x
+
+/(?<=(?=(?<=a)))b/
+ ab
+ 0: b
+
+/^(?a)(?()b)((?<=b).*)$/
+ abc
+ 0: abc
+ 1: a
+ 2: c
+
# End of testinput1
diff --git a/testdata/testoutput10 b/testdata/testoutput10
index 9660fc5..775c2ab 100644
--- a/testdata/testoutput10
+++ b/testdata/testoutput10
@@ -1,7 +1,7 @@
# This set of tests is for UTF-8 support and Unicode property support, with
# relevance only for the 8-bit library.
-# The next 4 patterns have UTF-8 errors
+# The next 5 patterns have UTF-8 errors
/[Ã]/utf
Failed: error -8 at offset 1: UTF-8 error: byte 2 top bits not 0x80
@@ -15,6 +15,9 @@ Failed: error -8 at offset 0: UTF-8 error: byte 2 top bits not 0x80
/ÃÃ/utf
Failed: error -22 at offset 2: UTF-8 error: isolated byte with 0x80 bit set
+/ÃÃ/match_invalid_utf
+Failed: error -22 at offset 2: UTF-8 error: isolated byte with 0x80 bit set
+
# Now test subjects
/badutf/utf
@@ -248,7 +251,7 @@ No match
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc4
Last code unit = \x80
@@ -261,7 +264,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xe1
Last code unit = \x80
@@ -274,7 +277,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xf0
Last code unit = \x80
@@ -287,7 +290,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xf4
Last code unit = \x80
@@ -300,7 +303,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xf4
Last code unit = \xbf
@@ -313,7 +316,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc3
Last code unit = \xbf
@@ -326,7 +329,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc4
Last code unit = \x80
@@ -339,7 +342,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc2
Last code unit = \x80
@@ -352,7 +355,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc3
Last code unit = \xbf
@@ -365,7 +368,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xed
Last code unit = \xb4
@@ -380,7 +383,7 @@ Subject length lower bound = 3
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xe6
Last code unit = \x9e
@@ -395,7 +398,7 @@ Subject length lower bound = 3
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc2
Last code unit = \x80
@@ -408,7 +411,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc2
Last code unit = \x84
@@ -421,7 +424,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc4
Last code unit = \x84
@@ -434,7 +437,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xe0
Last code unit = \xa1
@@ -447,7 +450,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xf0
Last code unit = \xab
@@ -460,7 +463,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
\x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19
@@ -495,7 +498,7 @@ No match
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc4
Last code unit = \x80
@@ -514,7 +517,7 @@ Subject length lower bound = 3
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
Starting code units: x \xc4
Subject length lower bound = 1
@@ -531,7 +534,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
Starting code units: a x \xc4
Subject length lower bound = 1
@@ -548,7 +551,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
Starting code units: a x \xc4
Subject length lower bound = 1
@@ -566,7 +569,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
Starting code units: x \xc4
Subject length lower bound = 1
@@ -578,7 +581,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc4
Last code unit = \x80
@@ -592,7 +595,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = 'a'
Last code unit = \x80
@@ -606,7 +609,7 @@ Subject length lower bound = 2
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = 'a'
Last code unit = \x81
@@ -619,7 +622,7 @@ Subject length lower bound = 3
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Subject length lower bound = 1
/[\x{100}]/IB,utf
@@ -629,7 +632,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc4
Last code unit = \x80
@@ -648,7 +651,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc3
Last code unit = \xbf
@@ -663,7 +666,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Subject length lower bound = 1
@@ -678,14 +681,14 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
First code unit = \xc4
Last code unit = 'z'
Subject length lower bound = 7
/\777/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc7
Last code unit = \xbf
@@ -703,7 +706,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc4
Last code unit = \x80
@@ -717,7 +720,7 @@ Subject length lower bound = 2
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc4
Last code unit = 'X'
@@ -761,7 +764,7 @@ No match
0: \x{1234}
/(*CRLF)(*UTF)(*BSR_UNICODE)a\Rb/I
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: utf
\R matches any Unicode newline
@@ -771,7 +774,7 @@ Last code unit = 'b'
Subject length lower bound = 3
/\h/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x09 \x20 \xc2 \xe1 \xe2 \xe3
Subject length lower bound = 1
@@ -795,7 +798,7 @@ Subject length lower bound = 1
0: \x{3000}
/\v/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x0a \x0b \x0c \x0d \xc2 \xe2
Subject length lower bound = 1
@@ -813,7 +816,7 @@ Subject length lower bound = 1
0: \x{2028}
/\h*A/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x09 \x20 A \xc2 \xe1 \xe2 \xe3
Last code unit = 'A'
@@ -822,21 +825,21 @@ Subject length lower bound = 1
0: A
/\v+A/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x0a \x0b \x0c \x0d \xc2 \xe2
Last code unit = 'A'
Subject length lower bound = 2
/\s?xxx\s/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x09 \x0a \x0b \x0c \x0d \x20 x
Last code unit = 'x'
Subject length lower bound = 4
/\sxxx\s/I,utf,tables=2
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x09 \x0a \x0b \x0c \x0d \x20 \xc2
Last code unit = 'x'
@@ -847,7 +850,7 @@ Subject length lower bound = 5
0: \x{a0}xxx\x{85}
/\S \S/I,utf,tables=2
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0e \x0f
\x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e
@@ -883,25 +886,25 @@ Error -36 (bad UTF-8 offset)
No match
/\x{1234}+/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: \xe1
Subject length lower bound = 1
/\x{1234}+?/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: \xe1
Subject length lower bound = 1
/\x{1234}++/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: \xe1
Subject length lower bound = 1
/\x{1234}{2}/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: \xe1
Subject length lower bound = 2
@@ -913,7 +916,7 @@ Subject length lower bound = 2
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Subject length lower bound = 1
@@ -925,14 +928,14 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = 'X'
Last code unit = \x80
Subject length lower bound = 2
/\R/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x0a \x0b \x0c \x0d \xc2 \xe2
Subject length lower bound = 1
@@ -944,7 +947,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xc7
Last code unit = \xbf
@@ -1105,7 +1108,7 @@ Failed: error 174 at offset 0: using UTF is disabled by the application
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = 'A' (caseless)
Subject length lower bound = 5
@@ -1117,7 +1120,7 @@ Subject length lower bound = 5
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = 'A'
Last code unit = \xb0
@@ -1130,7 +1133,7 @@ Subject length lower bound = 5
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = 'A'
Last code unit = \xb0
@@ -1143,14 +1146,14 @@ Subject length lower bound = 3
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = 'A' (caseless)
Last code unit = 'B' (caseless)
Subject length lower bound = 3
/\x{401}\x{420}\x{421}\x{422}\x{423}\x{424}\x{425}\x{426}\x{427}\x{428}\x{429}\x{42a}\x{42b}\x{42c}\x{42d}\x{42e}\x{42f}/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: \xd0 \xd1
Subject length lower bound = 17
@@ -1176,17 +1179,17 @@ Subject length lower bound = 17
------------------------------------------------------------------
/\h/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x09 \x20 \xa0
Subject length lower bound = 1
/\v/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x0a \x0b \x0c \x0d \x85
Subject length lower bound = 1
/\R/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x0a \x0b \x0c \x0d \x85
Subject length lower bound = 1
@@ -1199,7 +1202,7 @@ Subject length lower bound = 1
------------------------------------------------------------------
/\x{212a}+/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: K k \xe2
Subject length lower bound = 1
@@ -1207,7 +1210,7 @@ Subject length lower bound = 1
0: KKkk\x{212a}
/s+/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: S s \xc5
Subject length lower bound = 1
@@ -1222,7 +1225,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: A \xc4
Last code unit = 'A'
@@ -1239,7 +1242,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: 0 1 2 3 4 5 6 7 8 9 \xc4
Subject length lower bound = 1
@@ -1251,13 +1254,9 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
-Starting code units: Z \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd
- \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc
- \xdd \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb
- \xec \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa
- \xfb \xfc \xfd \xfe \xff
+Starting code units: Z \xc4
Subject length lower bound = 1
Z\x{100}
0: Z
@@ -1273,13 +1272,9 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
-Starting code units: z { | } ~ \x7f \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9
- \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8
- \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7
- \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6
- \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff
+Starting code units: z { | } ~ \x7f \xc2 \xc3 \xc4
Subject length lower bound = 1
/[z\Qa-d]Ä\E]/IB,utf
@@ -1289,13 +1284,9 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
-Starting code units: - ] a d z \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc
- \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb
- \xdc \xdd \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea
- \xeb \xec \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9
- \xfa \xfb \xfc \xfd \xfe \xff
+Starting code units: - ] a d z \xc4
Subject length lower bound = 1
\x{100}
0: \x{100}
@@ -1314,13 +1305,9 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
-Starting code units: a b \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd
- \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc
- \xdd \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb
- \xec \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa
- \xfb \xfc \xfd \xfe \xff
+Starting code units: a b \xc4
Last code unit = 'z'
Subject length lower bound = 7
@@ -1332,7 +1319,7 @@ Subject length lower bound = 7
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x09 \x0a \x0b \x0c \x0d \x20 \xc4
Subject length lower bound = 1
@@ -1345,7 +1332,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: 0 1 2 3 4 5 6 7 8 9 \xc4
Subject length lower bound = 1
@@ -1358,7 +1345,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P
Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z
@@ -1373,7 +1360,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
\x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19
@@ -1395,7 +1382,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0e \x0f
\x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e
@@ -1416,7 +1403,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
\x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19
@@ -1435,13 +1422,9 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
-Starting code units: \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce
- \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd
- \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec
- \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb
- \xfc \xfd \xfe \xff
+Starting code units: \xc4
Subject length lower bound = 1
\x{104}
0: \x{104}
@@ -1462,13 +1445,9 @@ No match
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
-Starting code units: Z z { | } ~ \x7f \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8
- \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7
- \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6
- \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5
- \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff
+Starting code units: Z z { | } ~ \x7f \xc2 \xc3 \xc4 \xc5 \xce \xe1 \xe2
Subject length lower bound = 1
Z
0: Z
@@ -1503,13 +1482,9 @@ No match
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
-Starting code units: Z z { | } ~ \x7f \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8
- \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7
- \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6
- \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5
- \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff
+Starting code units: Z z { | } ~ \x7f \xc2 \xc3 \xc4 \xc5 \xce \xe1 \xe2
Subject length lower bound = 1
/\x{3a3}B/IBi,utf
@@ -1520,7 +1495,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: \xce \xcf
Last code unit = 'B' (caseless)
@@ -1531,7 +1506,7 @@ Subject length lower bound = 2
Failed: error -3: UTF-8 error: 1 byte missing at end
/(?<=(a)(?-1))x/I,utf
-Capturing subpattern count = 1
+Capture group count = 1
Max lookbehind = 2
Options: utf
First code unit = 'x'
@@ -1579,7 +1554,7 @@ Failed: error 176 at offset 259: name is too long in (*MARK), (*PRUNE), (*SKIP),
# but subjects containing them must not be UTF-checked.
/\x{d800}/I,utf,allow_surrogate_escapes
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Extra options: allow_surrogate_escapes
First code unit = \xed
@@ -1602,7 +1577,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options: utf
Overall options: anchored utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
@@ -1625,5 +1600,217 @@ Subject length lower bound = 1
\= Expect no match
aaa
No match
+
+# Offsets are different in 8-bit mode.
+
+/(?<=abc)(|def)/g,utf,replace=<$0>,substitute_callout
+ 123abcáyzabcdef789abcá´qr
+ 1(2) Old 6 6 "" New 6 8 "<>"
+ 2(2) Old 13 13 "" New 15 17 "<>"
+ 3(2) Old 13 16 "def" New 17 22 ""
+ 4(2) Old 22 22 "" New 28 30 "<>"
+ 4: 123abc<>\x{e1}yzabc<>789abc<>\x{1234}qr
+
+# Check name length with non-ASCII characters
+
+/(?'ABáC678901234567890123456789012'...)/utf
+
+/(?'ABáC6789012345678901234567890123'...)/utf
+Failed: error 148 at offset 36: subpattern name is too long (maximum 32 code units)
+
+/(?'ABZC6789012345678901234567890123'...)/utf
+
+/(?(n/utf
+Failed: error 142 at offset 4: syntax error in subpattern name (missing terminator?)
+
+/(?(á/utf
+Failed: error 142 at offset 5: syntax error in subpattern name (missing terminator?)
+
+# Invalid UTF-8 tests
+
+/.../g,match_invalid_utf
+ abcd\x80wxzy\x80pqrs
+ 0: abc
+ 0: wxz
+ 0: pqr
+ abcd\x{80}wxzy\x80pqrs
+ 0: abc
+ 0: d\x{80}w
+ 0: xzy
+ 0: pqr
+
+/abc/match_invalid_utf
+ ab\x80ab\=ph
+Partial match: ab
+\= Expect no match
+ ab\x80cdef\=ph
+No match
+
+/ab$/match_invalid_utf
+ ab\x80cdeab
+ 0: ab
+\= Expect no match
+ ab\x80cde
+No match
+
+/.../g,match_invalid_utf
+ abcd\x{80}wxzy\x80pqrs
+ 0: abc
+ 0: d\x{80}w
+ 0: xzy
+ 0: pqr
+
+/(?<=x)../g,match_invalid_utf
+ abcd\x{80}wxzy\x80pqrs
+ 0: zy
+ abcd\x{80}wxzy\x80xpqrs
+ 0: zy
+ 0: pq
+
+/X$/match_invalid_utf
+\= Expect no match
+ X\xc4
+No match
+
+/(?<=..)X/match_invalid_utf,aftertext
+ AB\x80AQXYZ
+ 0: X
+ 0+ YZ
+ AB\x80AQXYZ\=offset=5
+ 0: X
+ 0+ YZ
+ AB\x80\x80AXYZXC\=offset=5
+ 0: X
+ 0+ C
+\= Expect no match
+ AB\x80XYZ
+No match
+ AB\x80XYZ\=offset=3
+No match
+ AB\xfeXYZ
+No match
+ AB\xffXYZ\=offset=3
+No match
+ AB\x80AXYZ
+No match
+ AB\x80AXYZ\=offset=4
+No match
+ AB\x80\x80AXYZ\=offset=5
+No match
+
+/.../match_invalid_utf
+ AB\xc4CCC
+ 0: CCC
+\= Expect no match
+ A\x{d800}B
+No match
+ A\x{110000}B
+No match
+ A\xc4B
+No match
+
+/\bX/match_invalid_utf
+ A\x80X
+ 0: X
+
+/\BX/match_invalid_utf
+\= Expect no match
+ A\x80X
+No match
+
+/(?<=...)X/match_invalid_utf
+ AAA\x80BBBXYZ
+ 0: X
+\= Expect no match
+ AAA\x80BXYZ
+No match
+ AAA\x80BBXYZ
+No match
+
+# -------------------------------------
+
+/(*UTF)(?=\x{123})/I
+Capture group count = 0
+May match empty string
+Compile options:
+Overall options: utf
+First code unit = \xc4
+Last code unit = \xa3
+Subject length lower bound = 1
+
+/[\x{c1}\x{e1}]X[\x{145}\x{146}]/I,utf
+Capture group count = 0
+Options: utf
+Starting code units: \xc3
+Last code unit = 'X'
+Subject length lower bound = 3
+
+/[ó¿¾,]/BI,utf
+------------------------------------------------------------------
+ Bra
+ [,\x{fff9f}]
+ Ket
+ End
+------------------------------------------------------------------
+Capture group count = 0
+Options: utf
+Starting code units: , \xf3
+Subject length lower bound = 1
+
+/[\x{fff4}-\x{ffff8}]/I,utf
+Capture group count = 0
+Options: utf
+Starting code units: \xef \xf0 \xf1 \xf2 \xf3
+Subject length lower bound = 1
+
+/[\x{fff4}-\x{afff8}\x{10ffff}]/I,utf
+Capture group count = 0
+Options: utf
+Starting code units: \xef \xf0 \xf1 \xf2 \xf4
+Subject length lower bound = 1
+
+/[\xff\x{ffff}]/I,utf
+Capture group count = 0
+Options: utf
+Starting code units: \xc3 \xef
+Subject length lower bound = 1
+
+/[\xff\x{ff}]/I,utf
+Capture group count = 0
+Options: utf
+Starting code units: \xc3
+Subject length lower bound = 1
+
+/[\xff\x{ff}]/I
+Capture group count = 0
+Starting code units: \xff
+Subject length lower bound = 1
+
+/[Ss]/I
+Capture group count = 0
+First code unit = 'S' (caseless)
+Subject length lower bound = 1
+
+/[Ss]/I,utf
+Capture group count = 0
+Options: utf
+Starting code units: S s
+Subject length lower bound = 1
+
+/(?:\x{ff}|\x{3000})/I,utf
+Capture group count = 0
+Options: utf
+Starting code units: \xc3 \xe3
+Subject length lower bound = 1
+
+/x/utf
+ abxyz
+ 0: x
+ \x80\=startchar
+Failed: error -22: UTF-8 error: isolated byte with 0x80 bit set at offset 0
+ abc\x80\=startchar
+Failed: error -22: UTF-8 error: isolated byte with 0x80 bit set at offset 3
+ abc\x80\=startchar,offset=3
+Error -36 (bad UTF-8 offset)
# End of testinput10
diff --git a/testdata/testoutput11-16 b/testdata/testoutput11-16
index e22581d..78bf7fb 100644
--- a/testdata/testoutput11-16
+++ b/testdata/testoutput11-16
@@ -13,11 +13,11 @@
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Subject length lower bound = 1
/\x{100}/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = \x{100}
Subject length lower bound = 1
@@ -215,7 +215,7 @@ Subject length lower bound = 1
(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )*
\) )* # optional trailing comment
/Ix
-Capturing subpattern count = 0
+Capture group count = 0
Contains explicit CR or LF match
Options: extended
Starting code units: \x09 \x20 ! " # $ % & ' ( * + - / 0 1 2 3 4 5 6 7 8
@@ -260,7 +260,7 @@ Subject length lower bound = 3
------------------------------------------------------------------
/\h+/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x09 \x20 \xa0 \xff
Subject length lower bound = 1
\x{1681}\x{200b}\x{1680}\x{2000}\x{202f}\x{3000}
@@ -275,7 +275,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x09 \x20 \xa0 \xff
Subject length lower bound = 1
\x{1681}\x{200b}\x{1680}\x{2000}\x{202f}\x{3000}
@@ -284,7 +284,7 @@ Subject length lower bound = 1
0: \x{200a}\xa0\x{2000}
/\H+/I
-Capturing subpattern count = 0
+Capture group count = 0
Subject length lower bound = 1
\x{1680}\x{180e}\x{167f}\x{1681}\x{180d}\x{180f}
0: \x{167f}\x{1681}\x{180d}\x{180f}
@@ -306,7 +306,7 @@ Subject length lower bound = 1
0: \x9f\xa1\x{2fff}\x{3001}
/\v+/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x0a \x0b \x0c \x0d \x85 \xff
Subject length lower bound = 1
\x{2027}\x{2030}\x{2028}\x{2029}
@@ -321,7 +321,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x0a \x0b \x0c \x0d \x85 \xff
Subject length lower bound = 1
\x{2027}\x{2030}\x{2028}\x{2029}
@@ -330,7 +330,7 @@ Subject length lower bound = 1
0: \x85\x0a\x0b\x0c\x0d
/\V+/I
-Capturing subpattern count = 0
+Capture group count = 0
Subject length lower bound = 1
\x{2028}\x{2029}\x{2027}\x{2030}
0: \x{2027}\x{2030}
@@ -344,7 +344,7 @@ Subject length lower bound = 1
0: \x09\x0e\x84\x86
/\R+/I,bsr=unicode
-Capturing subpattern count = 0
+Capture group count = 0
\R matches any Unicode newline
Starting code units: \x0a \x0b \x0c \x0d \x85 \xff
Subject length lower bound = 1
@@ -354,7 +354,7 @@ Subject length lower bound = 1
0: \x85\x0a\x0b\x0c\x0d
/\x{d800}\x{d7ff}\x{dc00}\x{dc00}\x{dcff}\x{dd00}/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = \x{d800}
Last code unit = \x{dd00}
Subject length lower bound = 6
@@ -600,7 +600,7 @@ Failed: error 134 at offset 9: character code point value in \x{} or \o{} is too
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0a \x0b
\x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a
\x1b \x1c \x1d \x1e \x1f ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9
@@ -624,7 +624,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0e
\x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d
\x1e \x1f \x20 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = >
diff --git a/testdata/testoutput11-32 b/testdata/testoutput11-32
index d8a909f..4b00384 100644
--- a/testdata/testoutput11-32
+++ b/testdata/testoutput11-32
@@ -13,11 +13,11 @@
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Subject length lower bound = 1
/\x{100}/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = \x{100}
Subject length lower bound = 1
@@ -215,7 +215,7 @@ Subject length lower bound = 1
(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )*
\) )* # optional trailing comment
/Ix
-Capturing subpattern count = 0
+Capture group count = 0
Contains explicit CR or LF match
Options: extended
Starting code units: \x09 \x20 ! " # $ % & ' ( * + - / 0 1 2 3 4 5 6 7 8
@@ -260,7 +260,7 @@ Subject length lower bound = 3
------------------------------------------------------------------
/\h+/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x09 \x20 \xa0 \xff
Subject length lower bound = 1
\x{1681}\x{200b}\x{1680}\x{2000}\x{202f}\x{3000}
@@ -275,7 +275,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x09 \x20 \xa0 \xff
Subject length lower bound = 1
\x{1681}\x{200b}\x{1680}\x{2000}\x{202f}\x{3000}
@@ -284,7 +284,7 @@ Subject length lower bound = 1
0: \x{200a}\xa0\x{2000}
/\H+/I
-Capturing subpattern count = 0
+Capture group count = 0
Subject length lower bound = 1
\x{1680}\x{180e}\x{167f}\x{1681}\x{180d}\x{180f}
0: \x{167f}\x{1681}\x{180d}\x{180f}
@@ -306,7 +306,7 @@ Subject length lower bound = 1
0: \x9f\xa1\x{2fff}\x{3001}
/\v+/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x0a \x0b \x0c \x0d \x85 \xff
Subject length lower bound = 1
\x{2027}\x{2030}\x{2028}\x{2029}
@@ -321,7 +321,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x0a \x0b \x0c \x0d \x85 \xff
Subject length lower bound = 1
\x{2027}\x{2030}\x{2028}\x{2029}
@@ -330,7 +330,7 @@ Subject length lower bound = 1
0: \x85\x0a\x0b\x0c\x0d
/\V+/I
-Capturing subpattern count = 0
+Capture group count = 0
Subject length lower bound = 1
\x{2028}\x{2029}\x{2027}\x{2030}
0: \x{2027}\x{2030}
@@ -344,7 +344,7 @@ Subject length lower bound = 1
0: \x09\x0e\x84\x86
/\R+/I,bsr=unicode
-Capturing subpattern count = 0
+Capture group count = 0
\R matches any Unicode newline
Starting code units: \x0a \x0b \x0c \x0d \x85 \xff
Subject length lower bound = 1
@@ -354,7 +354,7 @@ Subject length lower bound = 1
0: \x85\x0a\x0b\x0c\x0d
/\x{d800}\x{d7ff}\x{dc00}\x{dc00}\x{dcff}\x{dd00}/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = \x{d800}
Last code unit = \x{dd00}
Subject length lower bound = 6
@@ -558,19 +558,19 @@ Failed: error 134 at offset 12: character code point value in \x{} or \o{} is to
Failed: error 134 at offset 14: character code point value in \x{} or \o{} is too large
/\x{7fffffff}\x{7fffffff}/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = \x{7fffffff}
Last code unit = \x{7fffffff}
Subject length lower bound = 2
/\x{80000000}\x{80000000}/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = \x{80000000}
Last code unit = \x{80000000}
Subject length lower bound = 2
/\x{ffffffff}\x{ffffffff}/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = \x{ffffffff}
Last code unit = \x{ffffffff}
Subject length lower bound = 2
@@ -588,7 +588,7 @@ Subject length lower bound = 2
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless
First code unit = \x{400000}
Last code unit = \x{800000}
@@ -603,7 +603,7 @@ Subject length lower bound = 2
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0a \x0b
\x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a
\x1b \x1c \x1d \x1e \x1f ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9
@@ -627,7 +627,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0e
\x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d
\x1e \x1f \x20 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = >
diff --git a/testdata/testoutput12-16 b/testdata/testoutput12-16
index 52dbe74..3006bc1 100644
--- a/testdata/testoutput12-16
+++ b/testdata/testoutput12-16
@@ -18,7 +18,7 @@
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{ffff}
Subject length lower bound = 1
@@ -30,7 +30,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{d800}
Last code unit = \x{dc00}
@@ -43,7 +43,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{100}
Subject length lower bound = 1
@@ -55,7 +55,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{1000}
Subject length lower bound = 1
@@ -67,7 +67,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{d800}
Last code unit = \x{dc00}
@@ -80,7 +80,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{dbc0}
Last code unit = \x{dc00}
@@ -93,7 +93,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{dbff}
Last code unit = \x{dfff}
@@ -106,7 +106,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xff
Subject length lower bound = 1
@@ -118,7 +118,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{100}
Subject length lower bound = 1
@@ -130,7 +130,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x80
Subject length lower bound = 1
@@ -142,7 +142,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xff
Subject length lower bound = 1
@@ -154,7 +154,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{d55c}
Last code unit = \x{c5b4}
@@ -169,7 +169,7 @@ Subject length lower bound = 3
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{65e5}
Last code unit = \x{8a9e}
@@ -184,7 +184,7 @@ Subject length lower bound = 3
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x80
Subject length lower bound = 1
@@ -196,7 +196,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x84
Subject length lower bound = 1
@@ -208,7 +208,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{104}
Subject length lower bound = 1
@@ -220,7 +220,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{861}
Subject length lower bound = 1
@@ -232,7 +232,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{d844}
Last code unit = \x{deab}
@@ -245,7 +245,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
\x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19
@@ -281,7 +281,7 @@ No match
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{100}
Last code unit = \x{100}
@@ -300,7 +300,7 @@ Subject length lower bound = 3
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
Starting code units: x \xff
Subject length lower bound = 1
@@ -317,7 +317,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
Starting code units: a x \xff
Subject length lower bound = 1
@@ -334,7 +334,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
Starting code units: a x \xff
Subject length lower bound = 1
@@ -352,7 +352,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
Starting code units: x \xff
Subject length lower bound = 1
@@ -364,7 +364,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{100}
Subject length lower bound = 1
@@ -377,7 +377,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = 'a'
Last code unit = \x{100}
@@ -391,7 +391,7 @@ Subject length lower bound = 2
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = 'a'
Last code unit = \x{101}
@@ -404,7 +404,7 @@ Subject length lower bound = 3
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Subject length lower bound = 1
/[\x{100}]/IB,utf
@@ -414,7 +414,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{100}
Subject length lower bound = 1
@@ -432,7 +432,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xff
Subject length lower bound = 1
@@ -446,7 +446,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Subject length lower bound = 1
@@ -461,14 +461,14 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
First code unit = \x{100}
Last code unit = 'z'
Subject length lower bound = 7
/\777/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{1ff}
Subject length lower bound = 1
@@ -485,7 +485,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{100}
Last code unit = \x{200}
@@ -499,7 +499,7 @@ Subject length lower bound = 2
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{100}
Last code unit = 'X'
@@ -547,7 +547,7 @@ Failed: error -24: UTF-16 error: missing low surrogate at end at offset 2
0: \x{11234}
/(*UTF)\x{11234}/I
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: utf
First code unit = \x{d804}
@@ -565,7 +565,7 @@ Failed: error 160 at offset 5: (*VERB) not recognized or malformed
abcd\x{11234}pqr
/(*CRLF)(*UTF16)(*BSR_UNICODE)a\Rb/I
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: utf
\R matches any Unicode newline
@@ -575,10 +575,10 @@ Last code unit = 'b'
Subject length lower bound = 3
/(*CRLF)(*UTF32)(*BSR_UNICODE)a\Rb/I
-Failed: error 160 at offset 12: (*VERB) not recognized or malformed
+Failed: error 160 at offset 14: (*VERB) not recognized or malformed
/\h/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x09 \x20 \xa0 \xff
Subject length lower bound = 1
@@ -602,7 +602,7 @@ Subject length lower bound = 1
0: \x{3000}
/\v/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x0a \x0b \x0c \x0d \x85 \xff
Subject length lower bound = 1
@@ -620,7 +620,7 @@ Subject length lower bound = 1
0: \x{2028}
/\h*A/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x09 \x20 A \xa0 \xff
Last code unit = 'A'
@@ -631,7 +631,7 @@ Subject length lower bound = 1
0: \x{2000}A
/\R*A/I,bsr=unicode,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
\R matches any Unicode newline
Starting code units: \x0a \x0b \x0c \x0d A \x85 \xff
@@ -643,21 +643,21 @@ Subject length lower bound = 1
0: \x{2028}A
/\v+A/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x0a \x0b \x0c \x0d \x85 \xff
Last code unit = 'A'
Subject length lower bound = 2
/\s?xxx\s/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x09 \x0a \x0b \x0c \x0d \x20 x
Last code unit = 'x'
Subject length lower bound = 4
/\sxxx\s/I,utf,tables=2
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x09 \x0a \x0b \x0c \x0d \x20 \x85 \xa0
Last code unit = 'x'
@@ -668,7 +668,7 @@ Subject length lower bound = 5
0: \x{a0}xxx\x{85}
/\S \S/I,utf,tables=2
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0e \x0f
\x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e
@@ -708,25 +708,25 @@ Failed: error -33: bad offset value
Failed: error -33: bad offset value
/\x{1234}+/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = \x{1234}
Subject length lower bound = 1
/\x{1234}+?/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = \x{1234}
Subject length lower bound = 1
/\x{1234}++/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = \x{1234}
Subject length lower bound = 1
/\x{1234}{2}/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = \x{1234}
Last code unit = \x{1234}
@@ -739,7 +739,7 @@ Subject length lower bound = 2
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Subject length lower bound = 1
@@ -751,14 +751,14 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = 'X'
Last code unit = \x{200}
Subject length lower bound = 2
/\R/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x0a \x0b \x0c \x0d \x85 \xff
Subject length lower bound = 1
@@ -936,7 +936,7 @@ Failed: error 174 at offset 0: using UTF is disabled by the application
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = 'A' (caseless)
Last code unit = \x{1fb0} (caseless)
@@ -949,7 +949,7 @@ Subject length lower bound = 5
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = 'A'
Last code unit = \x{1fb0}
@@ -962,7 +962,7 @@ Subject length lower bound = 5
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = 'A'
Last code unit = \x{1fb0}
@@ -975,14 +975,14 @@ Subject length lower bound = 3
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = 'A' (caseless)
Last code unit = \x{1fb0} (caseless)
Subject length lower bound = 3
/\x{401}\x{420}\x{421}\x{422}\x{423}\x{424}\x{425}\x{426}\x{427}\x{428}\x{429}\x{42a}\x{42b}\x{42c}\x{42d}\x{42e}\x{42f}/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = \x{401} (caseless)
Last code unit = \x{42f} (caseless)
@@ -1017,7 +1017,7 @@ Subject length lower bound = 17
------------------------------------------------------------------
/\x{212a}+/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: K k \xff
Subject length lower bound = 1
@@ -1025,7 +1025,7 @@ Subject length lower bound = 1
0: KKkk\x{212a}
/s+/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: S s \xff
Subject length lower bound = 1
@@ -1048,7 +1048,7 @@ Failed: error 134 at offset 10: character code point value in \x{} or \o{} is to
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: A \xff
Last code unit = 'A'
@@ -1065,7 +1065,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: 0 1 2 3 4 5 6 7 8 9 \xff
Subject length lower bound = 1
@@ -1077,7 +1077,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: Z \xff
Subject length lower bound = 1
@@ -1095,7 +1095,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84 \x85 \x86 \x87
\x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95 \x96
@@ -1115,7 +1115,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: - ] a d z \xff
Subject length lower bound = 1
@@ -1136,7 +1136,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
Starting code units: a b \xff
Last code unit = 'z'
@@ -1150,7 +1150,7 @@ Subject length lower bound = 7
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x09 \x0a \x0b \x0c \x0d \x20 \xff
Subject length lower bound = 1
@@ -1163,7 +1163,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: 0 1 2 3 4 5 6 7 8 9 \xff
Subject length lower bound = 1
@@ -1176,7 +1176,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P
Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z
@@ -1191,7 +1191,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
\x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19
@@ -1217,7 +1217,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0e \x0f
\x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e
@@ -1243,7 +1243,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
\x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19
@@ -1266,7 +1266,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: \xff
Subject length lower bound = 1
@@ -1289,7 +1289,7 @@ No match
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: Z z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84 \x85 \x86
\x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95
@@ -1335,7 +1335,7 @@ No match
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: Z z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84 \x85 \x86
\x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95
@@ -1357,7 +1357,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: \xff
Last code unit = 'B' (caseless)
@@ -1443,7 +1443,7 @@ Failed: error 191 at offset 0: PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is not allowe
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options: utf
Overall options: anchored utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
@@ -1470,5 +1470,162 @@ Subject length lower bound = 1
\= Expect no match
aaa
No match
+
+# Offsets are different in 8-bit mode.
+
+/(?<=abc)(|def)/g,utf,replace=<$0>,substitute_callout
+ 123abcáyzabcdef789abcá´qr
+ 1(2) Old 6 6 "" New 6 8 "<>"
+ 2(2) Old 12 12 "" New 14 16 "<>"
+ 3(2) Old 12 15 "def" New 16 21 ""
+ 4(2) Old 21 21 "" New 27 29 "<>"
+ 4: 123abc<>\x{e1}yzabc<>789abc<>\x{1234}qr
+
+# A few script run tests in non-UTF mode (but they need Unicode support)
+
+/^(*script_run:.{4})/
+ \x{3041}\x{30a1}\x{3007}\x{3007} Hiragana Katakana Han Han
+ 0: \x{3041}\x{30a1}\x{3007}\x{3007}
+ \x{30a1}\x{3041}\x{3007}\x{3007} Katakana Hiragana Han Han
+ 0: \x{30a1}\x{3041}\x{3007}\x{3007}
+ \x{1100}\x{2e80}\x{2e80}\x{1101} Hangul Han Han Hangul
+ 0: \x{1100}\x{2e80}\x{2e80}\x{1101}
+
+/^(*sr:.*)/utf,allow_surrogate_escapes
+Failed: error 191 at offset 0: PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is not allowed in UTF-16 mode
+ \x{2e80}\x{3105}\x{2e80}\x{30a1} Han Bopomofo Han Katakana
+ \x{d800}\x{dfff} Surrogates (Unknown) \=no_utf_check
+
+/(?(n/utf
+Failed: error 142 at offset 4: syntax error in subpattern name (missing terminator?)
+
+/(?(á/utf
+Failed: error 142 at offset 4: syntax error in subpattern name (missing terminator?)
+
+# Invalid UTF-16/32 tests.
+
+/.../g,match_invalid_utf
+ abcd\x{df00}wxzy\x{df00}pqrs
+ 0: abc
+ 0: wxz
+ 0: pqr
+ abcd\x{80}wxzy\x{df00}pqrs
+ 0: abc
+ 0: d\x{80}w
+ 0: xzy
+ 0: pqr
+
+/abc/match_invalid_utf
+ ab\x{df00}ab\=ph
+Partial match: ab
+\= Expect no match
+ ab\x{df00}cdef\=ph
+No match
+
+/ab$/match_invalid_utf
+ ab\x{df00}cdeab
+ 0: ab
+\= Expect no match
+ ab\x{df00}cde
+No match
+
+/.../g,match_invalid_utf
+ abcd\x{80}wxzy\x{df00}pqrs
+ 0: abc
+ 0: d\x{80}w
+ 0: xzy
+ 0: pqr
+
+/(?<=x)../g,match_invalid_utf
+ abcd\x{80}wxzy\x{df00}pqrs
+ 0: zy
+ abcd\x{80}wxzy\x{df00}xpqrs
+ 0: zy
+ 0: pq
+
+/X$/match_invalid_utf
+\= Expect no match
+ X\x{df00}
+No match
+
+/(?<=..)X/match_invalid_utf,aftertext
+ AB\x{df00}AQXYZ
+ 0: X
+ 0+ YZ
+ AB\x{df00}AQXYZ\=offset=5
+ 0: X
+ 0+ YZ
+ AB\x{df00}\x{df00}AXYZXC\=offset=5
+ 0: X
+ 0+ C
+\= Expect no match
+ AB\x{df00}XYZ
+No match
+ AB\x{df00}XYZ\=offset=3
+No match
+ AB\x{df00}AXYZ
+No match
+ AB\x{df00}AXYZ\=offset=4
+No match
+ AB\x{df00}\x{df00}AXYZ\=offset=5
+No match
+
+/.../match_invalid_utf
+\= Expect no match
+ A\x{d800}B
+No match
+ A\x{110000}B
+** Failed: character \x{110000} is greater than 0x10ffff and so cannot be converted to UTF-16
+
+# ----------------------------------------------------
+
+/(*UTF)(?=\x{123})/I
+Capture group count = 0
+May match empty string
+Compile options:
+Overall options: utf
+First code unit = \x{123}
+Subject length lower bound = 1
+
+/[\x{c1}\x{e1}]X[\x{145}\x{146}]/I,utf
+Capture group count = 0
+Options: utf
+First code unit = \xc1 (caseless)
+Last code unit = \x{145} (caseless)
+Subject length lower bound = 3
+
+/[\xff\x{ffff}]/I,utf
+Capture group count = 0
+Options: utf
+Starting code units: \xff
+Subject length lower bound = 1
+
+/[\xff\x{ff}]/I,utf
+Capture group count = 0
+Options: utf
+Starting code units: \xff
+Subject length lower bound = 1
+
+/[\xff\x{ff}]/I
+Capture group count = 0
+Starting code units: \xff
+Subject length lower bound = 1
+
+/[Ss]/I
+Capture group count = 0
+Starting code units: S s
+Subject length lower bound = 1
+
+/[Ss]/I,utf
+Capture group count = 0
+Options: utf
+Starting code units: S s
+Subject length lower bound = 1
+
+/(?:\x{ff}|\x{3000})/I,utf
+Capture group count = 0
+Options: utf
+Starting code units: \xff
+Subject length lower bound = 1
# End of testinput12
diff --git a/testdata/testoutput12-32 b/testdata/testoutput12-32
index 38ff92d..ad240e2 100644
--- a/testdata/testoutput12-32
+++ b/testdata/testoutput12-32
@@ -18,7 +18,7 @@
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{ffff}
Subject length lower bound = 1
@@ -30,7 +30,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{10000}
Subject length lower bound = 1
@@ -42,7 +42,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{100}
Subject length lower bound = 1
@@ -54,7 +54,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{1000}
Subject length lower bound = 1
@@ -66,7 +66,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{10000}
Subject length lower bound = 1
@@ -78,7 +78,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{100000}
Subject length lower bound = 1
@@ -90,7 +90,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{10ffff}
Subject length lower bound = 1
@@ -102,7 +102,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xff
Subject length lower bound = 1
@@ -114,7 +114,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{100}
Subject length lower bound = 1
@@ -126,7 +126,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x80
Subject length lower bound = 1
@@ -138,7 +138,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xff
Subject length lower bound = 1
@@ -150,7 +150,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{d55c}
Last code unit = \x{c5b4}
@@ -165,7 +165,7 @@ Subject length lower bound = 3
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{65e5}
Last code unit = \x{8a9e}
@@ -180,7 +180,7 @@ Subject length lower bound = 3
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x80
Subject length lower bound = 1
@@ -192,7 +192,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x84
Subject length lower bound = 1
@@ -204,7 +204,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{104}
Subject length lower bound = 1
@@ -216,7 +216,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{861}
Subject length lower bound = 1
@@ -228,7 +228,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{212ab}
Subject length lower bound = 1
@@ -240,7 +240,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
\x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19
@@ -276,7 +276,7 @@ No match
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{100}
Last code unit = \x{100}
@@ -295,7 +295,7 @@ Subject length lower bound = 3
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
Starting code units: x \xff
Subject length lower bound = 1
@@ -312,7 +312,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
Starting code units: a x \xff
Subject length lower bound = 1
@@ -329,7 +329,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
Starting code units: a x \xff
Subject length lower bound = 1
@@ -347,7 +347,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
Starting code units: x \xff
Subject length lower bound = 1
@@ -359,7 +359,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{100}
Subject length lower bound = 1
@@ -372,7 +372,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = 'a'
Last code unit = \x{100}
@@ -386,7 +386,7 @@ Subject length lower bound = 2
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = 'a'
Last code unit = \x{101}
@@ -399,7 +399,7 @@ Subject length lower bound = 3
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Subject length lower bound = 1
/[\x{100}]/IB,utf
@@ -409,7 +409,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{100}
Subject length lower bound = 1
@@ -427,7 +427,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \xff
Subject length lower bound = 1
@@ -441,7 +441,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Subject length lower bound = 1
@@ -456,14 +456,14 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
First code unit = \x{100}
Last code unit = 'z'
Subject length lower bound = 7
/\777/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{1ff}
Subject length lower bound = 1
@@ -480,7 +480,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{100}
Last code unit = \x{200}
@@ -494,7 +494,7 @@ Subject length lower bound = 2
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = \x{100}
Last code unit = 'X'
@@ -538,11 +538,11 @@ No match
Failed: error -27: UTF-32 error: code points 0xd800-0xdfff are not defined at offset 2
/(*UTF16)\x{11234}/
-Failed: error 160 at offset 5: (*VERB) not recognized or malformed
+Failed: error 160 at offset 7: (*VERB) not recognized or malformed
abcd\x{11234}pqr
/(*UTF)\x{11234}/I
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: utf
First code unit = \x{11234}
@@ -559,10 +559,10 @@ Failed: error 160 at offset 5: (*VERB) not recognized or malformed
abcd\x{11234}pqr
/(*CRLF)(*UTF16)(*BSR_UNICODE)a\Rb/I
-Failed: error 160 at offset 12: (*VERB) not recognized or malformed
+Failed: error 160 at offset 14: (*VERB) not recognized or malformed
/(*CRLF)(*UTF32)(*BSR_UNICODE)a\Rb/I
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: utf
\R matches any Unicode newline
@@ -572,7 +572,7 @@ Last code unit = 'b'
Subject length lower bound = 3
/\h/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x09 \x20 \xa0 \xff
Subject length lower bound = 1
@@ -596,7 +596,7 @@ Subject length lower bound = 1
0: \x{3000}
/\v/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x0a \x0b \x0c \x0d \x85 \xff
Subject length lower bound = 1
@@ -614,7 +614,7 @@ Subject length lower bound = 1
0: \x{2028}
/\h*A/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x09 \x20 A \xa0 \xff
Last code unit = 'A'
@@ -625,7 +625,7 @@ Subject length lower bound = 1
0: \x{2000}A
/\R*A/I,bsr=unicode,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
\R matches any Unicode newline
Starting code units: \x0a \x0b \x0c \x0d A \x85 \xff
@@ -637,21 +637,21 @@ Subject length lower bound = 1
0: \x{2028}A
/\v+A/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x0a \x0b \x0c \x0d \x85 \xff
Last code unit = 'A'
Subject length lower bound = 2
/\s?xxx\s/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x09 \x0a \x0b \x0c \x0d \x20 x
Last code unit = 'x'
Subject length lower bound = 4
/\sxxx\s/I,utf,tables=2
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x09 \x0a \x0b \x0c \x0d \x20 \x85 \xa0
Last code unit = 'x'
@@ -662,7 +662,7 @@ Subject length lower bound = 5
0: \x{a0}xxx\x{85}
/\S \S/I,utf,tables=2
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0e \x0f
\x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e
@@ -702,25 +702,25 @@ Failed: error -33: bad offset value
Failed: error -33: bad offset value
/\x{1234}+/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = \x{1234}
Subject length lower bound = 1
/\x{1234}+?/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = \x{1234}
Subject length lower bound = 1
/\x{1234}++/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = \x{1234}
Subject length lower bound = 1
/\x{1234}{2}/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = \x{1234}
Last code unit = \x{1234}
@@ -733,7 +733,7 @@ Subject length lower bound = 2
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Subject length lower bound = 1
@@ -745,14 +745,14 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = 'X'
Last code unit = \x{200}
Subject length lower bound = 2
/\R/I,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x0a \x0b \x0c \x0d \x85 \xff
Subject length lower bound = 1
@@ -930,7 +930,7 @@ Failed: error 174 at offset 0: using UTF is disabled by the application
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = 'A' (caseless)
Last code unit = \x{1fb0} (caseless)
@@ -943,7 +943,7 @@ Subject length lower bound = 5
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = 'A'
Last code unit = \x{1fb0}
@@ -956,7 +956,7 @@ Subject length lower bound = 5
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
First code unit = 'A'
Last code unit = \x{1fb0}
@@ -969,14 +969,14 @@ Subject length lower bound = 3
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = 'A' (caseless)
Last code unit = \x{1fb0} (caseless)
Subject length lower bound = 3
/\x{401}\x{420}\x{421}\x{422}\x{423}\x{424}\x{425}\x{426}\x{427}\x{428}\x{429}\x{42a}\x{42b}\x{42c}\x{42d}\x{42e}\x{42f}/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
First code unit = \x{401} (caseless)
Last code unit = \x{42f} (caseless)
@@ -1011,7 +1011,7 @@ Subject length lower bound = 17
------------------------------------------------------------------
/\x{212a}+/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: K k \xff
Subject length lower bound = 1
@@ -1019,7 +1019,7 @@ Subject length lower bound = 1
0: KKkk\x{212a}
/s+/Ii,utf
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: S s \xff
Subject length lower bound = 1
@@ -1042,7 +1042,7 @@ Failed: error 134 at offset 10: character code point value in \x{} or \o{} is to
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: A \xff
Last code unit = 'A'
@@ -1059,7 +1059,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: 0 1 2 3 4 5 6 7 8 9 \xff
Subject length lower bound = 1
@@ -1071,7 +1071,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: Z \xff
Subject length lower bound = 1
@@ -1089,7 +1089,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84 \x85 \x86 \x87
\x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95 \x96
@@ -1109,7 +1109,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: - ] a d z \xff
Subject length lower bound = 1
@@ -1130,7 +1130,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Options: utf
Starting code units: a b \xff
Last code unit = 'z'
@@ -1144,7 +1144,7 @@ Subject length lower bound = 7
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x09 \x0a \x0b \x0c \x0d \x20 \xff
Subject length lower bound = 1
@@ -1157,7 +1157,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: 0 1 2 3 4 5 6 7 8 9 \xff
Subject length lower bound = 1
@@ -1170,7 +1170,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P
Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z
@@ -1185,7 +1185,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
\x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19
@@ -1211,7 +1211,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0e \x0f
\x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e
@@ -1237,7 +1237,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
\x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19
@@ -1260,7 +1260,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: \xff
Subject length lower bound = 1
@@ -1283,7 +1283,7 @@ No match
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: Z z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84 \x85 \x86
\x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95
@@ -1329,7 +1329,7 @@ No match
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: Z z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84 \x85 \x86
\x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95
@@ -1351,7 +1351,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless utf
Starting code units: \xff
Last code unit = 'B' (caseless)
@@ -1418,7 +1418,7 @@ No match
# errors in 16-bit mode.
/\x{d800}/I,utf,allow_surrogate_escapes
-Capturing subpattern count = 0
+Capture group count = 0
Options: utf
Extra options: allow_surrogate_escapes
First code unit = \x{d800}
@@ -1440,7 +1440,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options: utf
Overall options: anchored utf
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
@@ -1467,5 +1467,163 @@ Subject length lower bound = 1
\= Expect no match
aaa
No match
+
+# Offsets are different in 8-bit mode.
+
+/(?<=abc)(|def)/g,utf,replace=<$0>,substitute_callout
+ 123abcáyzabcdef789abcá´qr
+ 1(2) Old 6 6 "" New 6 8 "<>"
+ 2(2) Old 12 12 "" New 14 16 "<>"
+ 3(2) Old 12 15 "def" New 16 21 ""
+ 4(2) Old 21 21 "" New 27 29 "<>"
+ 4: 123abc<>\x{e1}yzabc<>789abc<>\x{1234}qr
+
+# A few script run tests in non-UTF mode (but they need Unicode support)
+
+/^(*script_run:.{4})/
+ \x{3041}\x{30a1}\x{3007}\x{3007} Hiragana Katakana Han Han
+ 0: \x{3041}\x{30a1}\x{3007}\x{3007}
+ \x{30a1}\x{3041}\x{3007}\x{3007} Katakana Hiragana Han Han
+ 0: \x{30a1}\x{3041}\x{3007}\x{3007}
+ \x{1100}\x{2e80}\x{2e80}\x{1101} Hangul Han Han Hangul
+ 0: \x{1100}\x{2e80}\x{2e80}\x{1101}
+
+/^(*sr:.*)/utf,allow_surrogate_escapes
+ \x{2e80}\x{3105}\x{2e80}\x{30a1} Han Bopomofo Han Katakana
+ 0: \x{2e80}\x{3105}\x{2e80}
+ \x{d800}\x{dfff} Surrogates (Unknown) \=no_utf_check
+ 0: \x{d800}
+
+/(?(n/utf
+Failed: error 142 at offset 4: syntax error in subpattern name (missing terminator?)
+
+/(?(á/utf
+Failed: error 142 at offset 4: syntax error in subpattern name (missing terminator?)
+
+# Invalid UTF-16/32 tests.
+
+/.../g,match_invalid_utf
+ abcd\x{df00}wxzy\x{df00}pqrs
+ 0: abc
+ 0: wxz
+ 0: pqr
+ abcd\x{80}wxzy\x{df00}pqrs
+ 0: abc
+ 0: d\x{80}w
+ 0: xzy
+ 0: pqr
+
+/abc/match_invalid_utf
+ ab\x{df00}ab\=ph
+Partial match: ab
+\= Expect no match
+ ab\x{df00}cdef\=ph
+No match
+
+/ab$/match_invalid_utf
+ ab\x{df00}cdeab
+ 0: ab
+\= Expect no match
+ ab\x{df00}cde
+No match
+
+/.../g,match_invalid_utf
+ abcd\x{80}wxzy\x{df00}pqrs
+ 0: abc
+ 0: d\x{80}w
+ 0: xzy
+ 0: pqr
+
+/(?<=x)../g,match_invalid_utf
+ abcd\x{80}wxzy\x{df00}pqrs
+ 0: zy
+ abcd\x{80}wxzy\x{df00}xpqrs
+ 0: zy
+ 0: pq
+
+/X$/match_invalid_utf
+\= Expect no match
+ X\x{df00}
+No match
+
+/(?<=..)X/match_invalid_utf,aftertext
+ AB\x{df00}AQXYZ
+ 0: X
+ 0+ YZ
+ AB\x{df00}AQXYZ\=offset=5
+ 0: X
+ 0+ YZ
+ AB\x{df00}\x{df00}AXYZXC\=offset=5
+ 0: X
+ 0+ C
+\= Expect no match
+ AB\x{df00}XYZ
+No match
+ AB\x{df00}XYZ\=offset=3
+No match
+ AB\x{df00}AXYZ
+No match
+ AB\x{df00}AXYZ\=offset=4
+No match
+ AB\x{df00}\x{df00}AXYZ\=offset=5
+No match
+
+/.../match_invalid_utf
+\= Expect no match
+ A\x{d800}B
+No match
+ A\x{110000}B
+No match
+
+# ----------------------------------------------------
+
+/(*UTF)(?=\x{123})/I
+Capture group count = 0
+May match empty string
+Compile options:
+Overall options: utf
+First code unit = \x{123}
+Subject length lower bound = 1
+
+/[\x{c1}\x{e1}]X[\x{145}\x{146}]/I,utf
+Capture group count = 0
+Options: utf
+First code unit = \xc1 (caseless)
+Last code unit = \x{145} (caseless)
+Subject length lower bound = 3
+
+/[\xff\x{ffff}]/I,utf
+Capture group count = 0
+Options: utf
+Starting code units: \xff
+Subject length lower bound = 1
+
+/[\xff\x{ff}]/I,utf
+Capture group count = 0
+Options: utf
+Starting code units: \xff
+Subject length lower bound = 1
+
+/[\xff\x{ff}]/I
+Capture group count = 0
+Starting code units: \xff
+Subject length lower bound = 1
+
+/[Ss]/I
+Capture group count = 0
+Starting code units: S s
+Subject length lower bound = 1
+
+/[Ss]/I,utf
+Capture group count = 0
+Options: utf
+Starting code units: S s
+Subject length lower bound = 1
+
+/(?:\x{ff}|\x{3000})/I,utf
+Capture group count = 0
+Options: utf
+Starting code units: \xff
+Subject length lower bound = 1
# End of testinput12
diff --git a/testdata/testoutput15 b/testdata/testoutput15
index d09e781..9154e5f 100644
--- a/testdata/testoutput15
+++ b/testdata/testoutput15
@@ -7,7 +7,7 @@
# (2) Other tests that must not be run with JIT.
/(a+)*zz/I
-Capturing subpattern count = 1
+Capture group count = 1
Starting code units: a z
Last code unit = 'z'
Subject length lower bound = 2
@@ -24,7 +24,7 @@ Minimum depth limit = 30
No match
!((?:\s|//.*\\n|/[*](?:\\n|.)*?[*]/)*)!I
-Capturing subpattern count = 1
+Capture group count = 1
May match empty string
Subject length lower bound = 0
/* this is a C style comment */\=find_limits
@@ -45,7 +45,7 @@ Minimum heap limit = 0
Minimum match limit = 12
Minimum depth limit = 3
0: aaaaaaaaa
-
+
/(a)(?1)++/
aa\=find_limits
Minimum heap limit = 0
@@ -66,7 +66,7 @@ Minimum heap limit = 0
Minimum match limit = 24
Minimum depth limit = 3
0: abbbbbbbbbbbbbbbbbbbbba
-
+
/a(?:.(*THEN))*?a/ims
abbbbbbbbbbbbbbbbbbbbba\=find_limits
Minimum heap limit = 0
@@ -117,7 +117,7 @@ Failed: error 160 at offset 17: (*VERB) not recognized or malformed
Failed: error 160 at offset 24: (*VERB) not recognized or malformed
/(*LIMIT_DEPTH=4294967280)abc/I
-Capturing subpattern count = 0
+Capture group count = 0
Depth limit = 4294967280
First code unit = 'a'
Last code unit = 'c'
@@ -137,7 +137,7 @@ Failed: error -47: match limit exceeded
Failed: error -53: matching depth limit exceeded
/(*LIMIT_MATCH=3000)(a+)*zz/I
-Capturing subpattern count = 1
+Capture group count = 1
Match limit = 3000
Starting code units: a z
Last code unit = 'z'
@@ -150,7 +150,7 @@ Failed: error -47: match limit exceeded
Failed: error -47: match limit exceeded
/(*LIMIT_MATCH=60000)(*LIMIT_MATCH=3000)(a+)*zz/I
-Capturing subpattern count = 1
+Capture group count = 1
Match limit = 3000
Starting code units: a z
Last code unit = 'z'
@@ -160,7 +160,7 @@ Subject length lower bound = 2
Failed: error -47: match limit exceeded
/(*LIMIT_MATCH=60000)(a+)*zz/I
-Capturing subpattern count = 1
+Capture group count = 1
Match limit = 60000
Starting code units: a z
Last code unit = 'z'
@@ -173,7 +173,7 @@ No match
Failed: error -47: match limit exceeded
/(*LIMIT_DEPTH=10)(a+)*zz/I
-Capturing subpattern count = 1
+Capture group count = 1
Depth limit = 10
Starting code units: a z
Last code unit = 'z'
@@ -186,7 +186,7 @@ Failed: error -53: matching depth limit exceeded
Failed: error -53: matching depth limit exceeded
/(*LIMIT_DEPTH=10)(*LIMIT_DEPTH=1000)(a+)*zz/I
-Capturing subpattern count = 1
+Capture group count = 1
Depth limit = 1000
Starting code units: a z
Last code unit = 'z'
@@ -196,7 +196,7 @@ Subject length lower bound = 2
No match
/(*LIMIT_DEPTH=1000)(a+)*zz/I
-Capturing subpattern count = 1
+Capture group count = 1
Depth limit = 1000
Starting code units: a z
Last code unit = 'z'
@@ -207,9 +207,9 @@ No match
\= Expect limit exceeded
aaaaaaaaaaaaaz\=depth_limit=10
Failed: error -53: matching depth limit exceeded
-
-# These three have infinitely nested recursions.
-
+
+# These three have infinitely nested recursions.
+
/((?2))((?1))/
abc
Failed: error -52: nested recursion at the same subject position
@@ -221,7 +221,7 @@ Failed: error -52: nested recursion at the same subject position
/(?(R)a*(?1)|((?R))b)/
aaaabcde
Failed: error -52: nested recursion at the same subject position
-
+
# The allusedtext modifier does not work with JIT, which does not maintain
# the leftchar/rightchar data.
@@ -233,7 +233,7 @@ Failed: error -52: nested recursion at the same subject position
0: abcxyz
>>>
0+ xyzpqr
-
+
/(?<=pqr)abc(?=xyz)/allusedtext
xyzpqrabcxyzpqr
0: pqrabcxyz
@@ -242,12 +242,12 @@ Failed: error -52: nested recursion at the same subject position
0: pqrabcxyz
<<< >>>
0+ xyzpqr
-
+
/a\b/
a.\=allusedtext
0: a.
>
- a\=allusedtext
+ a\=allusedtext
0: a
/abc\Kxyz/
@@ -264,65 +264,173 @@ Failed: error -52: nested recursion at the same subject position
abcabcdefg
0: abcabcde
>>>>>
-
+
+#subject allusedtext
+
+/(?<=abc)123/
+ xyzabc123pqr
+ 0: abc123
+ <<<
+ xyzabc12\=ps
+Partial match: abc12
+ <<<
+ xyzabc12\=ph
+Partial match: abc12
+ <<<
+
+/\babc\b/
+ +++abc+++
+ 0: +abc+
+ < >
+ +++ab\=ps
+Partial match: +ab
+ <
+ +++ab\=ph
+Partial match: +ab
+ <
+
+/(?<=abc)def/
+ abc\=ph
+Partial match: abc
+ <<<
+
+/(?<=123)(*MARK:xx)abc/mark
+ xxxx123a\=ph
+Partial match, mark=xx: 123a
+ <<<
+ xxxx123a\=ps
+Partial match, mark=xx: 123a
+ <<<
+
+/(?<=(?<=a)b)c.*/I
+Capture group count = 0
+Max lookbehind = 1
+First code unit = 'c'
+Subject length lower bound = 1
+ abc\=ph
+Partial match: abc
+ <<
+\= Expect no match
+ xbc\=ph
+No match
+
+/(?<=ab)c.*/I
+Capture group count = 0
+Max lookbehind = 2
+First code unit = 'c'
+Subject length lower bound = 1
+ abc\=ph
+Partial match: abc
+ <<
+\= Expect no match
+ xbc\=ph
+No match
+
+/abc(?<=bc)def/
+ xxxabcd\=ph
+Partial match: abcd
+
+/(?<=ab)cdef/
+ xxabcd\=ph
+Partial match: abcd
+ <<
+
+/(?<=(?<=(?<=a)b)c)./I
+Capture group count = 0
+Max lookbehind = 1
+Subject length lower bound = 1
+ 123abcXYZ
+ 0: abcX
+ <<<
+
+/(?<=ab(cd(?<=...)))./I
+Capture group count = 1
+Max lookbehind = 4
+Subject length lower bound = 1
+ abcdX
+ 0: abcdX
+ <<<<
+ 1: cd
+
+/(?<=ab((?<=...)cd))./I
+Capture group count = 1
+Max lookbehind = 4
+Subject length lower bound = 1
+ ZabcdX
+ 0: ZabcdX
+ <<<<<
+ 1: cd
+
+/(?<=((?<=(?<=ab).))(?1)(?1))./I
+Capture group count = 1
+Max lookbehind = 2
+Subject length lower bound = 1
+ abxZ
+ 0: abxZ
+ <<<
+ 1:
+
+#subject
+# -------------------------------------------------------------------
+
# These tests provoke recursion loops, which give a different error message
# when JIT is used.
/(?R)/I
-Capturing subpattern count = 0
+Capture group count = 0
May match empty string
Subject length lower bound = 0
abcd
Failed: error -52: nested recursion at the same subject position
/(a|(?R))/I
-Capturing subpattern count = 1
+Capture group count = 1
May match empty string
Subject length lower bound = 0
abcd
0: a
1: a
- defg
+ defg
Failed: error -52: nested recursion at the same subject position
/(ab|(bc|(de|(?R))))/I
-Capturing subpattern count = 3
+Capture group count = 3
May match empty string
Subject length lower bound = 0
abcd
0: ab
1: ab
- fghi
+ fghi
Failed: error -52: nested recursion at the same subject position
/(ab|(bc|(de|(?1))))/I
-Capturing subpattern count = 3
+Capture group count = 3
May match empty string
Subject length lower bound = 0
abcd
0: ab
1: ab
- fghi
+ fghi
Failed: error -52: nested recursion at the same subject position
/x(ab|(bc|(de|(?1)x)x)x)/I
-Capturing subpattern count = 3
+Capture group count = 3
First code unit = 'x'
Subject length lower bound = 3
xab123
0: xab
1: ab
- xfghi
+ xfghi
Failed: error -52: nested recursion at the same subject position
/(?!\w)(?R)/
abcd
Failed: error -52: nested recursion at the same subject position
- =abc
+ =abc
Failed: error -52: nested recursion at the same subject position
/(?=\w)(?R)/
- =abc
+ =abc
Failed: error -52: nested recursion at the same subject position
abcd
Failed: error -52: nested recursion at the same subject position
@@ -339,7 +447,7 @@ Failed: error -52: nested recursion at the same subject position
aaa
0: aaa
1: aaa
- bbb
+ bbb
Failed: error -52: nested recursion at the same subject position
/[^\xff]((?1))/BI
@@ -352,12 +460,12 @@ Failed: error -52: nested recursion at the same subject position
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Subject length lower bound = 1
abcd
Failed: error -52: nested recursion at the same subject position
-
-# These tests don't behave the same with JIT
+
+# These tests don't behave the same with JIT
/\w+(?C1)/BI,no_auto_possess
------------------------------------------------------------------
@@ -367,7 +475,7 @@ Failed: error -52: nested recursion at the same subject position
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Options: no_auto_possess
Starting code units: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P
Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z
@@ -390,7 +498,7 @@ No match
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: no_auto_possess
Starting code units: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P
@@ -406,7 +514,7 @@ Subject length lower bound = 1
1 ^^ End of pattern
No match
-# This test breaks the JIT stack limit
+# This test breaks the JIT stack limit
/(|]+){2,2452}/
(|]+){2,2452}
@@ -417,4 +525,12 @@ No match
\[a]{60}
Failed: error -63: heap limit exceeded
+/b(?
+ abcz
+ 0: abcz
+ < >>
+
# End of testinput15
diff --git a/testdata/testoutput16 b/testdata/testoutput16
index 616567b..78d43bd 100644
--- a/testdata/testoutput16
+++ b/testdata/testoutput16
@@ -3,14 +3,14 @@
# are different without JIT.
/abc/I,jit,jitverify
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'c'
Subject length lower bound = 3
JIT support is not available in this version of PCRE2
/a*/I
-Capturing subpattern count = 0
+Capture group count = 0
May match empty string
Subject length lower bound = 0
diff --git a/testdata/testoutput17 b/testdata/testoutput17
index acf00e0..b66cfa3 100644
--- a/testdata/testoutput17
+++ b/testdata/testoutput17
@@ -6,7 +6,7 @@
# JIT does not support this pattern (callout at start of condition).
/(?(?C1)(?=a)a)/I
-Capturing subpattern count = 0
+Capture group count = 0
May match empty string
Subject length lower bound = 0
JIT compilation was not successful (no more memory)
@@ -14,7 +14,7 @@ JIT compilation was not successful (no more memory)
# The following pattern cannot be compiled by JIT.
/b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*/I
-Capturing subpattern count = 0
+Capture group count = 0
May match empty string
Subject length lower bound = 0
JIT compilation was not successful (no more memory)
@@ -26,7 +26,7 @@ JIT compilation was not successful (no more memory)
Failed: error -46: JIT stack limit reached
/abcd/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'd'
Subject length lower bound = 4
@@ -38,7 +38,7 @@ JIT compilation was successful
No match (JIT)
/(*NO_JIT)abcd/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'd'
Subject length lower bound = 4
@@ -174,7 +174,7 @@ Partial match: ab (JIT)
No match (JIT)
/abcd/I,jit=2
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'd'
Subject length lower bound = 4
@@ -192,7 +192,7 @@ No match, mark = m (JIT)
# Limits tests that give different output with JIT.
/(a+)*zz/I
-Capturing subpattern count = 1
+Capture group count = 1
Starting code units: a z
Last code unit = 'z'
Subject length lower bound = 2
@@ -207,7 +207,7 @@ Minimum match limit = 16383
No match (JIT)
!((?:\s|//.*\\n|/[*](?:\\n|.)*?[*]/)*)!I
-Capturing subpattern count = 1
+Capture group count = 1
May match empty string
Subject length lower bound = 0
JIT compilation was successful
@@ -294,7 +294,7 @@ No match (JIT)
Failed: error -47: match limit exceeded
/(*LIMIT_MATCH=3000)(a+)*zz/I
-Capturing subpattern count = 1
+Capture group count = 1
Match limit = 3000
Starting code units: a z
Last code unit = 'z'
@@ -308,7 +308,7 @@ Failed: error -47: match limit exceeded
Failed: error -47: match limit exceeded
/(*LIMIT_MATCH=60000)(*LIMIT_MATCH=3000)(a+)*zz/I
-Capturing subpattern count = 1
+Capture group count = 1
Match limit = 3000
Starting code units: a z
Last code unit = 'z'
@@ -319,7 +319,7 @@ JIT compilation was successful
Failed: error -47: match limit exceeded
/(*LIMIT_MATCH=60000)(a+)*zz/I
-Capturing subpattern count = 1
+Capture group count = 1
Match limit = 60000
Starting code units: a z
Last code unit = 'z'
@@ -371,7 +371,7 @@ No match
/^abc\Kdef/info,push
** Applies only to compile when pattern is stacked with 'push': jitverify
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
First code unit = 'a'
@@ -383,7 +383,7 @@ JIT compilation was successful
/^abc\Kdef/info,push
** Applies only to compile when pattern is stacked with 'push': jitverify
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
First code unit = 'a'
@@ -423,7 +423,7 @@ JIT compilation was successful
# when JIT is used.
/(?R)/I
-Capturing subpattern count = 0
+Capture group count = 0
May match empty string
Subject length lower bound = 0
JIT compilation was successful
@@ -431,7 +431,7 @@ JIT compilation was successful
Failed: error -46: JIT stack limit reached
/(a|(?R))/I
-Capturing subpattern count = 1
+Capture group count = 1
May match empty string
Subject length lower bound = 0
JIT compilation was successful
@@ -442,7 +442,7 @@ JIT compilation was successful
Failed: error -46: JIT stack limit reached
/(ab|(bc|(de|(?R))))/I
-Capturing subpattern count = 3
+Capture group count = 3
May match empty string
Subject length lower bound = 0
JIT compilation was successful
@@ -453,7 +453,7 @@ JIT compilation was successful
Failed: error -46: JIT stack limit reached
/(ab|(bc|(de|(?1))))/I
-Capturing subpattern count = 3
+Capture group count = 3
May match empty string
Subject length lower bound = 0
JIT compilation was successful
@@ -464,7 +464,7 @@ JIT compilation was successful
Failed: error -46: JIT stack limit reached
/x(ab|(bc|(de|(?1)x)x)x)/I
-Capturing subpattern count = 3
+Capture group count = 3
First code unit = 'x'
Subject length lower bound = 3
JIT compilation was successful
@@ -511,7 +511,7 @@ Failed: error -46: JIT stack limit reached
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Subject length lower bound = 1
JIT compilation was successful
abcd
@@ -543,11 +543,11 @@ Failed: error -47: match limit exceeded
# ----
/[aC]/mg,firstline,newline=lf
-match\nmatch
+ match\nmatch
0: a (JIT)
/[aCz]/mg,firstline,newline=lf
-match\nmatch
+ match\nmatch
0: a (JIT)
# End of testinput17
diff --git a/testdata/testoutput2 b/testdata/testoutput2
index ecf0d80..c733c12 100644
--- a/testdata/testoutput2
+++ b/testdata/testoutput2
@@ -47,12 +47,12 @@
0: DE
/(a)b|/I
-Capturing subpattern count = 1
+Capture group count = 1
May match empty string
Subject length lower bound = 0
/abc/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'c'
Subject length lower bound = 3
@@ -69,7 +69,7 @@ No match
No match
/^abc/I
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
First code unit = 'a'
@@ -85,30 +85,30 @@ No match
No match
/a+bc/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'c'
Subject length lower bound = 3
/a*bc/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: a b
Last code unit = 'c'
Subject length lower bound = 2
/a{3}bc/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'c'
Subject length lower bound = 5
/(abc|a+z)/I
-Capturing subpattern count = 1
+Capture group count = 1
First code unit = 'a'
Subject length lower bound = 2
/^abc$/I
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
First code unit = 'a'
@@ -135,13 +135,13 @@ Failed: error 105 at offset 7: number too big in {} quantifier
Failed: error 106 at offset 5: missing terminating ] for character class
/[\B]/B
-Failed: error 107 at offset 2: invalid escape sequence in character class
+Failed: error 107 at offset 2: escape sequence is invalid in character class
/[\R]/B
-Failed: error 107 at offset 2: invalid escape sequence in character class
+Failed: error 107 at offset 2: escape sequence is invalid in character class
/[\X]/B
-Failed: error 107 at offset 2: invalid escape sequence in character class
+Failed: error 107 at offset 2: escape sequence is invalid in character class
/[z-a]/
Failed: error 108 at offset 3: range out of order in character class
@@ -159,19 +159,19 @@ Failed: error 118 at offset 7: missing ) after (?# comment
Failed: error 111 at offset 2: unrecognized character after (? or (?-
/.*b/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit at start or follows newline
Last code unit = 'b'
Subject length lower bound = 1
/.*?b/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit at start or follows newline
Last code unit = 'b'
Subject length lower bound = 1
/cat|dog|elephant/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: c d e
Subject length lower bound = 3
this sentence eventually mentions a cat
@@ -180,7 +180,7 @@ Subject length lower bound = 3
0: elephant
/cat|dog|elephant/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: c d e
Subject length lower bound = 3
this sentence eventually mentions a cat
@@ -189,7 +189,7 @@ Subject length lower bound = 3
0: elephant
/cat|dog|elephant/Ii
-Capturing subpattern count = 0
+Capture group count = 0
Options: caseless
Starting code units: C D E c d e
Subject length lower bound = 3
@@ -199,12 +199,12 @@ Subject length lower bound = 3
0: elephant
/a|[bcd]/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: a b c d
Subject length lower bound = 1
/(a|[^\dZ])/I
-Capturing subpattern count = 1
+Capture group count = 1
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
\x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19
\x1a \x1b \x1c \x1d \x1e \x1f \x20 ! " # $ % & ' ( ) * + , - . / : ; < = >
@@ -222,7 +222,7 @@ Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
Subject length lower bound = 1
/(a|b)*[\s]/I
-Capturing subpattern count = 1
+Capture group count = 1
Starting code units: \x09 \x0a \x0b \x0c \x0d \x20 a b
Subject length lower bound = 1
@@ -233,7 +233,7 @@ Failed: error 115 at offset 4: reference to non-existent subpattern
Failed: error 109 at offset 4: quantifier does not follow a repeatable item
/(a)(b)(c)\2/I
-Capturing subpattern count = 3
+Capture group count = 3
Max back reference = 2
First code unit = 'a'
Last code unit = 'c'
@@ -267,7 +267,7 @@ Matched, but too many substrings
3: c
/(a)bc|(a)(b)\2/I
-Capturing subpattern count = 3
+Capture group count = 3
Max back reference = 2
First code unit = 'a'
Subject length lower bound = 3
@@ -312,7 +312,7 @@ Matched, but too many substrings
3: b
/abc$/I,dollar_endonly
-Capturing subpattern count = 0
+Capture group count = 0
Options: dollar_endonly
First code unit = 'a'
Last code unit = 'c'
@@ -329,7 +329,7 @@ No match
Failed: error 115 at offset 16: reference to non-existent subpattern
/the quick brown fox/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 't'
Last code unit = 'x'
Subject length lower bound = 19
@@ -339,7 +339,7 @@ Subject length lower bound = 19
0: the quick brown fox
/the quick brown fox/I,anchored
-Capturing subpattern count = 0
+Capture group count = 0
Options: anchored
First code unit = 't'
Subject length lower bound = 19
@@ -353,7 +353,7 @@ No match
Failed: error 111 at offset 4: unrecognized character after (? or (?-
/^abc|def/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: a d
Subject length lower bound = 3
abcdef
@@ -362,7 +362,7 @@ Subject length lower bound = 3
0: def
/.*((abc)$|(def))/I
-Capturing subpattern count = 3
+Capture group count = 3
First code unit at start or follows newline
Subject length lower bound = 3
defabc
@@ -382,7 +382,7 @@ Failed: error 122 at offset 0: unmatched closing parenthesis
Failed: error 106 at offset 4: missing terminating ] for character class
/[^aeiou ]{3,}/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
\x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19
\x1a \x1b \x1c \x1d \x1e \x1f ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6
@@ -402,7 +402,7 @@ Subject length lower bound = 3
0: -pr
/<.*>/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = '<'
Last code unit = '>'
Subject length lower bound = 2
@@ -410,7 +410,7 @@ Subject length lower bound = 2
0: ghi
/<.*?>/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = '<'
Last code unit = '>'
Subject length lower bound = 2
@@ -418,7 +418,7 @@ Subject length lower bound = 2
0:
/<.*>/I,ungreedy
-Capturing subpattern count = 0
+Capture group count = 0
Options: ungreedy
First code unit = '<'
Last code unit = '>'
@@ -427,7 +427,7 @@ Subject length lower bound = 2
0:
/(?U)<.*>/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = '<'
Last code unit = '>'
Subject length lower bound = 2
@@ -435,7 +435,7 @@ Subject length lower bound = 2
0:
/<.*?>/I,ungreedy
-Capturing subpattern count = 0
+Capture group count = 0
Options: ungreedy
First code unit = '<'
Last code unit = '>'
@@ -444,7 +444,7 @@ Subject length lower bound = 2
0: ghi
/={3,}/I,ungreedy
-Capturing subpattern count = 0
+Capture group count = 0
Options: ungreedy
First code unit = '='
Last code unit = '='
@@ -453,7 +453,7 @@ Subject length lower bound = 3
0: ===
/(?U)={3,}?/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = '='
Last code unit = '='
Subject length lower bound = 3
@@ -461,7 +461,7 @@ Subject length lower bound = 3
0: ========
/(?
Overall options: anchored
First code unit = '1'
Subject length lower bound = 4
/(^b|(?i)^d)/I
-Capturing subpattern count = 1
+Capture group count = 1
Compile options:
Overall options: anchored
Starting code units: D b d
Subject length lower bound = 1
/(?s).*/I
-Capturing subpattern count = 0
+Capture group count = 0
May match empty string
Compile options:
Overall options: anchored
Subject length lower bound = 0
/[abcd]/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: a b c d
Subject length lower bound = 1
/(?i)[abcd]/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: A B C D a b c d
Subject length lower bound = 1
/(?m)[xy]|(b|c)/I
-Capturing subpattern count = 1
+Capture group count = 1
Starting code units: b c x y
Subject length lower bound = 1
/(^a|^b)/Im
-Capturing subpattern count = 1
+Capture group count = 1
Options: multiline
First code unit at start or follows newline
Subject length lower bound = 1
/(?i)(^a|^b)/Im
-Capturing subpattern count = 1
+Capture group count = 1
Options: multiline
First code unit at start or follows newline
Subject length lower bound = 1
/(a)(?(1)a|b|c)/
-Failed: error 127 at offset 3: conditional group contains more than two branches
+Failed: error 127 at offset 3: conditional subpattern contains more than two branches
/(?(?=a)a|b|c)/
-Failed: error 127 at offset 0: conditional group contains more than two branches
+Failed: error 127 at offset 0: conditional subpattern contains more than two branches
/(?(1a)/
Failed: error 124 at offset 4: missing closing parenthesis for condition
@@ -565,14 +565,14 @@ Failed: error 115 at offset 3: reference to non-existent subpattern
Failed: error 128 at offset 2: assertion expected after (?( or (?(?C)
/((?s)blah)\s+\1/I
-Capturing subpattern count = 1
+Capture group count = 1
Max back reference = 1
First code unit = 'b'
Last code unit = 'h'
Subject length lower bound = 9
/((?i)blah)\s+\1/I
-Capturing subpattern count = 1
+Capture group count = 1
Max back reference = 1
First code unit = 'b' (caseless)
Last code unit = 'h' (caseless)
@@ -587,17 +587,17 @@ Subject length lower bound = 9
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
First code unit = 'b' (caseless)
Subject length lower bound = 1
/(a*b|(?i:c*(?-i)d))/I
-Capturing subpattern count = 1
+Capture group count = 1
Starting code units: C a b c d
Subject length lower bound = 1
/a$/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Subject length lower bound = 1
a
@@ -611,7 +611,7 @@ No match
No match
/a$/Im
-Capturing subpattern count = 0
+Capture group count = 0
Options: multiline
First code unit = 'a'
Subject length lower bound = 1
@@ -626,7 +626,7 @@ Subject length lower bound = 1
No match
/\Aabc/Im
-Capturing subpattern count = 0
+Capture group count = 0
Max lookbehind = 1
Compile options: multiline
Overall options: anchored multiline
@@ -634,14 +634,14 @@ First code unit = 'a'
Subject length lower bound = 3
/^abc/Im
-Capturing subpattern count = 0
+Capture group count = 0
Options: multiline
First code unit at start or follows newline
Last code unit = 'c'
Subject length lower bound = 3
/^((a+)(?U)([ab]+)(?-U)([bc]+)(\w*))/I
-Capturing subpattern count = 5
+Capture group count = 5
Compile options:
Overall options: anchored
First code unit = 'a'
@@ -655,25 +655,25 @@ Subject length lower bound = 3
5: def
/(?<=foo)[ab]/I
-Capturing subpattern count = 0
+Capture group count = 0
Max lookbehind = 3
Starting code units: a b
Subject length lower bound = 1
/(?^abc)/Im
-Capturing subpattern count = 0
+Capture group count = 0
Options: multiline
First code unit at start or follows newline
Last code unit = 'c'
@@ -733,7 +733,7 @@ Failed: error 125 at offset 0: lookbehind assertion is not fixed length
/The next three are in testinput2 because they have variable length branches/
/(?<=bullock|donkey)-cart/I
-Capturing subpattern count = 0
+Capture group count = 0
Max lookbehind = 7
First code unit = '-'
Last code unit = 't'
@@ -749,13 +749,13 @@ No match
No match
/(?<=ab(?i)x|y|z)/I
-Capturing subpattern count = 0
+Capture group count = 0
Max lookbehind = 3
May match empty string
Subject length lower bound = 0
/(?>.*)(?<=(abcd)|(xyz))/I
-Capturing subpattern count = 2
+Capture group count = 2
Max lookbehind = 4
May match empty string
Subject length lower bound = 0
@@ -768,7 +768,7 @@ Subject length lower bound = 0
2: xyz
/(?<=ab(?i)x(?-i)y|(?i)z|b)ZZ/I
-Capturing subpattern count = 0
+Capture group count = 0
Max lookbehind = 4
First code unit = 'Z'
Last code unit = 'Z'
@@ -796,7 +796,7 @@ No match
No match
/(?
Overall options: anchored
-Starting code units: a
+First code unit = 'a'
Subject length lower bound = 4
\= Expect no match
aaaa
@@ -949,7 +949,7 @@ Failed: error 101 at offset 4: \ at end of pattern
Failed: error 101 at offset 4: \ at end of pattern
/(a)bc(d)/I
-Capturing subpattern count = 2
+Capture group count = 2
First code unit = 'a'
Last code unit = 'd'
Subject length lower bound = 4
@@ -969,7 +969,7 @@ Subject length lower bound = 4
Copy substring 5 failed (-49): unknown substring
/(.{20})/I
-Capturing subpattern count = 1
+Capture group count = 1
Subject length lower bound = 20
abcdefghijklmnopqrstuvwxyz
0: abcdefghijklmnopqrst
@@ -984,7 +984,7 @@ Subject length lower bound = 20
1G abcdefghijklmnopqrst (20)
/(.{15})/I
-Capturing subpattern count = 1
+Capture group count = 1
Subject length lower bound = 15
abcdefghijklmnopqrstuvwxyz
0: abcdefghijklmno
@@ -996,7 +996,7 @@ Subject length lower bound = 15
1G abcdefghijklmno (15)
/(.{16})/I
-Capturing subpattern count = 1
+Capture group count = 1
Subject length lower bound = 16
abcdefghijklmnopqrstuvwxyz
0: abcdefghijklmnop
@@ -1010,7 +1010,7 @@ Subject length lower bound = 16
1L abcdefghijklmnop
/^(a|(bc))de(f)/I
-Capturing subpattern count = 3
+Capture group count = 3
Compile options:
Overall options: anchored
Starting code units: a b
@@ -1049,7 +1049,7 @@ Get substring 4 failed (-49): unknown substring
0C adef (4)
/^abc\00def/I
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
First code unit = 'a'
@@ -1062,7 +1062,7 @@ Subject length lower bound = 7
/word ((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+
)((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+
)?)?)?)?)?)?)?)?)?otherword/I
-Capturing subpattern count = 8
+Capture group count = 8
Contains explicit CR or LF match
First code unit = 'w'
Last code unit = 'd'
@@ -1076,7 +1076,7 @@ Subject length lower bound = 14
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
First code unit at start or follows newline
Last code unit = 'X'
Subject length lower bound = 1
@@ -1089,7 +1089,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options: dotall
Overall options: anchored dotall
Last code unit = 'X'
@@ -1108,7 +1108,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
First code unit at start or follows newline
Subject length lower bound = 1
@@ -1125,7 +1125,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Compile options: dotall
Overall options: anchored dotall
Subject length lower bound = 1
@@ -1143,7 +1143,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 1
+Capture group count = 1
Compile options:
Overall options: anchored
Subject length lower bound = 1
@@ -1161,13 +1161,13 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
Subject length lower bound = 1
/\Biss\B/I,aftertext
-Capturing subpattern count = 0
+Capture group count = 0
Max lookbehind = 1
First code unit = 'i'
Last code unit = 's'
@@ -1177,7 +1177,7 @@ Subject length lower bound = 3
0+ issippi
/iss/I,aftertext,altglobal
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'i'
Last code unit = 's'
Subject length lower bound = 3
@@ -1188,7 +1188,7 @@ Subject length lower bound = 3
0+ ippi
/\Biss\B/I,aftertext,altglobal
-Capturing subpattern count = 0
+Capture group count = 0
Max lookbehind = 1
First code unit = 'i'
Last code unit = 's'
@@ -1198,7 +1198,7 @@ Subject length lower bound = 3
0+ issippi
/\Biss\B/Ig,aftertext
-Capturing subpattern count = 0
+Capture group count = 0
Max lookbehind = 1
First code unit = 'i'
Last code unit = 's'
@@ -1213,7 +1213,7 @@ Subject length lower bound = 3
No match
/(?<=[Ms])iss/Ig,aftertext
-Capturing subpattern count = 0
+Capture group count = 0
Max lookbehind = 1
First code unit = 'i'
Last code unit = 's'
@@ -1225,7 +1225,7 @@ Subject length lower bound = 3
0+ ippi
/(?<=[Ms])iss/I,aftertext,altglobal
-Capturing subpattern count = 0
+Capture group count = 0
Max lookbehind = 1
First code unit = 'i'
Last code unit = 's'
@@ -1235,7 +1235,7 @@ Subject length lower bound = 3
0+ issippi
/^iss/Ig,aftertext
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
First code unit = 'i'
@@ -1245,7 +1245,7 @@ Subject length lower bound = 3
0+ issippi
/.*iss/Ig,aftertext
-Capturing subpattern count = 0
+Capture group count = 0
First code unit at start or follows newline
Last code unit = 's'
Subject length lower bound = 3
@@ -1256,7 +1256,7 @@ Subject length lower bound = 3
0+ pqr
/.i./Ig,aftertext
-Capturing subpattern count = 0
+Capture group count = 0
Last code unit = 'i'
Subject length lower bound = 3
Mississippi
@@ -1285,7 +1285,7 @@ Subject length lower bound = 3
0+ souri river
/^.is/Ig,aftertext
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
Subject length lower bound = 3
@@ -1294,7 +1294,7 @@ Subject length lower bound = 3
0+ sissippi
/^ab\n/Ig,aftertext
-Capturing subpattern count = 0
+Capture group count = 0
Contains explicit CR or LF match
Compile options:
Overall options: anchored
@@ -1305,7 +1305,7 @@ Subject length lower bound = 3
0+ ab\x0acd
/^ab\n/Igm,aftertext
-Capturing subpattern count = 0
+Capture group count = 0
Contains explicit CR or LF match
Options: multiline
First code unit at start or follows newline
@@ -1329,238 +1329,238 @@ Subject length lower bound = 3
0+ xyz
/abc/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'c'
Subject length lower bound = 3
/abc|bac/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: a b
Last code unit = 'c'
Subject length lower bound = 3
/(abc|bac)/I
-Capturing subpattern count = 1
+Capture group count = 1
Starting code units: a b
Last code unit = 'c'
Subject length lower bound = 3
/(abc|(c|dc))/I
-Capturing subpattern count = 2
+Capture group count = 2
Starting code units: a c d
Last code unit = 'c'
Subject length lower bound = 1
/(abc|(d|de)c)/I
-Capturing subpattern count = 2
+Capture group count = 2
Starting code units: a d
Last code unit = 'c'
Subject length lower bound = 2
/a*/I
-Capturing subpattern count = 0
+Capture group count = 0
May match empty string
Subject length lower bound = 0
/a+/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Subject length lower bound = 1
/(baa|a+)/I
-Capturing subpattern count = 1
+Capture group count = 1
Starting code units: a b
Last code unit = 'a'
Subject length lower bound = 1
/a{0,3}/I
-Capturing subpattern count = 0
+Capture group count = 0
May match empty string
Subject length lower bound = 0
/baa{3,}/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'b'
Last code unit = 'a'
Subject length lower bound = 5
/"([^\\"]+|\\.)*"/I
-Capturing subpattern count = 1
+Capture group count = 1
First code unit = '"'
Last code unit = '"'
Subject length lower bound = 2
/(abc|ab[cd])/I
-Capturing subpattern count = 1
+Capture group count = 1
First code unit = 'a'
Subject length lower bound = 3
/(a|.)/I
-Capturing subpattern count = 1
+Capture group count = 1
Subject length lower bound = 1
/a|ba|\w/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P
Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z
Subject length lower bound = 1
/abc(?=pqr)/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'r'
Subject length lower bound = 3
/...(?<=abc)/I
-Capturing subpattern count = 0
+Capture group count = 0
Max lookbehind = 3
Subject length lower bound = 3
/abc(?!pqr)/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'c'
Subject length lower bound = 3
/ab./I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'b'
Subject length lower bound = 3
/ab[xyz]/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'b'
Subject length lower bound = 3
/abc*/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'b'
Subject length lower bound = 2
/ab.c*/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'b'
Subject length lower bound = 3
/a.c*/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Subject length lower bound = 2
/.c*/I
-Capturing subpattern count = 0
+Capture group count = 0
Subject length lower bound = 1
/ac*/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Subject length lower bound = 1
/(a.c*|b.c*)/I
-Capturing subpattern count = 1
+Capture group count = 1
Starting code units: a b
Subject length lower bound = 2
/a.c*|aba/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Subject length lower bound = 2
/.+a/I
-Capturing subpattern count = 0
+Capture group count = 0
Last code unit = 'a'
Subject length lower bound = 2
/(?=abcda)a.*/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'a'
-Subject length lower bound = 1
+Subject length lower bound = 2
/(?=a)a.*/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Subject length lower bound = 1
/a(b)*/I
-Capturing subpattern count = 1
+Capture group count = 1
First code unit = 'a'
Subject length lower bound = 1
/a\d*/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Subject length lower bound = 1
/ab\d*/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'b'
Subject length lower bound = 2
/a(\d)*/I
-Capturing subpattern count = 1
+Capture group count = 1
First code unit = 'a'
Subject length lower bound = 1
/abcde{0,0}/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'd'
Subject length lower bound = 4
/ab\d+/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'b'
Subject length lower bound = 3
/a(?(1)b)(.)/I
-Capturing subpattern count = 1
+Capture group count = 1
Max back reference = 1
First code unit = 'a'
Subject length lower bound = 2
/a(?(1)bag|big)(.)/I
-Capturing subpattern count = 1
+Capture group count = 1
Max back reference = 1
First code unit = 'a'
Last code unit = 'g'
Subject length lower bound = 5
/a(?(1)bag|big)*(.)/I
-Capturing subpattern count = 1
+Capture group count = 1
Max back reference = 1
First code unit = 'a'
Subject length lower bound = 2
/a(?(1)bag|big)+(.)/I
-Capturing subpattern count = 1
+Capture group count = 1
Max back reference = 1
First code unit = 'a'
Last code unit = 'g'
Subject length lower bound = 5
/a(?(1)b..|b..)(.)/I
-Capturing subpattern count = 1
+Capture group count = 1
Max back reference = 1
First code unit = 'a'
Last code unit = 'b'
Subject length lower bound = 5
/ab\d{0}e/I
-Capturing subpattern count = 0
+Capture group count = 0
First code unit = 'a'
Last code unit = 'e'
Subject length lower bound = 3
/a?b?/I
-Capturing subpattern count = 0
+Capture group count = 0
May match empty string
Subject length lower bound = 0
a
@@ -1576,7 +1576,7 @@ Subject length lower bound = 0
No match
/|-/I
-Capturing subpattern count = 0
+Capture group count = 0
May match empty string
Subject length lower bound = 0
abcd
@@ -1590,7 +1590,7 @@ Subject length lower bound = 0
No match
/^.?abcd/I
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
Last code unit = 'd'
@@ -1604,7 +1604,7 @@ Subject length lower bound = 4
)* # Zero or more contents
\) # Closing )
/Ix
-Capturing subpattern count = 0
+Capture group count = 0
Options: extended
First code unit = '('
Last code unit = ')'
@@ -1632,7 +1632,7 @@ No match
No match
/\( ( (?>[^()]+) | (?R) )* \) /Igx
-Capturing subpattern count = 1
+Capture group count = 1
Options: extended
First code unit = '('
Last code unit = ')'
@@ -1647,7 +1647,7 @@ Subject length lower bound = 2
1: z
/\( (?: (?>[^()]+) | (?R) ) \) /Ix
-Capturing subpattern count = 0
+Capture group count = 0
Options: extended
First code unit = '('
Last code unit = ')'
@@ -1665,7 +1665,7 @@ Subject length lower bound = 3
No match
/\( (?: (?>[^()]+) | (?R) )? \) /Ix
-Capturing subpattern count = 0
+Capture group count = 0
Options: extended
First code unit = '('
Last code unit = ')'
@@ -1676,7 +1676,7 @@ Subject length lower bound = 2
0: (fsh)
/\( ( (?>[^()]+) | (?R) )* \) /Ix
-Capturing subpattern count = 1
+Capture group count = 1
Options: extended
First code unit = '('
Last code unit = ')'
@@ -1686,7 +1686,7 @@ Subject length lower bound = 2
1: cd
/\( ( ( (?>[^()]+) | (?R) )* ) \) /Ix
-Capturing subpattern count = 2
+Capture group count = 2
Options: extended
First code unit = '('
Last code unit = ')'
@@ -1697,7 +1697,7 @@ Subject length lower bound = 2
2: cd
/\( (123)? ( ( (?>[^()]+) | (?R) )* ) \) /Ix
-Capturing subpattern count = 3
+Capture group count = 3
Options: extended
First code unit = '('
Last code unit = ')'
@@ -1714,7 +1714,7 @@ Subject length lower bound = 2
3: cd
/\( ( (123)? ( (?>[^()]+) | (?R) )* ) \) /Ix
-Capturing subpattern count = 3
+Capture group count = 3
Options: extended
First code unit = '('
Last code unit = ')'
@@ -1731,7 +1731,7 @@ Subject length lower bound = 2
3: cd
/\( (((((((((( ( (?>[^()]+) | (?R) )* )))))))))) \) /Ix
-Capturing subpattern count = 11
+Capture group count = 11
Options: extended
First code unit = '('
Last code unit = ')'
@@ -1751,7 +1751,7 @@ Subject length lower bound = 2
11: cd
/\( ( ( (?>[^()<>]+) | ((?>[^()]+)) | (?R) )* ) \) /Ix
-Capturing subpattern count = 3
+Capture group count = 3
Options: extended
First code unit = '('
Last code unit = ')'
@@ -1762,7 +1762,7 @@ Subject length lower bound = 2
2: 123
/\( ( ( (?>[^()]+) | ((?R)) )* ) \) /Ix
-Capturing subpattern count = 3
+Capture group count = 3
Options: extended
First code unit = '('
Last code unit = ')'
@@ -1786,7 +1786,7 @@ Subject length lower bound = 2
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
Starting code units: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P
@@ -1801,7 +1801,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
@@ -1826,7 +1826,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
Starting code units: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
@@ -1841,7 +1841,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
@@ -1860,7 +1860,7 @@ Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
Subject length lower bound = 1
/[_[:alpha:]]/I
-Capturing subpattern count = 0
+Capture group count = 0
Starting code units: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
_ a b c d e f g h i j k l m n o p q r s t u v w x y z
Subject length lower bound = 1
@@ -1873,7 +1873,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
@@ -1892,7 +1892,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
Starting code units: \x80 \x81 \x82 \x83 \x84 \x85 \x86 \x87 \x88 \x89 \x8a
@@ -1914,7 +1914,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
Starting code units: \x09 \x20
@@ -1928,7 +1928,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0a \x0b
@@ -1948,7 +1948,7 @@ Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0a \x0b
Subject length lower bound = 1
/[\n\x0b\x0c\x0d[:blank:]]/I
-Capturing subpattern count = 0
+Capture group count = 0
Contains explicit CR or LF match
Starting code units: \x09 \x0a \x0b \x0c \x0d \x20
Subject length lower bound = 1
@@ -1961,7 +1961,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
Starting code units: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a
@@ -1977,7 +1977,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
Starting code units: 0 1 2 3 4 5 6 7 8 9
@@ -1991,7 +1991,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options:
Overall options: anchored
Starting code units: ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 :
@@ -2007,7 +2007,7 @@ Subject length lower bound = 1
Ket
End
------------------------------------------------------------------
-Capturing subpattern count = 0
+Capture group count = 0
Compile options: