summaryrefslogtreecommitdiff
path: root/plugins/Pcre16/src
diff options
context:
space:
mode:
authorKirill Volinsky <mataes2007@gmail.com>2014-08-02 14:17:32 +0000
committerKirill Volinsky <mataes2007@gmail.com>2014-08-02 14:17:32 +0000
commit844c971d8aeb2693bc01739963f5da675b989d03 (patch)
treee32898f45b61f668ad805fdb4e9c9c2ea50c43bd /plugins/Pcre16/src
parentad8bc05808c6d1f45fb1d62500b4b30f0d654ed7 (diff)
added pcre16 project
git-svn-id: http://svn.miranda-ng.org/main/trunk@10019 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/Pcre16/src')
-rw-r--r--plugins/Pcre16/src/config.h57
-rw-r--r--plugins/Pcre16/src/pcre.h677
-rw-r--r--plugins/Pcre16/src/pcre16_byte_order.c45
-rw-r--r--plugins/Pcre16/src/pcre16_chartables.c45
-rw-r--r--plugins/Pcre16/src/pcre16_compile.c45
-rw-r--r--plugins/Pcre16/src/pcre16_config.c45
-rw-r--r--plugins/Pcre16/src/pcre16_dfa_exec.c45
-rw-r--r--plugins/Pcre16/src/pcre16_exec.c45
-rw-r--r--plugins/Pcre16/src/pcre16_fullinfo.c45
-rw-r--r--plugins/Pcre16/src/pcre16_get.c45
-rw-r--r--plugins/Pcre16/src/pcre16_globals.c45
-rw-r--r--plugins/Pcre16/src/pcre16_jit_compile.c45
-rw-r--r--plugins/Pcre16/src/pcre16_maketables.c45
-rw-r--r--plugins/Pcre16/src/pcre16_newline.c45
-rw-r--r--plugins/Pcre16/src/pcre16_ord2utf16.c90
-rw-r--r--plugins/Pcre16/src/pcre16_printint.c45
-rw-r--r--plugins/Pcre16/src/pcre16_refcount.c45
-rw-r--r--plugins/Pcre16/src/pcre16_string_utils.c45
-rw-r--r--plugins/Pcre16/src/pcre16_study.c45
-rw-r--r--plugins/Pcre16/src/pcre16_tables.c45
-rw-r--r--plugins/Pcre16/src/pcre16_ucd.c45
-rw-r--r--plugins/Pcre16/src/pcre16_utf16_utils.c130
-rw-r--r--plugins/Pcre16/src/pcre16_valid_utf16.c137
-rw-r--r--plugins/Pcre16/src/pcre16_version.c45
-rw-r--r--plugins/Pcre16/src/pcre16_xclass.c45
-rw-r--r--plugins/Pcre16/src/pcre_byte_order.c319
-rw-r--r--plugins/Pcre16/src/pcre_chartables.c198
-rw-r--r--plugins/Pcre16/src/pcre_compile.c9484
-rw-r--r--plugins/Pcre16/src/pcre_config.c190
-rw-r--r--plugins/Pcre16/src/pcre_dfa_exec.c3673
-rw-r--r--plugins/Pcre16/src/pcre_exec.c7178
-rw-r--r--plugins/Pcre16/src/pcre_fullinfo.c245
-rw-r--r--plugins/Pcre16/src/pcre_get.c662
-rw-r--r--plugins/Pcre16/src/pcre_globals.c86
-rw-r--r--plugins/Pcre16/src/pcre_internal.h2781
-rw-r--r--plugins/Pcre16/src/pcre_jit_compile.c10701
-rw-r--r--plugins/Pcre16/src/pcre_maketables.c156
-rw-r--r--plugins/Pcre16/src/pcre_newline.c210
-rw-r--r--plugins/Pcre16/src/pcre_refcount.c92
-rw-r--r--plugins/Pcre16/src/pcre_string_utils.c211
-rw-r--r--plugins/Pcre16/src/pcre_study.c1626
-rw-r--r--plugins/Pcre16/src/pcre_tables.c658
-rw-r--r--plugins/Pcre16/src/pcre_ucd.c3297
-rw-r--r--plugins/Pcre16/src/pcre_version.c98
-rw-r--r--plugins/Pcre16/src/pcre_xclass.c268
-rw-r--r--plugins/Pcre16/src/ucp.h200
46 files changed, 44324 insertions, 0 deletions
diff --git a/plugins/Pcre16/src/config.h b/plugins/Pcre16/src/config.h
new file mode 100644
index 0000000000..d1e35175fe
--- /dev/null
+++ b/plugins/Pcre16/src/config.h
@@ -0,0 +1,57 @@
+/* config.h for CMake builds */
+
+/* #undef HAVE_DIRENT_H */
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TYPES_H 1
+/* #undef HAVE_UNISTD_H */
+#define HAVE_WINDOWS_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_INTTYPES_H 1
+
+/* #undef HAVE_TYPE_TRAITS_H */
+/* #undef HAVE_BITS_TYPE_TRAITS_H */
+
+/* #undef HAVE_BCOPY */
+#define HAVE_MEMMOVE 1
+#define HAVE_STRERROR 1
+#define HAVE_STRTOLL 1
+/* #undef HAVE_STRTOQ */
+#define HAVE__STRTOI64 1
+
+/* #undef PCRE_STATIC */
+
+/* #undef SUPPORT_PCRE8 */
+#define SUPPORT_PCRE16 1
+/* #undef SUPPORT_PCRE32 */
+/* #undef SUPPORT_JIT */
+/* #undef SUPPORT_PCREGREP_JIT */
+/* #undef SUPPORT_UTF */
+/* #undef SUPPORT_UCP */
+/* #undef EBCDIC */
+/* #undef EBCDIC_NL25 */
+/* #undef BSR_ANYCRLF */
+/* #undef NO_RECURSE */
+
+#define HAVE_LONG_LONG 1
+#define HAVE_UNSIGNED_LONG_LONG 1
+
+/* #undef SUPPORT_LIBBZ2 */
+/* #undef SUPPORT_LIBZ */
+/* #undef SUPPORT_LIBEDIT */
+/* #undef SUPPORT_LIBREADLINE */
+
+/* #undef SUPPORT_VALGRIND */
+/* #undef SUPPORT_GCOV */
+
+#define NEWLINE 10
+#define POSIX_MALLOC_THRESHOLD 10
+#define LINK_SIZE 2
+#define PARENS_NEST_LIMIT 250
+#define MATCH_LIMIT 10000000
+#define MATCH_LIMIT_RECURSION MATCH_LIMIT
+#define PCREGREP_BUFSIZE 20480
+
+#define MAX_NAME_SIZE 32
+#define MAX_NAME_COUNT 10000
+
+/* end config.h for CMake builds */
diff --git a/plugins/Pcre16/src/pcre.h b/plugins/Pcre16/src/pcre.h
new file mode 100644
index 0000000000..7fcea56f4c
--- /dev/null
+++ b/plugins/Pcre16/src/pcre.h
@@ -0,0 +1,677 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* This is the public header file for the PCRE library, to be #included by
+applications that call the PCRE functions.
+
+ Copyright (c) 1997-2014 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.
+-----------------------------------------------------------------------------
+*/
+
+#ifndef _PCRE_H
+#define _PCRE_H
+
+/* The current PCRE version information. */
+
+#define PCRE_MAJOR 8
+#define PCRE_MINOR 35
+#define PCRE_PRERELEASE
+#define PCRE_DATE 2014-04-04
+
+/* When an application links to a PCRE DLL in Windows, the symbols that are
+imported have to be identified as such. When building PCRE, the appropriate
+export setting is defined in pcre_internal.h, which includes this file. So we
+don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL. */
+
+#if defined(_WIN32) && !defined(PCRE_STATIC)
+# ifndef PCRE_EXP_DECL
+# define PCRE_EXP_DECL extern __declspec(dllimport)
+# endif
+# ifdef __cplusplus
+# ifndef PCRECPP_EXP_DECL
+# define PCRECPP_EXP_DECL extern __declspec(dllimport)
+# endif
+# ifndef PCRECPP_EXP_DEFN
+# define PCRECPP_EXP_DEFN __declspec(dllimport)
+# endif
+# endif
+#endif
+
+/* By default, we use the standard "extern" declarations. */
+
+#ifndef PCRE_EXP_DECL
+# ifdef __cplusplus
+# define PCRE_EXP_DECL extern "C"
+# else
+# define PCRE_EXP_DECL extern
+# endif
+#endif
+
+#ifdef __cplusplus
+# ifndef PCRECPP_EXP_DECL
+# define PCRECPP_EXP_DECL extern
+# endif
+# ifndef PCRECPP_EXP_DEFN
+# define PCRECPP_EXP_DEFN
+# endif
+#endif
+
+/* Have to include stdlib.h in order to ensure that size_t is defined;
+it is needed here for malloc. */
+
+#include <stdlib.h>
+
+/* Allow for C++ users */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Public options. Some are compile-time only, some are run-time only, and some
+are both. Most of the compile-time options are saved with the compiled regex so
+that they can be inspected during studying (and therefore JIT compiling). Note
+that pcre_study() has its own set of options. Originally, all the options
+defined here used distinct bits. However, almost all the bits in a 32-bit word
+are now used, so in order to conserve them, option bits that were previously
+only recognized at matching time (i.e. by pcre_exec() or pcre_dfa_exec()) may
+also be used for compile-time options that affect only compiling and are not
+relevant for studying or JIT compiling.
+
+Some options for pcre_compile() change its behaviour but do not affect the
+behaviour of the execution functions. Other options are passed through to the
+execution functions and affect their behaviour, with or without affecting the
+behaviour of pcre_compile().
+
+Options that can be passed to pcre_compile() are tagged Cx below, with these
+variants:
+
+C1 Affects compile only
+C2 Does not affect compile; affects exec, dfa_exec
+C3 Affects compile, exec, dfa_exec
+C4 Affects compile, exec, dfa_exec, study
+C5 Affects compile, exec, study
+
+Options that can be set for pcre_exec() and/or pcre_dfa_exec() are flagged with
+E and D, respectively. They take precedence over C3, C4, and C5 settings passed
+from pcre_compile(). Those that are compatible with JIT execution are flagged
+with J. */
+
+#define PCRE_CASELESS 0x00000001 /* C1 */
+#define PCRE_MULTILINE 0x00000002 /* C1 */
+#define PCRE_DOTALL 0x00000004 /* C1 */
+#define PCRE_EXTENDED 0x00000008 /* C1 */
+#define PCRE_ANCHORED 0x00000010 /* C4 E D */
+#define PCRE_DOLLAR_ENDONLY 0x00000020 /* C2 */
+#define PCRE_EXTRA 0x00000040 /* C1 */
+#define PCRE_NOTBOL 0x00000080 /* E D J */
+#define PCRE_NOTEOL 0x00000100 /* E D J */
+#define PCRE_UNGREEDY 0x00000200 /* C1 */
+#define PCRE_NOTEMPTY 0x00000400 /* E D J */
+#define PCRE_UTF8 0x00000800 /* C4 ) */
+#define PCRE_UTF16 0x00000800 /* C4 ) Synonyms */
+#define PCRE_UTF32 0x00000800 /* C4 ) */
+#define PCRE_NO_AUTO_CAPTURE 0x00001000 /* C1 */
+#define PCRE_NO_UTF8_CHECK 0x00002000 /* C1 E D J ) */
+#define PCRE_NO_UTF16_CHECK 0x00002000 /* C1 E D J ) Synonyms */
+#define PCRE_NO_UTF32_CHECK 0x00002000 /* C1 E D J ) */
+#define PCRE_AUTO_CALLOUT 0x00004000 /* C1 */
+#define PCRE_PARTIAL_SOFT 0x00008000 /* E D J ) Synonyms */
+#define PCRE_PARTIAL 0x00008000 /* E D J ) */
+
+/* This pair use the same bit. */
+#define PCRE_NEVER_UTF 0x00010000 /* C1 ) Overlaid */
+#define PCRE_DFA_SHORTEST 0x00010000 /* D ) Overlaid */
+
+/* This pair use the same bit. */
+#define PCRE_NO_AUTO_POSSESS 0x00020000 /* C1 ) Overlaid */
+#define PCRE_DFA_RESTART 0x00020000 /* D ) Overlaid */
+
+#define PCRE_FIRSTLINE 0x00040000 /* C3 */
+#define PCRE_DUPNAMES 0x00080000 /* C1 */
+#define PCRE_NEWLINE_CR 0x00100000 /* C3 E D */
+#define PCRE_NEWLINE_LF 0x00200000 /* C3 E D */
+#define PCRE_NEWLINE_CRLF 0x00300000 /* C3 E D */
+#define PCRE_NEWLINE_ANY 0x00400000 /* C3 E D */
+#define PCRE_NEWLINE_ANYCRLF 0x00500000 /* C3 E D */
+#define PCRE_BSR_ANYCRLF 0x00800000 /* C3 E D */
+#define PCRE_BSR_UNICODE 0x01000000 /* C3 E D */
+#define PCRE_JAVASCRIPT_COMPAT 0x02000000 /* C5 */
+#define PCRE_NO_START_OPTIMIZE 0x04000000 /* C2 E D ) Synonyms */
+#define PCRE_NO_START_OPTIMISE 0x04000000 /* C2 E D ) */
+#define PCRE_PARTIAL_HARD 0x08000000 /* E D J */
+#define PCRE_NOTEMPTY_ATSTART 0x10000000 /* E D J */
+#define PCRE_UCP 0x20000000 /* C3 */
+
+/* Exec-time and get/set-time error codes */
+
+#define PCRE_ERROR_NOMATCH (-1)
+#define PCRE_ERROR_NULL (-2)
+#define PCRE_ERROR_BADOPTION (-3)
+#define PCRE_ERROR_BADMAGIC (-4)
+#define PCRE_ERROR_UNKNOWN_OPCODE (-5)
+#define PCRE_ERROR_UNKNOWN_NODE (-5) /* For backward compatibility */
+#define PCRE_ERROR_NOMEMORY (-6)
+#define PCRE_ERROR_NOSUBSTRING (-7)
+#define PCRE_ERROR_MATCHLIMIT (-8)
+#define PCRE_ERROR_CALLOUT (-9) /* Never used by PCRE itself */
+#define PCRE_ERROR_BADUTF8 (-10) /* Same for 8/16/32 */
+#define PCRE_ERROR_BADUTF16 (-10) /* Same for 8/16/32 */
+#define PCRE_ERROR_BADUTF32 (-10) /* Same for 8/16/32 */
+#define PCRE_ERROR_BADUTF8_OFFSET (-11) /* Same for 8/16 */
+#define PCRE_ERROR_BADUTF16_OFFSET (-11) /* Same for 8/16 */
+#define PCRE_ERROR_PARTIAL (-12)
+#define PCRE_ERROR_BADPARTIAL (-13)
+#define PCRE_ERROR_INTERNAL (-14)
+#define PCRE_ERROR_BADCOUNT (-15)
+#define PCRE_ERROR_DFA_UITEM (-16)
+#define PCRE_ERROR_DFA_UCOND (-17)
+#define PCRE_ERROR_DFA_UMLIMIT (-18)
+#define PCRE_ERROR_DFA_WSSIZE (-19)
+#define PCRE_ERROR_DFA_RECURSE (-20)
+#define PCRE_ERROR_RECURSIONLIMIT (-21)
+#define PCRE_ERROR_NULLWSLIMIT (-22) /* No longer actually used */
+#define PCRE_ERROR_BADNEWLINE (-23)
+#define PCRE_ERROR_BADOFFSET (-24)
+#define PCRE_ERROR_SHORTUTF8 (-25)
+#define PCRE_ERROR_SHORTUTF16 (-25) /* Same for 8/16 */
+#define PCRE_ERROR_RECURSELOOP (-26)
+#define PCRE_ERROR_JIT_STACKLIMIT (-27)
+#define PCRE_ERROR_BADMODE (-28)
+#define PCRE_ERROR_BADENDIANNESS (-29)
+#define PCRE_ERROR_DFA_BADRESTART (-30)
+#define PCRE_ERROR_JIT_BADOPTION (-31)
+#define PCRE_ERROR_BADLENGTH (-32)
+#define PCRE_ERROR_UNSET (-33)
+
+/* Specific error codes for UTF-8 validity checks */
+
+#define PCRE_UTF8_ERR0 0
+#define PCRE_UTF8_ERR1 1
+#define PCRE_UTF8_ERR2 2
+#define PCRE_UTF8_ERR3 3
+#define PCRE_UTF8_ERR4 4
+#define PCRE_UTF8_ERR5 5
+#define PCRE_UTF8_ERR6 6
+#define PCRE_UTF8_ERR7 7
+#define PCRE_UTF8_ERR8 8
+#define PCRE_UTF8_ERR9 9
+#define PCRE_UTF8_ERR10 10
+#define PCRE_UTF8_ERR11 11
+#define PCRE_UTF8_ERR12 12
+#define PCRE_UTF8_ERR13 13
+#define PCRE_UTF8_ERR14 14
+#define PCRE_UTF8_ERR15 15
+#define PCRE_UTF8_ERR16 16
+#define PCRE_UTF8_ERR17 17
+#define PCRE_UTF8_ERR18 18
+#define PCRE_UTF8_ERR19 19
+#define PCRE_UTF8_ERR20 20
+#define PCRE_UTF8_ERR21 21
+#define PCRE_UTF8_ERR22 22 /* Unused (was non-character) */
+
+/* Specific error codes for UTF-16 validity checks */
+
+#define PCRE_UTF16_ERR0 0
+#define PCRE_UTF16_ERR1 1
+#define PCRE_UTF16_ERR2 2
+#define PCRE_UTF16_ERR3 3
+#define PCRE_UTF16_ERR4 4 /* Unused (was non-character) */
+
+/* Specific error codes for UTF-32 validity checks */
+
+#define PCRE_UTF32_ERR0 0
+#define PCRE_UTF32_ERR1 1
+#define PCRE_UTF32_ERR2 2 /* Unused (was non-character) */
+#define PCRE_UTF32_ERR3 3
+
+/* Request types for pcre_fullinfo() */
+
+#define PCRE_INFO_OPTIONS 0
+#define PCRE_INFO_SIZE 1
+#define PCRE_INFO_CAPTURECOUNT 2
+#define PCRE_INFO_BACKREFMAX 3
+#define PCRE_INFO_FIRSTBYTE 4
+#define PCRE_INFO_FIRSTCHAR 4 /* For backwards compatibility */
+#define PCRE_INFO_FIRSTTABLE 5
+#define PCRE_INFO_LASTLITERAL 6
+#define PCRE_INFO_NAMEENTRYSIZE 7
+#define PCRE_INFO_NAMECOUNT 8
+#define PCRE_INFO_NAMETABLE 9
+#define PCRE_INFO_STUDYSIZE 10
+#define PCRE_INFO_DEFAULT_TABLES 11
+#define PCRE_INFO_OKPARTIAL 12
+#define PCRE_INFO_JCHANGED 13
+#define PCRE_INFO_HASCRORLF 14
+#define PCRE_INFO_MINLENGTH 15
+#define PCRE_INFO_JIT 16
+#define PCRE_INFO_JITSIZE 17
+#define PCRE_INFO_MAXLOOKBEHIND 18
+#define PCRE_INFO_FIRSTCHARACTER 19
+#define PCRE_INFO_FIRSTCHARACTERFLAGS 20
+#define PCRE_INFO_REQUIREDCHAR 21
+#define PCRE_INFO_REQUIREDCHARFLAGS 22
+#define PCRE_INFO_MATCHLIMIT 23
+#define PCRE_INFO_RECURSIONLIMIT 24
+#define PCRE_INFO_MATCH_EMPTY 25
+
+/* Request types for pcre_config(). Do not re-arrange, in order to remain
+compatible. */
+
+#define PCRE_CONFIG_UTF8 0
+#define PCRE_CONFIG_NEWLINE 1
+#define PCRE_CONFIG_LINK_SIZE 2
+#define PCRE_CONFIG_POSIX_MALLOC_THRESHOLD 3
+#define PCRE_CONFIG_MATCH_LIMIT 4
+#define PCRE_CONFIG_STACKRECURSE 5
+#define PCRE_CONFIG_UNICODE_PROPERTIES 6
+#define PCRE_CONFIG_MATCH_LIMIT_RECURSION 7
+#define PCRE_CONFIG_BSR 8
+#define PCRE_CONFIG_JIT 9
+#define PCRE_CONFIG_UTF16 10
+#define PCRE_CONFIG_JITTARGET 11
+#define PCRE_CONFIG_UTF32 12
+#define PCRE_CONFIG_PARENS_LIMIT 13
+
+/* Request types for pcre_study(). Do not re-arrange, in order to remain
+compatible. */
+
+#define PCRE_STUDY_JIT_COMPILE 0x0001
+#define PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE 0x0002
+#define PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE 0x0004
+#define PCRE_STUDY_EXTRA_NEEDED 0x0008
+
+/* Bit flags for the pcre[16|32]_extra structure. Do not re-arrange or redefine
+these bits, just add new ones on the end, in order to remain compatible. */
+
+#define PCRE_EXTRA_STUDY_DATA 0x0001
+#define PCRE_EXTRA_MATCH_LIMIT 0x0002
+#define PCRE_EXTRA_CALLOUT_DATA 0x0004
+#define PCRE_EXTRA_TABLES 0x0008
+#define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0x0010
+#define PCRE_EXTRA_MARK 0x0020
+#define PCRE_EXTRA_EXECUTABLE_JIT 0x0040
+
+/* Types */
+
+struct real_pcre; /* declaration; the definition is private */
+typedef struct real_pcre pcre;
+
+struct real_pcre16; /* declaration; the definition is private */
+typedef struct real_pcre16 pcre16;
+
+struct real_pcre32; /* declaration; the definition is private */
+typedef struct real_pcre32 pcre32;
+
+struct real_pcre_jit_stack; /* declaration; the definition is private */
+typedef struct real_pcre_jit_stack pcre_jit_stack;
+
+struct real_pcre16_jit_stack; /* declaration; the definition is private */
+typedef struct real_pcre16_jit_stack pcre16_jit_stack;
+
+struct real_pcre32_jit_stack; /* declaration; the definition is private */
+typedef struct real_pcre32_jit_stack pcre32_jit_stack;
+
+/* If PCRE is compiled with 16 bit character support, PCRE_UCHAR16 must contain
+a 16 bit wide signed data type. Otherwise it can be a dummy data type since
+pcre16 functions are not implemented. There is a check for this in pcre_internal.h. */
+#ifndef PCRE_UCHAR16
+#define PCRE_UCHAR16 unsigned short
+#endif
+
+#ifndef PCRE_SPTR16
+#define PCRE_SPTR16 const PCRE_UCHAR16 *
+#endif
+
+/* If PCRE is compiled with 32 bit character support, PCRE_UCHAR32 must contain
+a 32 bit wide signed data type. Otherwise it can be a dummy data type since
+pcre32 functions are not implemented. There is a check for this in pcre_internal.h. */
+#ifndef PCRE_UCHAR32
+#define PCRE_UCHAR32 unsigned int
+#endif
+
+#ifndef PCRE_SPTR32
+#define PCRE_SPTR32 const PCRE_UCHAR32 *
+#endif
+
+/* When PCRE is compiled as a C++ library, the subject pointer type can be
+replaced with a custom type. For conventional use, the public interface is a
+const char *. */
+
+#ifndef PCRE_SPTR
+#define PCRE_SPTR const char *
+#endif
+
+/* The structure for passing additional data to pcre_exec(). This is defined in
+such as way as to be extensible. Always add new fields at the end, in order to
+remain compatible. */
+
+typedef struct pcre_extra {
+ unsigned long int flags; /* Bits for which fields are set */
+ void *study_data; /* Opaque data from pcre_study() */
+ unsigned long int match_limit; /* Maximum number of calls to match() */
+ void *callout_data; /* Data passed back in callouts */
+ const unsigned char *tables; /* Pointer to character tables */
+ unsigned long int match_limit_recursion; /* Max recursive calls to match() */
+ unsigned char **mark; /* For passing back a mark pointer */
+ void *executable_jit; /* Contains a pointer to a compiled jit code */
+} pcre_extra;
+
+/* Same structure as above, but with 16 bit char pointers. */
+
+typedef struct pcre16_extra {
+ unsigned long int flags; /* Bits for which fields are set */
+ void *study_data; /* Opaque data from pcre_study() */
+ unsigned long int match_limit; /* Maximum number of calls to match() */
+ void *callout_data; /* Data passed back in callouts */
+ const unsigned char *tables; /* Pointer to character tables */
+ unsigned long int match_limit_recursion; /* Max recursive calls to match() */
+ PCRE_UCHAR16 **mark; /* For passing back a mark pointer */
+ void *executable_jit; /* Contains a pointer to a compiled jit code */
+} pcre16_extra;
+
+/* Same structure as above, but with 32 bit char pointers. */
+
+typedef struct pcre32_extra {
+ unsigned long int flags; /* Bits for which fields are set */
+ void *study_data; /* Opaque data from pcre_study() */
+ unsigned long int match_limit; /* Maximum number of calls to match() */
+ void *callout_data; /* Data passed back in callouts */
+ const unsigned char *tables; /* Pointer to character tables */
+ unsigned long int match_limit_recursion; /* Max recursive calls to match() */
+ PCRE_UCHAR32 **mark; /* For passing back a mark pointer */
+ void *executable_jit; /* Contains a pointer to a compiled jit code */
+} pcre32_extra;
+
+/* 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. */
+
+typedef struct pcre_callout_block {
+ int version; /* Identifies version of block */
+ /* ------------------------ Version 0 ------------------------------- */
+ int callout_number; /* Number compiled into pattern */
+ int *offset_vector; /* The offset vector */
+ PCRE_SPTR subject; /* The subject being matched */
+ int subject_length; /* The length of the subject */
+ int start_match; /* Offset to start of this match attempt */
+ int current_position; /* Where we currently are in the subject */
+ int capture_top; /* Max current capture */
+ int capture_last; /* Most recently closed capture */
+ void *callout_data; /* Data passed in with the call */
+ /* ------------------- Added for Version 1 -------------------------- */
+ int pattern_position; /* Offset to next item in the pattern */
+ int next_item_length; /* Length of next item in the pattern */
+ /* ------------------- Added for Version 2 -------------------------- */
+ const unsigned char *mark; /* Pointer to current mark or NULL */
+ /* ------------------------------------------------------------------ */
+} pcre_callout_block;
+
+/* Same structure as above, but with 16 bit char pointers. */
+
+typedef struct pcre16_callout_block {
+ int version; /* Identifies version of block */
+ /* ------------------------ Version 0 ------------------------------- */
+ int callout_number; /* Number compiled into pattern */
+ int *offset_vector; /* The offset vector */
+ PCRE_SPTR16 subject; /* The subject being matched */
+ int subject_length; /* The length of the subject */
+ int start_match; /* Offset to start of this match attempt */
+ int current_position; /* Where we currently are in the subject */
+ int capture_top; /* Max current capture */
+ int capture_last; /* Most recently closed capture */
+ void *callout_data; /* Data passed in with the call */
+ /* ------------------- Added for Version 1 -------------------------- */
+ int pattern_position; /* Offset to next item in the pattern */
+ int next_item_length; /* Length of next item in the pattern */
+ /* ------------------- Added for Version 2 -------------------------- */
+ const PCRE_UCHAR16 *mark; /* Pointer to current mark or NULL */
+ /* ------------------------------------------------------------------ */
+} pcre16_callout_block;
+
+/* Same structure as above, but with 32 bit char pointers. */
+
+typedef struct pcre32_callout_block {
+ int version; /* Identifies version of block */
+ /* ------------------------ Version 0 ------------------------------- */
+ int callout_number; /* Number compiled into pattern */
+ int *offset_vector; /* The offset vector */
+ PCRE_SPTR32 subject; /* The subject being matched */
+ int subject_length; /* The length of the subject */
+ int start_match; /* Offset to start of this match attempt */
+ int current_position; /* Where we currently are in the subject */
+ int capture_top; /* Max current capture */
+ int capture_last; /* Most recently closed capture */
+ void *callout_data; /* Data passed in with the call */
+ /* ------------------- Added for Version 1 -------------------------- */
+ int pattern_position; /* Offset to next item in the pattern */
+ int next_item_length; /* Length of next item in the pattern */
+ /* ------------------- Added for Version 2 -------------------------- */
+ const PCRE_UCHAR32 *mark; /* Pointer to current mark or NULL */
+ /* ------------------------------------------------------------------ */
+} pcre32_callout_block;
+
+/* Indirection for store get and free functions. These can be set to
+alternative malloc/free functions if required. Special ones are used in the
+non-recursive case for "frames". There is also an optional callout function
+that is triggered by the (?) regex item. For Virtual Pascal, these definitions
+have to take another form. */
+
+#ifndef VPCOMPAT
+PCRE_EXP_DECL void *(*pcre_malloc)(size_t);
+PCRE_EXP_DECL void (*pcre_free)(void *);
+PCRE_EXP_DECL void *(*pcre_stack_malloc)(size_t);
+PCRE_EXP_DECL void (*pcre_stack_free)(void *);
+PCRE_EXP_DECL int (*pcre_callout)(pcre_callout_block *);
+PCRE_EXP_DECL int (*pcre_stack_guard)(void);
+
+PCRE_EXP_DECL void *(*pcre16_malloc)(size_t);
+PCRE_EXP_DECL void (*pcre16_free)(void *);
+PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t);
+PCRE_EXP_DECL void (*pcre16_stack_free)(void *);
+PCRE_EXP_DECL int (*pcre16_callout)(pcre16_callout_block *);
+PCRE_EXP_DECL int (*pcre16_stack_guard)(void);
+
+PCRE_EXP_DECL void *(*pcre32_malloc)(size_t);
+PCRE_EXP_DECL void (*pcre32_free)(void *);
+PCRE_EXP_DECL void *(*pcre32_stack_malloc)(size_t);
+PCRE_EXP_DECL void (*pcre32_stack_free)(void *);
+PCRE_EXP_DECL int (*pcre32_callout)(pcre32_callout_block *);
+PCRE_EXP_DECL int (*pcre32_stack_guard)(void);
+#else /* VPCOMPAT */
+PCRE_EXP_DECL void *pcre_malloc(size_t);
+PCRE_EXP_DECL void pcre_free(void *);
+PCRE_EXP_DECL void *pcre_stack_malloc(size_t);
+PCRE_EXP_DECL void pcre_stack_free(void *);
+PCRE_EXP_DECL int pcre_callout(pcre_callout_block *);
+PCRE_EXP_DECL int pcre_stack_guard(void);
+
+PCRE_EXP_DECL void *pcre16_malloc(size_t);
+PCRE_EXP_DECL void pcre16_free(void *);
+PCRE_EXP_DECL void *pcre16_stack_malloc(size_t);
+PCRE_EXP_DECL void pcre16_stack_free(void *);
+PCRE_EXP_DECL int pcre16_callout(pcre16_callout_block *);
+PCRE_EXP_DECL int pcre16_stack_guard(void);
+
+PCRE_EXP_DECL void *pcre32_malloc(size_t);
+PCRE_EXP_DECL void pcre32_free(void *);
+PCRE_EXP_DECL void *pcre32_stack_malloc(size_t);
+PCRE_EXP_DECL void pcre32_stack_free(void *);
+PCRE_EXP_DECL int pcre32_callout(pcre32_callout_block *);
+PCRE_EXP_DECL int pcre32_stack_guard(void);
+#endif /* VPCOMPAT */
+
+/* User defined callback which provides a stack just before the match starts. */
+
+typedef pcre_jit_stack *(*pcre_jit_callback)(void *);
+typedef pcre16_jit_stack *(*pcre16_jit_callback)(void *);
+typedef pcre32_jit_stack *(*pcre32_jit_callback)(void *);
+
+/* Exported PCRE functions */
+
+PCRE_EXP_DECL pcre *pcre_compile(const char *, int, const char **, int *,
+ const unsigned char *);
+PCRE_EXP_DECL pcre16 *pcre16_compile(PCRE_SPTR16, int, const char **, int *,
+ const unsigned char *);
+PCRE_EXP_DECL pcre32 *pcre32_compile(PCRE_SPTR32, int, const char **, int *,
+ const unsigned char *);
+PCRE_EXP_DECL pcre *pcre_compile2(const char *, int, int *, const char **,
+ int *, const unsigned char *);
+PCRE_EXP_DECL pcre16 *pcre16_compile2(PCRE_SPTR16, int, int *, const char **,
+ int *, const unsigned char *);
+PCRE_EXP_DECL pcre32 *pcre32_compile2(PCRE_SPTR32, int, int *, const char **,
+ int *, const unsigned char *);
+PCRE_EXP_DECL int pcre_config(int, void *);
+PCRE_EXP_DECL int pcre16_config(int, void *);
+PCRE_EXP_DECL int pcre32_config(int, void *);
+PCRE_EXP_DECL int pcre_copy_named_substring(const pcre *, const char *,
+ int *, int, const char *, char *, int);
+PCRE_EXP_DECL int pcre16_copy_named_substring(const pcre16 *, PCRE_SPTR16,
+ int *, int, PCRE_SPTR16, PCRE_UCHAR16 *, int);
+PCRE_EXP_DECL int pcre32_copy_named_substring(const pcre32 *, PCRE_SPTR32,
+ int *, int, PCRE_SPTR32, PCRE_UCHAR32 *, int);
+PCRE_EXP_DECL int pcre_copy_substring(const char *, int *, int, int,
+ char *, int);
+PCRE_EXP_DECL int pcre16_copy_substring(PCRE_SPTR16, int *, int, int,
+ PCRE_UCHAR16 *, int);
+PCRE_EXP_DECL int pcre32_copy_substring(PCRE_SPTR32, int *, int, int,
+ PCRE_UCHAR32 *, int);
+PCRE_EXP_DECL int pcre_dfa_exec(const pcre *, const pcre_extra *,
+ const char *, int, int, int, int *, int , int *, int);
+PCRE_EXP_DECL int pcre16_dfa_exec(const pcre16 *, const pcre16_extra *,
+ PCRE_SPTR16, int, int, int, int *, int , int *, int);
+PCRE_EXP_DECL int pcre32_dfa_exec(const pcre32 *, const pcre32_extra *,
+ PCRE_SPTR32, int, int, int, int *, int , int *, int);
+PCRE_EXP_DECL int pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR,
+ int, int, int, int *, int);
+PCRE_EXP_DECL int pcre16_exec(const pcre16 *, const pcre16_extra *,
+ PCRE_SPTR16, int, int, int, int *, int);
+PCRE_EXP_DECL int pcre32_exec(const pcre32 *, const pcre32_extra *,
+ PCRE_SPTR32, int, int, int, int *, int);
+PCRE_EXP_DECL int pcre_jit_exec(const pcre *, const pcre_extra *,
+ PCRE_SPTR, int, int, int, int *, int,
+ pcre_jit_stack *);
+PCRE_EXP_DECL int pcre16_jit_exec(const pcre16 *, const pcre16_extra *,
+ PCRE_SPTR16, int, int, int, int *, int,
+ pcre16_jit_stack *);
+PCRE_EXP_DECL int pcre32_jit_exec(const pcre32 *, const pcre32_extra *,
+ PCRE_SPTR32, int, int, int, int *, int,
+ pcre32_jit_stack *);
+PCRE_EXP_DECL void pcre_free_substring(const char *);
+PCRE_EXP_DECL void pcre16_free_substring(PCRE_SPTR16);
+PCRE_EXP_DECL void pcre32_free_substring(PCRE_SPTR32);
+PCRE_EXP_DECL void pcre_free_substring_list(const char **);
+PCRE_EXP_DECL void pcre16_free_substring_list(PCRE_SPTR16 *);
+PCRE_EXP_DECL void pcre32_free_substring_list(PCRE_SPTR32 *);
+PCRE_EXP_DECL int pcre_fullinfo(const pcre *, const pcre_extra *, int,
+ void *);
+PCRE_EXP_DECL int pcre16_fullinfo(const pcre16 *, const pcre16_extra *, int,
+ void *);
+PCRE_EXP_DECL int pcre32_fullinfo(const pcre32 *, const pcre32_extra *, int,
+ void *);
+PCRE_EXP_DECL int pcre_get_named_substring(const pcre *, const char *,
+ int *, int, const char *, const char **);
+PCRE_EXP_DECL int pcre16_get_named_substring(const pcre16 *, PCRE_SPTR16,
+ int *, int, PCRE_SPTR16, PCRE_SPTR16 *);
+PCRE_EXP_DECL int pcre32_get_named_substring(const pcre32 *, PCRE_SPTR32,
+ int *, int, PCRE_SPTR32, PCRE_SPTR32 *);
+PCRE_EXP_DECL int pcre_get_stringnumber(const pcre *, const char *);
+PCRE_EXP_DECL int pcre16_get_stringnumber(const pcre16 *, PCRE_SPTR16);
+PCRE_EXP_DECL int pcre32_get_stringnumber(const pcre32 *, PCRE_SPTR32);
+PCRE_EXP_DECL int pcre_get_stringtable_entries(const pcre *, const char *,
+ char **, char **);
+PCRE_EXP_DECL int pcre16_get_stringtable_entries(const pcre16 *, PCRE_SPTR16,
+ PCRE_UCHAR16 **, PCRE_UCHAR16 **);
+PCRE_EXP_DECL int pcre32_get_stringtable_entries(const pcre32 *, PCRE_SPTR32,
+ PCRE_UCHAR32 **, PCRE_UCHAR32 **);
+PCRE_EXP_DECL int pcre_get_substring(const char *, int *, int, int,
+ const char **);
+PCRE_EXP_DECL int pcre16_get_substring(PCRE_SPTR16, int *, int, int,
+ PCRE_SPTR16 *);
+PCRE_EXP_DECL int pcre32_get_substring(PCRE_SPTR32, int *, int, int,
+ PCRE_SPTR32 *);
+PCRE_EXP_DECL int pcre_get_substring_list(const char *, int *, int,
+ const char ***);
+PCRE_EXP_DECL int pcre16_get_substring_list(PCRE_SPTR16, int *, int,
+ PCRE_SPTR16 **);
+PCRE_EXP_DECL int pcre32_get_substring_list(PCRE_SPTR32, int *, int,
+ PCRE_SPTR32 **);
+PCRE_EXP_DECL const unsigned char *pcre_maketables(void);
+PCRE_EXP_DECL const unsigned char *pcre16_maketables(void);
+PCRE_EXP_DECL const unsigned char *pcre32_maketables(void);
+PCRE_EXP_DECL int pcre_refcount(pcre *, int);
+PCRE_EXP_DECL int pcre16_refcount(pcre16 *, int);
+PCRE_EXP_DECL int pcre32_refcount(pcre32 *, int);
+PCRE_EXP_DECL pcre_extra *pcre_study(const pcre *, int, const char **);
+PCRE_EXP_DECL pcre16_extra *pcre16_study(const pcre16 *, int, const char **);
+PCRE_EXP_DECL pcre32_extra *pcre32_study(const pcre32 *, int, const char **);
+PCRE_EXP_DECL void pcre_free_study(pcre_extra *);
+PCRE_EXP_DECL void pcre16_free_study(pcre16_extra *);
+PCRE_EXP_DECL void pcre32_free_study(pcre32_extra *);
+PCRE_EXP_DECL const char *pcre_version(void);
+PCRE_EXP_DECL const char *pcre16_version(void);
+PCRE_EXP_DECL const char *pcre32_version(void);
+
+/* Utility functions for byte order swaps. */
+PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *, pcre_extra *,
+ const unsigned char *);
+PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *, pcre16_extra *,
+ const unsigned char *);
+PCRE_EXP_DECL int pcre32_pattern_to_host_byte_order(pcre32 *, pcre32_extra *,
+ const unsigned char *);
+PCRE_EXP_DECL int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *,
+ PCRE_SPTR16, int, int *, int);
+PCRE_EXP_DECL int pcre32_utf32_to_host_byte_order(PCRE_UCHAR32 *,
+ PCRE_SPTR32, int, int *, int);
+
+/* JIT compiler related functions. */
+
+PCRE_EXP_DECL pcre_jit_stack *pcre_jit_stack_alloc(int, int);
+PCRE_EXP_DECL pcre16_jit_stack *pcre16_jit_stack_alloc(int, int);
+PCRE_EXP_DECL pcre32_jit_stack *pcre32_jit_stack_alloc(int, int);
+PCRE_EXP_DECL void pcre_jit_stack_free(pcre_jit_stack *);
+PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_jit_stack *);
+PCRE_EXP_DECL void pcre32_jit_stack_free(pcre32_jit_stack *);
+PCRE_EXP_DECL void pcre_assign_jit_stack(pcre_extra *,
+ pcre_jit_callback, void *);
+PCRE_EXP_DECL void pcre16_assign_jit_stack(pcre16_extra *,
+ pcre16_jit_callback, void *);
+PCRE_EXP_DECL void pcre32_assign_jit_stack(pcre32_extra *,
+ pcre32_jit_callback, void *);
+PCRE_EXP_DECL void pcre_jit_free_unused_memory(void);
+PCRE_EXP_DECL void pcre16_jit_free_unused_memory(void);
+PCRE_EXP_DECL void pcre32_jit_free_unused_memory(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* End of pcre.h */
diff --git a/plugins/Pcre16/src/pcre16_byte_order.c b/plugins/Pcre16/src/pcre16_byte_order.c
new file mode 100644
index 0000000000..11d2973a3d
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_byte_order.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_byte_order.c"
+
+/* End of pcre16_byte_order.c */
diff --git a/plugins/Pcre16/src/pcre16_chartables.c b/plugins/Pcre16/src/pcre16_chartables.c
new file mode 100644
index 0000000000..7c0ff35f5e
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_chartables.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_chartables.c"
+
+/* End of pcre16_chartables.c */
diff --git a/plugins/Pcre16/src/pcre16_compile.c b/plugins/Pcre16/src/pcre16_compile.c
new file mode 100644
index 0000000000..e499b67087
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_compile.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_compile.c"
+
+/* End of pcre16_compile.c */
diff --git a/plugins/Pcre16/src/pcre16_config.c b/plugins/Pcre16/src/pcre16_config.c
new file mode 100644
index 0000000000..b52138764f
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_config.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_config.c"
+
+/* End of pcre16_config.c */
diff --git a/plugins/Pcre16/src/pcre16_dfa_exec.c b/plugins/Pcre16/src/pcre16_dfa_exec.c
new file mode 100644
index 0000000000..2ba740e972
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_dfa_exec.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_dfa_exec.c"
+
+/* End of pcre16_dfa_exec.c */
diff --git a/plugins/Pcre16/src/pcre16_exec.c b/plugins/Pcre16/src/pcre16_exec.c
new file mode 100644
index 0000000000..7417b1770c
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_exec.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_exec.c"
+
+/* End of pcre16_exec.c */
diff --git a/plugins/Pcre16/src/pcre16_fullinfo.c b/plugins/Pcre16/src/pcre16_fullinfo.c
new file mode 100644
index 0000000000..544dca6ed5
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_fullinfo.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_fullinfo.c"
+
+/* End of pcre16_fullinfo.c */
diff --git a/plugins/Pcre16/src/pcre16_get.c b/plugins/Pcre16/src/pcre16_get.c
new file mode 100644
index 0000000000..3ded08c622
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_get.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_get.c"
+
+/* End of pcre16_get.c */
diff --git a/plugins/Pcre16/src/pcre16_globals.c b/plugins/Pcre16/src/pcre16_globals.c
new file mode 100644
index 0000000000..a136b3d8c2
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_globals.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_globals.c"
+
+/* End of pcre16_globals.c */
diff --git a/plugins/Pcre16/src/pcre16_jit_compile.c b/plugins/Pcre16/src/pcre16_jit_compile.c
new file mode 100644
index 0000000000..ab0cacd764
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_jit_compile.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_jit_compile.c"
+
+/* End of pcre16_jit_compile.c */
diff --git a/plugins/Pcre16/src/pcre16_maketables.c b/plugins/Pcre16/src/pcre16_maketables.c
new file mode 100644
index 0000000000..b1cd1c579d
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_maketables.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_maketables.c"
+
+/* End of pcre16_maketables.c */
diff --git a/plugins/Pcre16/src/pcre16_newline.c b/plugins/Pcre16/src/pcre16_newline.c
new file mode 100644
index 0000000000..7fe201400f
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_newline.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_newline.c"
+
+/* End of pcre16_newline.c */
diff --git a/plugins/Pcre16/src/pcre16_ord2utf16.c b/plugins/Pcre16/src/pcre16_ord2utf16.c
new file mode 100644
index 0000000000..8e2ce5ea6c
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_ord2utf16.c
@@ -0,0 +1,90 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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 file contains a private PCRE function that converts an ordinal
+character value into a UTF16 string. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_internal.h"
+
+/*************************************************
+* Convert character value to UTF-16 *
+*************************************************/
+
+/* This function takes an integer value in the range 0 - 0x10ffff
+and encodes it as a UTF-16 character in 1 to 2 pcre_uchars.
+
+Arguments:
+ cvalue the character value
+ buffer pointer to buffer for result - at least 2 pcre_uchars long
+
+Returns: number of characters placed in the buffer
+*/
+
+unsigned int
+PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer)
+{
+#ifdef SUPPORT_UTF
+
+if (cvalue <= 0xffff)
+ {
+ *buffer = (pcre_uchar)cvalue;
+ return 1;
+ }
+
+cvalue -= 0x10000;
+*buffer++ = 0xd800 | (cvalue >> 10);
+*buffer = 0xdc00 | (cvalue & 0x3ff);
+return 2;
+
+#else /* SUPPORT_UTF */
+(void)(cvalue); /* Keep compiler happy; this function won't ever be */
+(void)(buffer); /* called when SUPPORT_UTF is not defined. */
+return 0;
+#endif /* SUPPORT_UTF */
+}
+
+/* End of pcre16_ord2utf16.c */
diff --git a/plugins/Pcre16/src/pcre16_printint.c b/plugins/Pcre16/src/pcre16_printint.c
new file mode 100644
index 0000000000..33d8c34020
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_printint.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_printint.c"
+
+/* End of pcre16_printint.c */
diff --git a/plugins/Pcre16/src/pcre16_refcount.c b/plugins/Pcre16/src/pcre16_refcount.c
new file mode 100644
index 0000000000..d3d1543973
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_refcount.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_refcount.c"
+
+/* End of pcre16_refcount.c */
diff --git a/plugins/Pcre16/src/pcre16_string_utils.c b/plugins/Pcre16/src/pcre16_string_utils.c
new file mode 100644
index 0000000000..382c40799f
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_string_utils.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_string_utils.c"
+
+/* End of pcre16_string_utils.c */
diff --git a/plugins/Pcre16/src/pcre16_study.c b/plugins/Pcre16/src/pcre16_study.c
new file mode 100644
index 0000000000..f87de081fc
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_study.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_study.c"
+
+/* End of pcre16_study.c */
diff --git a/plugins/Pcre16/src/pcre16_tables.c b/plugins/Pcre16/src/pcre16_tables.c
new file mode 100644
index 0000000000..d84297093a
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_tables.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_tables.c"
+
+/* End of pcre16_tables.c */
diff --git a/plugins/Pcre16/src/pcre16_ucd.c b/plugins/Pcre16/src/pcre16_ucd.c
new file mode 100644
index 0000000000..ee23439a01
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_ucd.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_ucd.c"
+
+/* End of pcre16_ucd.c */
diff --git a/plugins/Pcre16/src/pcre16_utf16_utils.c b/plugins/Pcre16/src/pcre16_utf16_utils.c
new file mode 100644
index 0000000000..49ced0c0b1
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_utf16_utils.c
@@ -0,0 +1,130 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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 a function for converting any UTF-16 character
+strings to host byte order. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_internal.h"
+
+/*************************************************
+* Convert any UTF-16 string to host byte order *
+*************************************************/
+
+/* This function takes an UTF-16 string and converts
+it to host byte order. The length can be explicitly set,
+or automatically detected for zero terminated strings.
+BOMs can be kept or discarded during the conversion.
+Conversion can be done in place (output == input).
+
+Arguments:
+ output the output buffer, its size must be greater
+ or equal than the input string
+ input any UTF-16 string
+ length the number of 16-bit units in the input string
+ can be less than zero for zero terminated strings
+ host_byte_order
+ A non-zero value means the input is in host byte
+ order, which can be dynamically changed by BOMs later.
+ Initially it contains the starting byte order and returns
+ with the last byte order so it can be used for stream
+ processing. It can be NULL, which set the host byte
+ order mode by default.
+ keep_boms for a non-zero value, the BOM (0xfeff) characters
+ are copied as well
+
+Returns: the number of 16-bit units placed into the output buffer,
+ including the zero-terminator
+*/
+
+int
+pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *output, PCRE_SPTR16 input,
+ int length, int *host_byte_order, int keep_boms)
+{
+#ifdef SUPPORT_UTF
+/* This function converts any UTF-16 string to host byte order and optionally
+removes any Byte Order Marks (BOMS). Returns with the remainig length. */
+int host_bo = host_byte_order != NULL ? *host_byte_order : 1;
+pcre_uchar *optr = (pcre_uchar *)output;
+const pcre_uchar *iptr = (const pcre_uchar *)input;
+const pcre_uchar *end;
+/* The c variable must be unsigned. */
+register pcre_uchar c;
+
+if (length < 0)
+ length = STRLEN_UC(iptr) + 1;
+end = iptr + length;
+
+while (iptr < end)
+ {
+ c = *iptr++;
+ if (c == 0xfeff || c == 0xfffe)
+ {
+ /* Detecting the byte order of the machine is unnecessary, it is
+ enough to know that the UTF-16 string has the same byte order or not. */
+ host_bo = c == 0xfeff;
+ if (keep_boms != 0)
+ *optr++ = 0xfeff;
+ else
+ length--;
+ }
+ else
+ *optr++ = host_bo ? c : ((c >> 8) | (c << 8)); /* Flip bytes if needed. */
+ }
+if (host_byte_order != NULL)
+ *host_byte_order = host_bo;
+
+#else /* Not SUPPORT_UTF */
+(void)(output); /* Keep picky compilers happy */
+(void)(input);
+(void)(keep_boms);
+(void)(host_byte_order);
+#endif /* SUPPORT_UTF */
+return length;
+}
+
+/* End of pcre16_utf16_utils.c */
diff --git a/plugins/Pcre16/src/pcre16_valid_utf16.c b/plugins/Pcre16/src/pcre16_valid_utf16.c
new file mode 100644
index 0000000000..09076539d0
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_valid_utf16.c
@@ -0,0 +1,137 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2013 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 an internal function for validating UTF-16 character
+strings. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_internal.h"
+
+
+/*************************************************
+* Validate a UTF-16 string *
+*************************************************/
+
+/* This function is called (optionally) at the start of compile or match, to
+check that a supposed UTF-16 string is actually valid. The early check means
+that subsequent code can assume it is dealing with a valid string. The check
+can be turned off for maximum performance, but the consequences of supplying an
+invalid string are then undefined.
+
+From release 8.21 more information about the details of the error are passed
+back in the returned value:
+
+PCRE_UTF16_ERR0 No error
+PCRE_UTF16_ERR1 Missing low surrogate at the end of the string
+PCRE_UTF16_ERR2 Invalid low surrogate
+PCRE_UTF16_ERR3 Isolated low surrogate
+PCRE_UTF16_ERR4 Unused (was non-character)
+
+Arguments:
+ string points to the string
+ length length of string, or -1 if the string is zero-terminated
+ errp pointer to an error position offset variable
+
+Returns: = 0 if the string is a valid UTF-16 string
+ > 0 otherwise, setting the offset of the bad character
+*/
+
+int
+PRIV(valid_utf)(PCRE_PUCHAR string, int length, int *erroroffset)
+{
+#ifdef SUPPORT_UTF
+register PCRE_PUCHAR p;
+register pcre_uint32 c;
+
+if (length < 0)
+ {
+ for (p = string; *p != 0; p++);
+ length = p - string;
+ }
+
+for (p = string; length-- > 0; p++)
+ {
+ c = *p;
+
+ if ((c & 0xf800) != 0xd800)
+ {
+ /* Normal UTF-16 code point. Neither high nor low surrogate. */
+ }
+ else if ((c & 0x0400) == 0)
+ {
+ /* High surrogate. Must be a followed by a low surrogate. */
+ if (length == 0)
+ {
+ *erroroffset = p - string;
+ return PCRE_UTF16_ERR1;
+ }
+ p++;
+ length--;
+ if ((*p & 0xfc00) != 0xdc00)
+ {
+ *erroroffset = p - string;
+ return PCRE_UTF16_ERR2;
+ }
+ }
+ else
+ {
+ /* Isolated low surrogate. Always an error. */
+ *erroroffset = p - string;
+ return PCRE_UTF16_ERR3;
+ }
+ }
+
+#else /* SUPPORT_UTF */
+(void)(string); /* Keep picky compilers happy */
+(void)(length);
+(void)(erroroffset);
+#endif /* SUPPORT_UTF */
+
+return PCRE_UTF16_ERR0; /* This indicates success */
+}
+
+/* End of pcre16_valid_utf16.c */
diff --git a/plugins/Pcre16/src/pcre16_version.c b/plugins/Pcre16/src/pcre16_version.c
new file mode 100644
index 0000000000..e991b1a8cf
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_version.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_version.c"
+
+/* End of pcre16_version.c */
diff --git a/plugins/Pcre16/src/pcre16_xclass.c b/plugins/Pcre16/src/pcre16_xclass.c
new file mode 100644
index 0000000000..5aac2a36c6
--- /dev/null
+++ b/plugins/Pcre16/src/pcre16_xclass.c
@@ -0,0 +1,45 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+/* Generate code with 16 bit character support. */
+#define COMPILE_PCRE16
+
+#include "pcre_xclass.c"
+
+/* End of pcre16_xclass.c */
diff --git a/plugins/Pcre16/src/pcre_byte_order.c b/plugins/Pcre16/src/pcre_byte_order.c
new file mode 100644
index 0000000000..cf5f12b04e
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_byte_order.c
@@ -0,0 +1,319 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2014 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 an internal function that tests a compiled pattern to
+see if it was compiled with the opposite endianness. If so, it uses an
+auxiliary local function to flip the appropriate bytes. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+
+/*************************************************
+* Swap byte functions *
+*************************************************/
+
+/* The following functions swap the bytes of a pcre_uint16
+and pcre_uint32 value.
+
+Arguments:
+ value any number
+
+Returns: the byte swapped value
+*/
+
+static pcre_uint32
+swap_uint32(pcre_uint32 value)
+{
+return ((value & 0x000000ff) << 24) |
+ ((value & 0x0000ff00) << 8) |
+ ((value & 0x00ff0000) >> 8) |
+ (value >> 24);
+}
+
+static pcre_uint16
+swap_uint16(pcre_uint16 value)
+{
+return (value >> 8) | (value << 8);
+}
+
+
+/*************************************************
+* Test for a byte-flipped compiled regex *
+*************************************************/
+
+/* This function swaps the bytes of a compiled pattern usually
+loaded form the disk. It also sets the tables pointer, which
+is likely an invalid pointer after reload.
+
+Arguments:
+ argument_re points to the compiled expression
+ extra_data points to extra data or is NULL
+ tables points to the character tables or NULL
+
+Returns: 0 if the swap is successful, negative on error
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *argument_re,
+ pcre_extra *extra_data, const unsigned char *tables)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *argument_re,
+ pcre16_extra *extra_data, const unsigned char *tables)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DECL int pcre32_pattern_to_host_byte_order(pcre32 *argument_re,
+ pcre32_extra *extra_data, const unsigned char *tables)
+#endif
+{
+REAL_PCRE *re = (REAL_PCRE *)argument_re;
+pcre_study_data *study;
+#ifndef COMPILE_PCRE8
+pcre_uchar *ptr;
+int length;
+#if defined SUPPORT_UTF && defined COMPILE_PCRE16
+BOOL utf;
+BOOL utf16_char;
+#endif /* SUPPORT_UTF && COMPILE_PCRE16 */
+#endif /* !COMPILE_PCRE8 */
+
+if (re == NULL) return PCRE_ERROR_NULL;
+if (re->magic_number == MAGIC_NUMBER)
+ {
+ if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
+ re->tables = tables;
+ return 0;
+ }
+
+if (re->magic_number != REVERSED_MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
+if ((swap_uint32(re->flags) & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
+
+re->magic_number = MAGIC_NUMBER;
+re->size = swap_uint32(re->size);
+re->options = swap_uint32(re->options);
+re->flags = swap_uint32(re->flags);
+re->limit_match = swap_uint32(re->limit_match);
+re->limit_recursion = swap_uint32(re->limit_recursion);
+
+#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
+re->first_char = swap_uint16(re->first_char);
+re->req_char = swap_uint16(re->req_char);
+#elif defined COMPILE_PCRE32
+re->first_char = swap_uint32(re->first_char);
+re->req_char = swap_uint32(re->req_char);
+#endif
+
+re->max_lookbehind = swap_uint16(re->max_lookbehind);
+re->top_bracket = swap_uint16(re->top_bracket);
+re->top_backref = swap_uint16(re->top_backref);
+re->name_table_offset = swap_uint16(re->name_table_offset);
+re->name_entry_size = swap_uint16(re->name_entry_size);
+re->name_count = swap_uint16(re->name_count);
+re->ref_count = swap_uint16(re->ref_count);
+re->tables = tables;
+
+if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0)
+ {
+ study = (pcre_study_data *)extra_data->study_data;
+ study->size = swap_uint32(study->size);
+ study->flags = swap_uint32(study->flags);
+ study->minlength = swap_uint32(study->minlength);
+ }
+
+#ifndef COMPILE_PCRE8
+ptr = (pcre_uchar *)re + re->name_table_offset;
+length = re->name_count * re->name_entry_size;
+#if defined SUPPORT_UTF && defined COMPILE_PCRE16
+utf = (re->options & PCRE_UTF16) != 0;
+utf16_char = FALSE;
+#endif /* SUPPORT_UTF && COMPILE_PCRE16 */
+
+while(TRUE)
+ {
+ /* Swap previous characters. */
+ while (length-- > 0)
+ {
+#if defined COMPILE_PCRE16
+ *ptr = swap_uint16(*ptr);
+#elif defined COMPILE_PCRE32
+ *ptr = swap_uint32(*ptr);
+#endif
+ ptr++;
+ }
+#if defined SUPPORT_UTF && defined COMPILE_PCRE16
+ if (utf16_char)
+ {
+ if (HAS_EXTRALEN(ptr[-1]))
+ {
+ /* We know that there is only one extra character in UTF-16. */
+ *ptr = swap_uint16(*ptr);
+ ptr++;
+ }
+ }
+ utf16_char = FALSE;
+#endif /* SUPPORT_UTF */
+
+ /* Get next opcode. */
+ length = 0;
+#if defined COMPILE_PCRE16
+ *ptr = swap_uint16(*ptr);
+#elif defined COMPILE_PCRE32
+ *ptr = swap_uint32(*ptr);
+#endif
+ switch (*ptr)
+ {
+ case OP_END:
+ return 0;
+
+#if defined SUPPORT_UTF && defined COMPILE_PCRE16
+ case OP_CHAR:
+ case OP_CHARI:
+ case OP_NOT:
+ case OP_NOTI:
+ case OP_STAR:
+ case OP_MINSTAR:
+ case OP_PLUS:
+ case OP_MINPLUS:
+ case OP_QUERY:
+ case OP_MINQUERY:
+ case OP_UPTO:
+ case OP_MINUPTO:
+ case OP_EXACT:
+ case OP_POSSTAR:
+ case OP_POSPLUS:
+ case OP_POSQUERY:
+ case OP_POSUPTO:
+ case OP_STARI:
+ case OP_MINSTARI:
+ case OP_PLUSI:
+ case OP_MINPLUSI:
+ case OP_QUERYI:
+ case OP_MINQUERYI:
+ case OP_UPTOI:
+ case OP_MINUPTOI:
+ case OP_EXACTI:
+ case OP_POSSTARI:
+ case OP_POSPLUSI:
+ case OP_POSQUERYI:
+ case OP_POSUPTOI:
+ case OP_NOTSTAR:
+ case OP_NOTMINSTAR:
+ case OP_NOTPLUS:
+ case OP_NOTMINPLUS:
+ case OP_NOTQUERY:
+ case OP_NOTMINQUERY:
+ case OP_NOTUPTO:
+ case OP_NOTMINUPTO:
+ case OP_NOTEXACT:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSUPTO:
+ case OP_NOTSTARI:
+ case OP_NOTMINSTARI:
+ case OP_NOTPLUSI:
+ case OP_NOTMINPLUSI:
+ case OP_NOTQUERYI:
+ case OP_NOTMINQUERYI:
+ case OP_NOTUPTOI:
+ case OP_NOTMINUPTOI:
+ case OP_NOTEXACTI:
+ case OP_NOTPOSSTARI:
+ case OP_NOTPOSPLUSI:
+ case OP_NOTPOSQUERYI:
+ case OP_NOTPOSUPTOI:
+ if (utf) utf16_char = TRUE;
+#endif
+ /* Fall through. */
+
+ default:
+ length = PRIV(OP_lengths)[*ptr] - 1;
+ break;
+
+ case OP_CLASS:
+ case OP_NCLASS:
+ /* Skip the character bit map. */
+ ptr += 32/sizeof(pcre_uchar);
+ length = 0;
+ break;
+
+ case OP_XCLASS:
+ /* Reverse the size of the XCLASS instance. */
+ ptr++;
+#if defined COMPILE_PCRE16
+ *ptr = swap_uint16(*ptr);
+#elif defined COMPILE_PCRE32
+ *ptr = swap_uint32(*ptr);
+#endif
+#ifndef COMPILE_PCRE32
+ if (LINK_SIZE > 1)
+ {
+ /* LINK_SIZE can be 1 or 2 in 16 bit mode. */
+ ptr++;
+ *ptr = swap_uint16(*ptr);
+ }
+#endif
+ ptr++;
+ length = (GET(ptr, -LINK_SIZE)) - (1 + LINK_SIZE + 1);
+#if defined COMPILE_PCRE16
+ *ptr = swap_uint16(*ptr);
+#elif defined COMPILE_PCRE32
+ *ptr = swap_uint32(*ptr);
+#endif
+ if ((*ptr & XCL_MAP) != 0)
+ {
+ /* Skip the character bit map. */
+ ptr += 32/sizeof(pcre_uchar);
+ length -= 32/sizeof(pcre_uchar);
+ }
+ break;
+ }
+ ptr++;
+ }
+/* Control should never reach here in 16/32 bit mode. */
+#else /* In 8-bit mode, the pattern does not need to be processed. */
+return 0;
+#endif /* !COMPILE_PCRE8 */
+}
+
+/* End of pcre_byte_order.c */
diff --git a/plugins/Pcre16/src/pcre_chartables.c b/plugins/Pcre16/src/pcre_chartables.c
new file mode 100644
index 0000000000..1e20ec29d0
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_chartables.c
@@ -0,0 +1,198 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* This file contains character tables that are used when no external tables
+are passed to PCRE by the application that calls it. The tables are used only
+for characters whose code values are less than 256.
+
+This is a default version of the tables that assumes ASCII encoding. A program
+called dftables (which is distributed with PCRE) can be used to build
+alternative versions of this file. This is necessary if you are running in an
+EBCDIC environment, or if you want to default to a different encoding, for
+example ISO-8859-1. When dftables is run, it creates these tables in the
+current locale. If PCRE is configured with --enable-rebuild-chartables, this
+happens automatically.
+
+The following #includes are present because without them gcc 4.x may remove the
+array definition from the final binary if PCRE is built into a static library
+and dead code stripping is activated. This leads to link errors. Pulling in the
+header ensures that the array gets flagged as "someone outside this compilation
+unit might reference this" and so it will always be supplied to the linker. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+const pcre_uint8 PRIV(default_tables)[] = {
+
+/* This table is a lower casing table. */
+
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,
+ 104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,
+ 120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,
+ 104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,
+ 120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,
+ 136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,
+ 152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,
+ 168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,
+ 184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,
+ 200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,
+ 216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,
+ 232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,
+ 248,249,250,251,252,253,254,255,
+
+/* This table is a case flipping table. */
+
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,
+ 104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,
+ 120,121,122, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,
+ 136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,
+ 152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,
+ 168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,
+ 184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,
+ 200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,
+ 216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,
+ 232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,
+ 248,249,250,251,252,253,254,255,
+
+/* This table contains bit maps for various character classes. Each map is 32
+bytes long and the bits run from the least significant end of each byte. The
+classes that have their own maps are: space, xdigit, digit, upper, lower, word,
+graph, print, punct, and cntrl. Other classes are built from combinations. */
+
+ 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
+ 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
+ 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc,
+ 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+/* This table identifies various classes of character by individual bits:
+ 0x01 white space character
+ 0x02 letter
+ 0x04 decimal digit
+ 0x08 hexadecimal digit
+ 0x10 alphanumeric or '_'
+ 0x80 regular expression metacharacter or binary zero
+*/
+
+ 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */
+ 0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /* 8- 15 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */
+ 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */
+ 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */
+ 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */
+ 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,0x80,0x80,0x00,0x80,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,0x80,0x80,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 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */
+
+/* End of pcre_chartables.c */
diff --git a/plugins/Pcre16/src/pcre_compile.c b/plugins/Pcre16/src/pcre_compile.c
new file mode 100644
index 0000000000..8a5b723347
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_compile.c
@@ -0,0 +1,9484 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2014 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 external function pcre_compile(), along with
+supporting internal functions that are not used by other modules. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define NLBLOCK cd /* Block containing newline information */
+#define PSSTART start_pattern /* Field containing processed string start */
+#define PSEND end_pattern /* Field containing processed string end */
+
+#include "pcre_internal.h"
+
+
+/* When PCRE_DEBUG is defined, we need the pcre(16|32)_printint() function, which
+is also used by pcretest. PCRE_DEBUG is not defined when building a production
+library. We do not need to select pcre16_printint.c specially, because the
+COMPILE_PCREx macro will already be appropriately set. */
+
+#ifdef PCRE_DEBUG
+/* pcre_printint.c should not include any headers */
+#define PCRE_INCLUDED
+#include "pcre_printint.c"
+#undef PCRE_INCLUDED
+#endif
+
+
+/* Macro for setting individual bits in class bitmaps. */
+
+#define SETBIT(a,b) a[(b)/8] |= (1 << ((b)&7))
+
+/* Maximum length value to check against when making sure that the integer that
+holds the compiled pattern length does not overflow. We make it a bit less than
+INT_MAX to allow for adding in group terminating bytes, so that we don't have
+to check them every time. */
+
+#define OFLOW_MAX (INT_MAX - 20)
+
+/* Definitions to allow mutual recursion */
+
+static int
+ add_list_to_class(pcre_uint8 *, pcre_uchar **, int, compile_data *,
+ const pcre_uint32 *, unsigned int);
+
+static BOOL
+ compile_regex(int, pcre_uchar **, const pcre_uchar **, int *, BOOL, BOOL, int, int,
+ pcre_uint32 *, pcre_int32 *, pcre_uint32 *, pcre_int32 *, branch_chain *,
+ compile_data *, int *);
+
+
+
+/*************************************************
+* Code parameters and static tables *
+*************************************************/
+
+/* This value specifies the size of stack workspace that is used during the
+first pre-compile phase that determines how much memory is required. The regex
+is partly compiled into this space, but the compiled parts are discarded as
+soon as they can be, so that hopefully there will never be an overrun. The code
+does, however, check for an overrun. The largest amount I've seen used is 218,
+so this number is very generous.
+
+The same workspace is used during the second, actual compile phase for
+remembering forward references to groups so that they can be filled in at the
+end. Each entry in this list occupies LINK_SIZE bytes, so even when LINK_SIZE
+is 4 there is plenty of room for most patterns. However, the memory can get
+filled up by repetitions of forward references, for example patterns like
+/(?1){0,1999}(b)/, and one user did hit the limit. The code has been changed so
+that the workspace is expanded using malloc() in this situation. The value
+below is therefore a minimum, and we put a maximum on it for safety. The
+minimum is now also defined in terms of LINK_SIZE so that the use of malloc()
+kicks in at the same number of forward references in all cases. */
+
+#define COMPILE_WORK_SIZE (2048*LINK_SIZE)
+#define COMPILE_WORK_SIZE_MAX (100*COMPILE_WORK_SIZE)
+
+/* This value determines the size of the initial vector that is used for
+remembering named groups during the pre-compile. It is allocated on the stack,
+but if it is too small, it is expanded using malloc(), in a similar way to the
+workspace. The value is the number of slots in the list. */
+
+#define NAMED_GROUP_LIST_SIZE 20
+
+/* The overrun tests check for a slightly smaller size so that they detect the
+overrun before it actually does run off the end of the data block. */
+
+#define WORK_SIZE_SAFETY_MARGIN (100)
+
+/* Private flags added to firstchar and reqchar. */
+
+#define REQ_CASELESS (1 << 0) /* Indicates caselessness */
+#define REQ_VARY (1 << 1) /* Reqchar followed non-literal item */
+/* Negative values for the firstchar and reqchar flags */
+#define REQ_UNSET (-2)
+#define REQ_NONE (-1)
+
+/* Repeated character flags. */
+
+#define UTF_LENGTH 0x10000000l /* The char contains its length. */
+
+/* Table for handling escaped characters in the range '0'-'z'. Positive returns
+are simple data values; negative values are for special things like \d and so
+on. Zero means further processing is needed (for things like \x), or the escape
+is invalid. */
+
+#ifndef EBCDIC
+
+/* This is the "normal" table for ASCII systems or for EBCDIC systems running
+in UTF-8 mode. */
+
+static const short int escapes[] = {
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ CHAR_COLON, CHAR_SEMICOLON,
+ CHAR_LESS_THAN_SIGN, CHAR_EQUALS_SIGN,
+ CHAR_GREATER_THAN_SIGN, CHAR_QUESTION_MARK,
+ CHAR_COMMERCIAL_AT, -ESC_A,
+ -ESC_B, -ESC_C,
+ -ESC_D, -ESC_E,
+ 0, -ESC_G,
+ -ESC_H, 0,
+ 0, -ESC_K,
+ 0, 0,
+ -ESC_N, 0,
+ -ESC_P, -ESC_Q,
+ -ESC_R, -ESC_S,
+ 0, 0,
+ -ESC_V, -ESC_W,
+ -ESC_X, 0,
+ -ESC_Z, CHAR_LEFT_SQUARE_BRACKET,
+ CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET,
+ CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE,
+ CHAR_GRAVE_ACCENT, 7,
+ -ESC_b, 0,
+ -ESC_d, ESC_e,
+ ESC_f, 0,
+ -ESC_h, 0,
+ 0, -ESC_k,
+ 0, 0,
+ ESC_n, 0,
+ -ESC_p, 0,
+ ESC_r, -ESC_s,
+ ESC_tee, 0,
+ -ESC_v, -ESC_w,
+ 0, 0,
+ -ESC_z
+};
+
+#else
+
+/* This is the "abnormal" table for EBCDIC systems without UTF-8 support. */
+
+static const short int escapes[] = {
+/* 48 */ 0, 0, 0, '.', '<', '(', '+', '|',
+/* 50 */ '&', 0, 0, 0, 0, 0, 0, 0,
+/* 58 */ 0, 0, '!', '$', '*', ')', ';', '~',
+/* 60 */ '-', '/', 0, 0, 0, 0, 0, 0,
+/* 68 */ 0, 0, '|', ',', '%', '_', '>', '?',
+/* 70 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 78 */ 0, '`', ':', '#', '@', '\'', '=', '"',
+/* 80 */ 0, 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0,
+/* 88 */-ESC_h, 0, 0, '{', 0, 0, 0, 0,
+/* 90 */ 0, 0, -ESC_k, 'l', 0, ESC_n, 0, -ESC_p,
+/* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0,
+/* A0 */ 0, '~', -ESC_s, ESC_tee, 0,-ESC_v, -ESC_w, 0,
+/* A8 */ 0,-ESC_z, 0, 0, 0, '[', 0, 0,
+/* B0 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* B8 */ 0, 0, 0, 0, 0, ']', '=', '-',
+/* C0 */ '{',-ESC_A, -ESC_B, -ESC_C, -ESC_D,-ESC_E, 0, -ESC_G,
+/* C8 */-ESC_H, 0, 0, 0, 0, 0, 0, 0,
+/* D0 */ '}', 0, -ESC_K, 0, 0,-ESC_N, 0, -ESC_P,
+/* D8 */-ESC_Q,-ESC_R, 0, 0, 0, 0, 0, 0,
+/* E0 */ '\\', 0, -ESC_S, 0, 0,-ESC_V, -ESC_W, -ESC_X,
+/* E8 */ 0,-ESC_Z, 0, 0, 0, 0, 0, 0,
+/* F0 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* F8 */ 0, 0, 0, 0, 0, 0, 0, 0
+};
+#endif
+
+
+/* Table of special "verbs" like (*PRUNE). This is a short table, so it is
+searched linearly. Put all the names into a single string, in order to reduce
+the number of relocations when a shared library is dynamically linked. The
+string is built from string macros so that it works in UTF-8 mode on EBCDIC
+platforms. */
+
+typedef struct verbitem {
+ int len; /* Length of verb name */
+ int op; /* Op when no arg, or -1 if arg mandatory */
+ int op_arg; /* Op when arg present, or -1 if not allowed */
+} verbitem;
+
+static const char verbnames[] =
+ "\0" /* Empty name is a shorthand for MARK */
+ STRING_MARK0
+ STRING_ACCEPT0
+ STRING_COMMIT0
+ STRING_F0
+ STRING_FAIL0
+ STRING_PRUNE0
+ STRING_SKIP0
+ STRING_THEN;
+
+static const verbitem verbs[] = {
+ { 0, -1, OP_MARK },
+ { 4, -1, OP_MARK },
+ { 6, OP_ACCEPT, -1 },
+ { 6, OP_COMMIT, -1 },
+ { 1, OP_FAIL, -1 },
+ { 4, OP_FAIL, -1 },
+ { 5, OP_PRUNE, OP_PRUNE_ARG },
+ { 4, OP_SKIP, OP_SKIP_ARG },
+ { 4, OP_THEN, OP_THEN_ARG }
+};
+
+static const int verbcount = sizeof(verbs)/sizeof(verbitem);
+
+
+/* Substitutes for [[:<:]] and [[:>:]], which mean start and end of word in
+another regex library. */
+
+static const pcre_uchar sub_start_of_word[] = {
+ CHAR_BACKSLASH, CHAR_b, CHAR_LEFT_PARENTHESIS, CHAR_QUESTION_MARK,
+ CHAR_EQUALS_SIGN, CHAR_BACKSLASH, CHAR_w, CHAR_RIGHT_PARENTHESIS, '\0' };
+
+static const pcre_uchar sub_end_of_word[] = {
+ CHAR_BACKSLASH, CHAR_b, CHAR_LEFT_PARENTHESIS, CHAR_QUESTION_MARK,
+ CHAR_LESS_THAN_SIGN, CHAR_EQUALS_SIGN, CHAR_BACKSLASH, CHAR_w,
+ CHAR_RIGHT_PARENTHESIS, '\0' };
+
+
+/* Tables of names of POSIX character classes and their lengths. The names are
+now all in a single string, to reduce the number of relocations when a shared
+library is dynamically loaded. The list of lengths is terminated by a zero
+length entry. The first three must be alpha, lower, upper, as this is assumed
+for handling case independence. The indices for graph, print, and punct are
+needed, so identify them. */
+
+static const char posix_names[] =
+ STRING_alpha0 STRING_lower0 STRING_upper0 STRING_alnum0
+ STRING_ascii0 STRING_blank0 STRING_cntrl0 STRING_digit0
+ STRING_graph0 STRING_print0 STRING_punct0 STRING_space0
+ STRING_word0 STRING_xdigit;
+
+static const pcre_uint8 posix_name_lengths[] = {
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 };
+
+#define PC_GRAPH 8
+#define PC_PRINT 9
+#define PC_PUNCT 10
+
+
+/* Table of class bit maps for each POSIX class. Each class is formed from a
+base map, with an optional addition or removal of another map. Then, for some
+classes, there is some additional tweaking: for [:blank:] the vertical space
+characters are removed, and for [:alpha:] and [:alnum:] the underscore
+character is removed. The triples in the table consist of the base map offset,
+second map offset or -1 if no second map, and a non-negative value for map
+addition or a negative value for map subtraction (if there are two maps). The
+absolute value of the third field has these meanings: 0 => no tweaking, 1 =>
+remove vertical space characters, 2 => remove underscore. */
+
+static const int posix_class_maps[] = {
+ cbit_word, cbit_digit, -2, /* alpha */
+ cbit_lower, -1, 0, /* lower */
+ cbit_upper, -1, 0, /* upper */
+ cbit_word, -1, 2, /* alnum - word without underscore */
+ cbit_print, cbit_cntrl, 0, /* ascii */
+ cbit_space, -1, 1, /* blank - a GNU extension */
+ cbit_cntrl, -1, 0, /* cntrl */
+ cbit_digit, -1, 0, /* digit */
+ cbit_graph, -1, 0, /* graph */
+ cbit_print, -1, 0, /* print */
+ cbit_punct, -1, 0, /* punct */
+ cbit_space, -1, 0, /* space */
+ cbit_word, -1, 0, /* word - a Perl extension */
+ cbit_xdigit,-1, 0 /* xdigit */
+};
+
+/* Table of substitutes for \d etc when PCRE_UCP is set. They are replaced by
+Unicode property escapes. */
+
+#ifdef SUPPORT_UCP
+static const pcre_uchar string_PNd[] = {
+ CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_N, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const pcre_uchar string_pNd[] = {
+ CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_N, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const pcre_uchar string_PXsp[] = {
+ CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_X, CHAR_s, CHAR_p, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const pcre_uchar string_pXsp[] = {
+ CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_X, CHAR_s, CHAR_p, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const pcre_uchar string_PXwd[] = {
+ CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_X, CHAR_w, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const pcre_uchar string_pXwd[] = {
+ CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_X, CHAR_w, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+
+static const pcre_uchar *substitutes[] = {
+ string_PNd, /* \D */
+ string_pNd, /* \d */
+ string_PXsp, /* \S */ /* Xsp is Perl space, but from 8.34, Perl */
+ string_pXsp, /* \s */ /* space and POSIX space are the same. */
+ string_PXwd, /* \W */
+ string_pXwd /* \w */
+};
+
+/* The POSIX class substitutes must be in the order of the POSIX class names,
+defined above, and there are both positive and negative cases. NULL means no
+general substitute of a Unicode property escape (\p or \P). However, for some
+POSIX classes (e.g. graph, print, punct) a special property code is compiled
+directly. */
+
+static const pcre_uchar string_pL[] = {
+ CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_L, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const pcre_uchar string_pLl[] = {
+ CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_L, CHAR_l, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const pcre_uchar string_pLu[] = {
+ CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_L, CHAR_u, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const pcre_uchar string_pXan[] = {
+ CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_X, CHAR_a, CHAR_n, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const pcre_uchar string_h[] = {
+ CHAR_BACKSLASH, CHAR_h, '\0' };
+static const pcre_uchar string_pXps[] = {
+ CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_X, CHAR_p, CHAR_s, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const pcre_uchar string_PL[] = {
+ CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_L, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const pcre_uchar string_PLl[] = {
+ CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_L, CHAR_l, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const pcre_uchar string_PLu[] = {
+ CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_L, CHAR_u, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const pcre_uchar string_PXan[] = {
+ CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_X, CHAR_a, CHAR_n, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const pcre_uchar string_H[] = {
+ CHAR_BACKSLASH, CHAR_H, '\0' };
+static const pcre_uchar string_PXps[] = {
+ CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_X, CHAR_p, CHAR_s, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+
+static const pcre_uchar *posix_substitutes[] = {
+ string_pL, /* alpha */
+ string_pLl, /* lower */
+ string_pLu, /* upper */
+ string_pXan, /* alnum */
+ NULL, /* ascii */
+ string_h, /* blank */
+ NULL, /* cntrl */
+ string_pNd, /* digit */
+ NULL, /* graph */
+ NULL, /* print */
+ NULL, /* punct */
+ string_pXps, /* space */ /* Xps is POSIX space, but from 8.34 */
+ string_pXwd, /* word */ /* Perl and POSIX space are the same */
+ NULL, /* xdigit */
+ /* Negated cases */
+ string_PL, /* ^alpha */
+ string_PLl, /* ^lower */
+ string_PLu, /* ^upper */
+ string_PXan, /* ^alnum */
+ NULL, /* ^ascii */
+ string_H, /* ^blank */
+ NULL, /* ^cntrl */
+ string_PNd, /* ^digit */
+ NULL, /* ^graph */
+ NULL, /* ^print */
+ NULL, /* ^punct */
+ string_PXps, /* ^space */ /* Xps is POSIX space, but from 8.34 */
+ string_PXwd, /* ^word */ /* Perl and POSIX space are the same */
+ NULL /* ^xdigit */
+};
+#define POSIX_SUBSIZE (sizeof(posix_substitutes) / sizeof(pcre_uchar *))
+#endif
+
+#define STRING(a) # a
+#define XSTRING(s) STRING(s)
+
+/* The texts of compile-time error messages. These are "char *" because they
+are passed to the outside world. Do not ever re-use any error number, because
+they are documented. Always add a new error instead. Messages marked DEAD below
+are no longer used. This used to be a table of strings, but in order to reduce
+the number of relocations needed when a shared library is loaded dynamically,
+it is now one long string. We cannot use a table of offsets, because the
+lengths of inserts such as XSTRING(MAX_NAME_SIZE) are not known. Instead, we
+simply count through to the one we want - this isn't a performance issue
+because these strings are used only when there is a compilation error.
+
+Each substring ends with \0 to insert a null character. This includes the final
+substring, so that the whole string ends with \0\0, which can be detected when
+counting through. */
+
+static const char error_texts[] =
+ "no error\0"
+ "\\ at end of pattern\0"
+ "\\c at end of pattern\0"
+ "unrecognized character follows \\\0"
+ "numbers out of order in {} quantifier\0"
+ /* 5 */
+ "number too big in {} quantifier\0"
+ "missing terminating ] for character class\0"
+ "invalid escape sequence in character class\0"
+ "range out of order in character class\0"
+ "nothing to repeat\0"
+ /* 10 */
+ "operand of unlimited repeat could match the empty string\0" /** DEAD **/
+ "internal error: unexpected repeat\0"
+ "unrecognized character after (? or (?-\0"
+ "POSIX named classes are supported only within a class\0"
+ "missing )\0"
+ /* 15 */
+ "reference to non-existent subpattern\0"
+ "erroffset passed as NULL\0"
+ "unknown option bit(s) set\0"
+ "missing ) after comment\0"
+ "parentheses nested too deeply\0" /** DEAD **/
+ /* 20 */
+ "regular expression is too large\0"
+ "failed to get memory\0"
+ "unmatched parentheses\0"
+ "internal error: code overflow\0"
+ "unrecognized character after (?<\0"
+ /* 25 */
+ "lookbehind assertion is not fixed length\0"
+ "malformed number or name after (?(\0"
+ "conditional group contains more than two branches\0"
+ "assertion expected after (?(\0"
+ "(?R or (?[+-]digits must be followed by )\0"
+ /* 30 */
+ "unknown POSIX class name\0"
+ "POSIX collating elements are not supported\0"
+ "this version of PCRE is compiled without UTF support\0"
+ "spare error\0" /** DEAD **/
+ "character value in \\x{} or \\o{} is too large\0"
+ /* 35 */
+ "invalid condition (?(0)\0"
+ "\\C not allowed in lookbehind assertion\0"
+ "PCRE does not support \\L, \\l, \\N{name}, \\U, or \\u\0"
+ "number after (?C is > 255\0"
+ "closing ) for (?C expected\0"
+ /* 40 */
+ "recursive call could loop indefinitely\0"
+ "unrecognized character after (?P\0"
+ "syntax error in subpattern name (missing terminator)\0"
+ "two named subpatterns have the same name\0"
+ "invalid UTF-8 string\0"
+ /* 45 */
+ "support for \\P, \\p, and \\X has not been compiled\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"
+ "too many named subpatterns (maximum " XSTRING(MAX_NAME_COUNT) ")\0"
+ /* 50 */
+ "repeated subpattern is too long\0" /** DEAD **/
+ "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"
+ /* 55 */
+ "repeating a DEFINE group is not allowed\0" /** DEAD **/
+ "inconsistent NEWLINE options\0"
+ "\\g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number\0"
+ "a numbered reference must not be zero\0"
+ "an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)\0"
+ /* 60 */
+ "(*VERB) not recognized or malformed\0"
+ "number is too big\0"
+ "subpattern name expected\0"
+ "digit expected after (?+\0"
+ "] is an invalid data character in JavaScript compatibility mode\0"
+ /* 65 */
+ "different names for subpatterns of the same number are not allowed\0"
+ "(*MARK) must have an argument\0"
+ "this version of PCRE is not compiled with Unicode property support\0"
+ "\\c must be followed by an ASCII character\0"
+ "\\k is not followed by a braced, angle-bracketed, or quoted name\0"
+ /* 70 */
+ "internal error: unknown opcode in find_fixedlength()\0"
+ "\\N is not supported in a class\0"
+ "too many forward references\0"
+ "disallowed Unicode code point (>= 0xd800 && <= 0xdfff)\0"
+ "invalid UTF-16 string\0"
+ /* 75 */
+ "name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)\0"
+ "character value in \\u.... sequence is too large\0"
+ "invalid UTF-32 string\0"
+ "setting UTF is disabled by the application\0"
+ "non-hex character in \\x{} (closing brace missing?)\0"
+ /* 80 */
+ "non-octal character in \\o{} (closing brace missing?)\0"
+ "missing opening brace after \\o\0"
+ "parentheses are too deeply nested\0"
+ "invalid range in character class\0"
+ "group name must start with a non-digit\0"
+ /* 85 */
+ "parentheses are too deeply nested (stack check)\0"
+ ;
+
+/* Table to identify digits and hex digits. This is used when compiling
+patterns. Note that the tables in chartables are dependent on the locale, and
+may mark arbitrary characters as digits - but the PCRE compiling code expects
+to handle only 0-9, a-z, and A-Z as digits when compiling. That is why we have
+a private table here. It costs 256 bytes, but it is a lot faster than doing
+character value tests (at least in some simple cases I timed), and in some
+applications one wants PCRE to compile efficiently as well as match
+efficiently.
+
+For convenience, we use the same bit definitions as in chartables:
+
+ 0x04 decimal digit
+ 0x08 hexadecimal digit
+
+Then we can use ctype_digit and ctype_xdigit in the code. */
+
+/* Using a simple comparison for decimal numbers rather than a memory read
+is much faster, and the resulting code is simpler (the compiler turns it
+into a subtraction and unsigned comparison). */
+
+#define IS_DIGIT(x) ((x) >= CHAR_0 && (x) <= CHAR_9)
+
+#ifndef EBCDIC
+
+/* This is the "normal" case, for ASCII systems, and EBCDIC systems running in
+UTF-8 mode. */
+
+static const pcre_uint8 digitab[] =
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - ' */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ( - / */
+ 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 */
+ 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, /* 8 - ? */
+ 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* @ - G */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H - O */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* P - W */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* X - _ */
+ 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* ` - g */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h - o */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p - w */
+ 0x00,0x00,0x00,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 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */
+
+#else
+
+/* This is the "abnormal" case, for EBCDIC systems not running in UTF-8 mode. */
+
+static const pcre_uint8 digitab[] =
+ {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 0 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 10 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 32- 39 20 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 30 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 40 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 72- | */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 50 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 88- 95 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 60 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 104- ? */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 70 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */
+ 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* 128- g 80 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144- p 90 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160- x A0 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 B0 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
+ 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* { - G C0 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* } - P D0 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* \ - X E0 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */
+ 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 F0 */
+ 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */
+
+static const pcre_uint8 ebcdic_chartab[] = { /* chartable partial dup */
+ 0x80,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 0- 7 */
+ 0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00, /* 8- 15 */
+ 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 16- 23 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */
+ 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 32- 39 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 */
+ 0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x80, /* 72- | */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 */
+ 0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00, /* 88- 95 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 */
+ 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x80, /* 104- ? */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */
+ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* 128- g */
+ 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */
+ 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* 144- p */
+ 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */
+ 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* 160- x */
+ 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */
+ 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 */
+ 0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
+ 0x80,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* { - G */
+ 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */
+ 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* } - P */
+ 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */
+ 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* \ - X */
+ 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */
+ 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */
+#endif
+
+
+/* This table is used to check whether auto-possessification is possible
+between adjacent character-type opcodes. The left-hand (repeated) opcode is
+used to select the row, and the right-hand opcode is use to select the column.
+A value of 1 means that auto-possessification is OK. For example, the second
+value in the first row means that \D+\d can be turned into \D++\d.
+
+The Unicode property types (\P and \p) have to be present to fill out the table
+because of what their opcode values are, but the table values should always be
+zero because property types are handled separately in the code. The last four
+columns apply to items that cannot be repeated, so there is no need to have
+rows for them. Note that OP_DIGIT etc. are generated only when PCRE_UCP is
+*not* set. When it is set, \d etc. are converted into OP_(NOT_)PROP codes. */
+
+#define APTROWS (LAST_AUTOTAB_LEFT_OP - FIRST_AUTOTAB_OP + 1)
+#define APTCOLS (LAST_AUTOTAB_RIGHT_OP - FIRST_AUTOTAB_OP + 1)
+
+static const pcre_uint8 autoposstab[APTROWS][APTCOLS] = {
+/* \D \d \S \s \W \w . .+ \C \P \p \R \H \h \V \v \X \Z \z $ $M */
+ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \D */
+ { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, /* \d */
+ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, /* \S */
+ { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \s */
+ { 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \W */
+ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, /* \w */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* . */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* .+ */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \C */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* \P */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* \p */
+ { 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }, /* \R */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }, /* \H */
+ { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0 }, /* \h */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0 }, /* \V */
+ { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0 }, /* \v */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } /* \X */
+};
+
+
+/* This table is used to check whether auto-possessification is possible
+between adjacent Unicode property opcodes (OP_PROP and OP_NOTPROP). The
+left-hand (repeated) opcode is used to select the row, and the right-hand
+opcode is used to select the column. The values are as follows:
+
+ 0 Always return FALSE (never auto-possessify)
+ 1 Character groups are distinct (possessify if both are OP_PROP)
+ 2 Check character categories in the same group (general or particular)
+ 3 TRUE if the two opcodes are not the same (PROP vs NOTPROP)
+
+ 4 Check left general category vs right particular category
+ 5 Check right general category vs left particular category
+
+ 6 Left alphanum vs right general category
+ 7 Left space vs right general category
+ 8 Left word vs right general category
+
+ 9 Right alphanum vs left general category
+ 10 Right space vs left general category
+ 11 Right word vs left general category
+
+ 12 Left alphanum vs right particular category
+ 13 Left space vs right particular category
+ 14 Left word vs right particular category
+
+ 15 Right alphanum vs left particular category
+ 16 Right space vs left particular category
+ 17 Right word vs left particular category
+*/
+
+static const pcre_uint8 propposstab[PT_TABSIZE][PT_TABSIZE] = {
+/* ANY LAMP GC PC SC ALNUM SPACE PXSPACE WORD CLIST UCNC */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_ANY */
+ { 0, 3, 0, 0, 0, 3, 1, 1, 0, 0, 0 }, /* PT_LAMP */
+ { 0, 0, 2, 4, 0, 9, 10, 10, 11, 0, 0 }, /* PT_GC */
+ { 0, 0, 5, 2, 0, 15, 16, 16, 17, 0, 0 }, /* PT_PC */
+ { 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 }, /* PT_SC */
+ { 0, 3, 6, 12, 0, 3, 1, 1, 0, 0, 0 }, /* PT_ALNUM */
+ { 0, 1, 7, 13, 0, 1, 3, 3, 1, 0, 0 }, /* PT_SPACE */
+ { 0, 1, 7, 13, 0, 1, 3, 3, 1, 0, 0 }, /* PT_PXSPACE */
+ { 0, 0, 8, 14, 0, 0, 1, 1, 3, 0, 0 }, /* PT_WORD */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_CLIST */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 } /* PT_UCNC */
+};
+
+/* This table is used to check whether auto-possessification is possible
+between adjacent Unicode property opcodes (OP_PROP and OP_NOTPROP) when one
+specifies a general category and the other specifies a particular category. The
+row is selected by the general category and the column by the particular
+category. The value is 1 if the particular category is not part of the general
+category. */
+
+static const pcre_uint8 catposstab[7][30] = {
+/* Cc Cf Cn Co Cs Ll Lm Lo Lt Lu Mc Me Mn Nd Nl No Pc Pd Pe Pf Pi Po Ps Sc Sk Sm So Zl Zp Zs */
+ { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* C */
+ { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* L */
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* M */
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* N */
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 }, /* P */
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1 }, /* S */
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 } /* Z */
+};
+
+/* This table is used when checking ALNUM, (PX)SPACE, SPACE, and WORD against
+a general or particular category. The properties in each row are those
+that apply to the character set in question. Duplication means that a little
+unnecessary work is done when checking, but this keeps things much simpler
+because they can all use the same code. For more details see the comment where
+this table is used.
+
+Note: SPACE and PXSPACE used to be different because Perl excluded VT from
+"space", but from Perl 5.18 it's included, so both categories are treated the
+same here. */
+
+static const pcre_uint8 posspropstab[3][4] = {
+ { ucp_L, ucp_N, ucp_N, ucp_Nl }, /* ALNUM, 3rd and 4th values redundant */
+ { ucp_Z, ucp_Z, ucp_C, ucp_Cc }, /* SPACE and PXSPACE, 2nd value redundant */
+ { ucp_L, ucp_N, ucp_P, ucp_Po } /* WORD */
+};
+
+/* This table is used when converting repeating opcodes into possessified
+versions as a result of an explicit possessive quantifier such as ++. A zero
+value means there is no possessified version - in those cases the item in
+question must be wrapped in ONCE brackets. The table is truncated at OP_CALLOUT
+because all relevant opcodes are less than that. */
+
+static const pcre_uint8 opcode_possessify[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 15 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 - 31 */
+
+ 0, /* NOTI */
+ OP_POSSTAR, 0, /* STAR, MINSTAR */
+ OP_POSPLUS, 0, /* PLUS, MINPLUS */
+ OP_POSQUERY, 0, /* QUERY, MINQUERY */
+ OP_POSUPTO, 0, /* UPTO, MINUPTO */
+ 0, /* EXACT */
+ 0, 0, 0, 0, /* POS{STAR,PLUS,QUERY,UPTO} */
+
+ OP_POSSTARI, 0, /* STARI, MINSTARI */
+ OP_POSPLUSI, 0, /* PLUSI, MINPLUSI */
+ OP_POSQUERYI, 0, /* QUERYI, MINQUERYI */
+ OP_POSUPTOI, 0, /* UPTOI, MINUPTOI */
+ 0, /* EXACTI */
+ 0, 0, 0, 0, /* POS{STARI,PLUSI,QUERYI,UPTOI} */
+
+ OP_NOTPOSSTAR, 0, /* NOTSTAR, NOTMINSTAR */
+ OP_NOTPOSPLUS, 0, /* NOTPLUS, NOTMINPLUS */
+ OP_NOTPOSQUERY, 0, /* NOTQUERY, NOTMINQUERY */
+ OP_NOTPOSUPTO, 0, /* NOTUPTO, NOTMINUPTO */
+ 0, /* NOTEXACT */
+ 0, 0, 0, 0, /* NOTPOS{STAR,PLUS,QUERY,UPTO} */
+
+ OP_NOTPOSSTARI, 0, /* NOTSTARI, NOTMINSTARI */
+ OP_NOTPOSPLUSI, 0, /* NOTPLUSI, NOTMINPLUSI */
+ OP_NOTPOSQUERYI, 0, /* NOTQUERYI, NOTMINQUERYI */
+ OP_NOTPOSUPTOI, 0, /* NOTUPTOI, NOTMINUPTOI */
+ 0, /* NOTEXACTI */
+ 0, 0, 0, 0, /* NOTPOS{STARI,PLUSI,QUERYI,UPTOI} */
+
+ OP_TYPEPOSSTAR, 0, /* TYPESTAR, TYPEMINSTAR */
+ OP_TYPEPOSPLUS, 0, /* TYPEPLUS, TYPEMINPLUS */
+ OP_TYPEPOSQUERY, 0, /* TYPEQUERY, TYPEMINQUERY */
+ OP_TYPEPOSUPTO, 0, /* TYPEUPTO, TYPEMINUPTO */
+ 0, /* TYPEEXACT */
+ 0, 0, 0, 0, /* TYPEPOS{STAR,PLUS,QUERY,UPTO} */
+
+ OP_CRPOSSTAR, 0, /* CRSTAR, CRMINSTAR */
+ OP_CRPOSPLUS, 0, /* CRPLUS, CRMINPLUS */
+ OP_CRPOSQUERY, 0, /* CRQUERY, CRMINQUERY */
+ OP_CRPOSRANGE, 0, /* CRRANGE, CRMINRANGE */
+ 0, 0, 0, 0, /* CRPOS{STAR,PLUS,QUERY,RANGE} */
+
+ 0, 0, 0, /* CLASS, NCLASS, XCLASS */
+ 0, 0, /* REF, REFI */
+ 0, 0, /* DNREF, DNREFI */
+ 0, 0 /* RECURSE, CALLOUT */
+};
+
+
+
+/*************************************************
+* Find an error text *
+*************************************************/
+
+/* The error texts are now all in one long string, to save on relocations. As
+some of the text is of unknown length, we can't use a table of offsets.
+Instead, just count through the strings. This is not a performance issue
+because it happens only when there has been a compilation error.
+
+Argument: the error number
+Returns: pointer to the error string
+*/
+
+static const char *
+find_error_text(int n)
+{
+const char *s = error_texts;
+for (; n > 0; n--)
+ {
+ while (*s++ != CHAR_NULL) {};
+ if (*s == CHAR_NULL) return "Error text not found (please report)";
+ }
+return s;
+}
+
+
+
+/*************************************************
+* Expand the workspace *
+*************************************************/
+
+/* This function is called during the second compiling phase, if the number of
+forward references fills the existing workspace, which is originally a block on
+the stack. A larger block is obtained from malloc() unless the ultimate limit
+has been reached or the increase will be rather small.
+
+Argument: pointer to the compile data block
+Returns: 0 if all went well, else an error number
+*/
+
+static int
+expand_workspace(compile_data *cd)
+{
+pcre_uchar *newspace;
+int newsize = cd->workspace_size * 2;
+
+if (newsize > COMPILE_WORK_SIZE_MAX) newsize = COMPILE_WORK_SIZE_MAX;
+if (cd->workspace_size >= COMPILE_WORK_SIZE_MAX ||
+ newsize - cd->workspace_size < WORK_SIZE_SAFETY_MARGIN)
+ return ERR72;
+
+newspace = (PUBL(malloc))(IN_UCHARS(newsize));
+if (newspace == NULL) return ERR21;
+memcpy(newspace, cd->start_workspace, cd->workspace_size * sizeof(pcre_uchar));
+cd->hwm = (pcre_uchar *)newspace + (cd->hwm - cd->start_workspace);
+if (cd->workspace_size > COMPILE_WORK_SIZE)
+ (PUBL(free))((void *)cd->start_workspace);
+cd->start_workspace = newspace;
+cd->workspace_size = newsize;
+return 0;
+}
+
+
+
+/*************************************************
+* Check for counted repeat *
+*************************************************/
+
+/* This function is called when a '{' is encountered in a place where it might
+start a quantifier. It looks ahead to see if it really is a quantifier or not.
+It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd}
+where the ddds are digits.
+
+Arguments:
+ p pointer to the first char after '{'
+
+Returns: TRUE or FALSE
+*/
+
+static BOOL
+is_counted_repeat(const pcre_uchar *p)
+{
+if (!IS_DIGIT(*p)) return FALSE;
+p++;
+while (IS_DIGIT(*p)) p++;
+if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE;
+
+if (*p++ != CHAR_COMMA) return FALSE;
+if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE;
+
+if (!IS_DIGIT(*p)) return FALSE;
+p++;
+while (IS_DIGIT(*p)) p++;
+
+return (*p == CHAR_RIGHT_CURLY_BRACKET);
+}
+
+
+
+/*************************************************
+* Handle escapes *
+*************************************************/
+
+/* This function is called when a \ has been encountered. It either returns a
+positive value for a simple escape such as \n, or 0 for a data character which
+will be placed in chptr. A backreference to group n is returned as negative n.
+When UTF-8 is enabled, a positive value greater than 255 may be returned in
+chptr. On entry, ptr is pointing at the \. On exit, it is on the final
+character of the escape sequence.
+
+Arguments:
+ ptrptr points to the pattern position pointer
+ chptr points to a returned data character
+ errorcodeptr points to the errorcode variable
+ bracount number of previous extracting brackets
+ options the options bits
+ isclass TRUE if inside a character class
+
+Returns: zero => a data character
+ positive => a special escape sequence
+ negative => a back reference
+ on error, errorcodeptr is set
+*/
+
+static int
+check_escape(const pcre_uchar **ptrptr, pcre_uint32 *chptr, int *errorcodeptr,
+ int bracount, int options, BOOL isclass)
+{
+/* PCRE_UTF16 has the same value as PCRE_UTF8. */
+BOOL utf = (options & PCRE_UTF8) != 0;
+const pcre_uchar *ptr = *ptrptr + 1;
+pcre_uint32 c;
+int escape = 0;
+int i;
+
+GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */
+ptr--; /* Set pointer back to the last byte */
+
+/* If backslash is at the end of the pattern, it's an error. */
+
+if (c == CHAR_NULL) *errorcodeptr = ERR1;
+
+/* Non-alphanumerics are literals. For digits or letters, do an initial lookup
+in a table. A non-zero result is something that can be returned immediately.
+Otherwise further processing may be required. */
+
+#ifndef EBCDIC /* ASCII/UTF-8 coding */
+/* Not alphanumeric */
+else if (c < CHAR_0 || c > CHAR_z) {}
+else if ((i = escapes[c - CHAR_0]) != 0)
+ { if (i > 0) c = (pcre_uint32)i; else escape = -i; }
+
+#else /* EBCDIC coding */
+/* Not alphanumeric */
+else if (c < CHAR_a || (!MAX_255(c) || (ebcdic_chartab[c] & 0x0E) == 0)) {}
+else if ((i = escapes[c - 0x48]) != 0) { if (i > 0) c = (pcre_uint32)i; else escape = -i; }
+#endif
+
+/* Escapes that need further processing, or are illegal. */
+
+else
+ {
+ const pcre_uchar *oldptr;
+ BOOL braced, negated, overflow;
+ int s;
+
+ switch (c)
+ {
+ /* A number of Perl escapes are not handled by PCRE. We give an explicit
+ error. */
+
+ case CHAR_l:
+ case CHAR_L:
+ *errorcodeptr = ERR37;
+ break;
+
+ case CHAR_u:
+ if ((options & PCRE_JAVASCRIPT_COMPAT) != 0)
+ {
+ /* In JavaScript, \u must be followed by four hexadecimal numbers.
+ Otherwise it is a lowercase u letter. */
+ if (MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0
+ && MAX_255(ptr[2]) && (digitab[ptr[2]] & ctype_xdigit) != 0
+ && MAX_255(ptr[3]) && (digitab[ptr[3]] & ctype_xdigit) != 0
+ && MAX_255(ptr[4]) && (digitab[ptr[4]] & ctype_xdigit) != 0)
+ {
+ c = 0;
+ for (i = 0; i < 4; ++i)
+ {
+ register pcre_uint32 cc = *(++ptr);
+#ifndef EBCDIC /* ASCII/UTF-8 coding */
+ if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */
+ c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10));
+#else /* EBCDIC coding */
+ if (cc >= CHAR_a && cc <= CHAR_z) cc += 64; /* Convert to upper case */
+ c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10));
+#endif
+ }
+
+#if defined COMPILE_PCRE8
+ if (c > (utf ? 0x10ffffU : 0xffU))
+#elif defined COMPILE_PCRE16
+ if (c > (utf ? 0x10ffffU : 0xffffU))
+#elif defined COMPILE_PCRE32
+ if (utf && c > 0x10ffffU)
+#endif
+ {
+ *errorcodeptr = ERR76;
+ }
+ else if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73;
+ }
+ }
+ else
+ *errorcodeptr = ERR37;
+ break;
+
+ case CHAR_U:
+ /* In JavaScript, \U is an uppercase U letter. */
+ if ((options & PCRE_JAVASCRIPT_COMPAT) == 0) *errorcodeptr = ERR37;
+ break;
+
+ /* In a character class, \g is just a literal "g". Outside a character
+ class, \g must be followed by one of a number of specific things:
+
+ (1) A number, either plain or braced. If positive, it is an absolute
+ backreference. If negative, it is a relative backreference. This is a Perl
+ 5.10 feature.
+
+ (2) Perl 5.10 also supports \g{name} as a reference to a named group. This
+ is part of Perl's movement towards a unified syntax for back references. As
+ this is synonymous with \k{name}, we fudge it up by pretending it really
+ was \k.
+
+ (3) For Oniguruma compatibility we also support \g followed by a name or a
+ number either in angle brackets or in single quotes. However, these are
+ (possibly recursive) subroutine calls, _not_ backreferences. Just return
+ the ESC_g code (cf \k). */
+
+ case CHAR_g:
+ if (isclass) break;
+ if (ptr[1] == CHAR_LESS_THAN_SIGN || ptr[1] == CHAR_APOSTROPHE)
+ {
+ escape = ESC_g;
+ break;
+ }
+
+ /* Handle the Perl-compatible cases */
+
+ if (ptr[1] == CHAR_LEFT_CURLY_BRACKET)
+ {
+ const pcre_uchar *p;
+ for (p = ptr+2; *p != CHAR_NULL && *p != CHAR_RIGHT_CURLY_BRACKET; p++)
+ if (*p != CHAR_MINUS && !IS_DIGIT(*p)) break;
+ if (*p != CHAR_NULL && *p != CHAR_RIGHT_CURLY_BRACKET)
+ {
+ escape = ESC_k;
+ break;
+ }
+ braced = TRUE;
+ ptr++;
+ }
+ else braced = FALSE;
+
+ if (ptr[1] == CHAR_MINUS)
+ {
+ negated = TRUE;
+ ptr++;
+ }
+ else negated = FALSE;
+
+ /* The integer range is limited by the machine's int representation. */
+ s = 0;
+ overflow = FALSE;
+ while (IS_DIGIT(ptr[1]))
+ {
+ if (s > INT_MAX / 10 - 1) /* Integer overflow */
+ {
+ overflow = TRUE;
+ break;
+ }
+ s = s * 10 + (int)(*(++ptr) - CHAR_0);
+ }
+ if (overflow) /* Integer overflow */
+ {
+ while (IS_DIGIT(ptr[1]))
+ ptr++;
+ *errorcodeptr = ERR61;
+ break;
+ }
+
+ if (braced && *(++ptr) != CHAR_RIGHT_CURLY_BRACKET)
+ {
+ *errorcodeptr = ERR57;
+ break;
+ }
+
+ if (s == 0)
+ {
+ *errorcodeptr = ERR58;
+ break;
+ }
+
+ if (negated)
+ {
+ if (s > bracount)
+ {
+ *errorcodeptr = ERR15;
+ break;
+ }
+ s = bracount - (s - 1);
+ }
+
+ escape = -s;
+ break;
+
+ /* The handling of escape sequences consisting of a string of digits
+ starting with one that is not zero is not straightforward. Perl has changed
+ over the years. Nowadays \g{} for backreferences and \o{} for octal are
+ recommended to avoid the ambiguities in the old syntax.
+
+ Outside a character class, the digits are read as a decimal number. If the
+ number is less than 8 (used to be 10), or if there are that many previous
+ extracting left brackets, then it is a back reference. Otherwise, up to
+ three octal digits are read to form an escaped byte. Thus \123 is likely to
+ be octal 123 (cf \0123, which is octal 012 followed by the literal 3). If
+ the octal value is greater than 377, the least significant 8 bits are
+ taken. \8 and \9 are treated as the literal characters 8 and 9.
+
+ Inside a character class, \ followed by a digit is always either a literal
+ 8 or 9 or an octal number. */
+
+ case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4: case CHAR_5:
+ case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9:
+
+ if (!isclass)
+ {
+ oldptr = ptr;
+ /* The integer range is limited by the machine's int representation. */
+ s = (int)(c -CHAR_0);
+ overflow = FALSE;
+ while (IS_DIGIT(ptr[1]))
+ {
+ if (s > INT_MAX / 10 - 1) /* Integer overflow */
+ {
+ overflow = TRUE;
+ break;
+ }
+ s = s * 10 + (int)(*(++ptr) - CHAR_0);
+ }
+ if (overflow) /* Integer overflow */
+ {
+ while (IS_DIGIT(ptr[1]))
+ ptr++;
+ *errorcodeptr = ERR61;
+ break;
+ }
+ if (s < 8 || s <= bracount) /* Check for back reference */
+ {
+ escape = -s;
+ break;
+ }
+ ptr = oldptr; /* Put the pointer back and fall through */
+ }
+
+ /* Handle a digit following \ when the number is not a back reference. If
+ the first digit is 8 or 9, Perl used to generate a binary zero byte and
+ then treat the digit as a following literal. At least by Perl 5.18 this
+ changed so as not to insert the binary zero. */
+
+ if ((c = *ptr) >= CHAR_8) break;
+
+ /* Fall through with a digit less than 8 */
+
+ /* \0 always starts an octal number, but we may drop through to here with a
+ larger first octal digit. The original code used just to take the least
+ significant 8 bits of octal numbers (I think this is what early Perls used
+ to do). Nowadays we allow for larger numbers in UTF-8 mode and 16-bit mode,
+ but no more than 3 octal digits. */
+
+ case CHAR_0:
+ c -= CHAR_0;
+ while(i++ < 2 && ptr[1] >= CHAR_0 && ptr[1] <= CHAR_7)
+ c = c * 8 + *(++ptr) - CHAR_0;
+#ifdef COMPILE_PCRE8
+ if (!utf && c > 0xff) *errorcodeptr = ERR51;
+#endif
+ break;
+
+ /* \o is a relatively new Perl feature, supporting a more general way of
+ specifying character codes in octal. The only supported form is \o{ddd}. */
+
+ case CHAR_o:
+ if (ptr[1] != CHAR_LEFT_CURLY_BRACKET) *errorcodeptr = ERR81; else
+ {
+ ptr += 2;
+ c = 0;
+ overflow = FALSE;
+ while (*ptr >= CHAR_0 && *ptr <= CHAR_7)
+ {
+ register pcre_uint32 cc = *ptr++;
+ if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */
+#ifdef COMPILE_PCRE32
+ if (c >= 0x20000000l) { overflow = TRUE; break; }
+#endif
+ c = (c << 3) + cc - CHAR_0 ;
+#if defined COMPILE_PCRE8
+ if (c > (utf ? 0x10ffffU : 0xffU)) { overflow = TRUE; break; }
+#elif defined COMPILE_PCRE16
+ if (c > (utf ? 0x10ffffU : 0xffffU)) { overflow = TRUE; break; }
+#elif defined COMPILE_PCRE32
+ if (utf && c > 0x10ffffU) { overflow = TRUE; break; }
+#endif
+ }
+ if (overflow)
+ {
+ while (*ptr >= CHAR_0 && *ptr <= CHAR_7) ptr++;
+ *errorcodeptr = ERR34;
+ }
+ else if (*ptr == CHAR_RIGHT_CURLY_BRACKET)
+ {
+ if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73;
+ }
+ else *errorcodeptr = ERR80;
+ }
+ break;
+
+ /* \x is complicated. In JavaScript, \x must be followed by two hexadecimal
+ numbers. Otherwise it is a lowercase x letter. */
+
+ case CHAR_x:
+ if ((options & PCRE_JAVASCRIPT_COMPAT) != 0)
+ {
+ if (MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0
+ && MAX_255(ptr[2]) && (digitab[ptr[2]] & ctype_xdigit) != 0)
+ {
+ c = 0;
+ for (i = 0; i < 2; ++i)
+ {
+ register pcre_uint32 cc = *(++ptr);
+#ifndef EBCDIC /* ASCII/UTF-8 coding */
+ if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */
+ c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10));
+#else /* EBCDIC coding */
+ if (cc >= CHAR_a && cc <= CHAR_z) cc += 64; /* Convert to upper case */
+ c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10));
+#endif
+ }
+ }
+ } /* End JavaScript handling */
+
+ /* Handle \x in Perl's style. \x{ddd} is a character number which can be
+ greater than 0xff in utf 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
+ that, for example \x{zz} matches a binary zero. This seems crazy, so PCRE
+ now gives an error. */
+
+ else
+ {
+ if (ptr[1] == CHAR_LEFT_CURLY_BRACKET)
+ {
+ ptr += 2;
+ c = 0;
+ overflow = FALSE;
+ while (MAX_255(*ptr) && (digitab[*ptr] & ctype_xdigit) != 0)
+ {
+ register pcre_uint32 cc = *ptr++;
+ if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */
+
+#ifdef COMPILE_PCRE32
+ if (c >= 0x10000000l) { overflow = TRUE; break; }
+#endif
+
+#ifndef EBCDIC /* ASCII/UTF-8 coding */
+ if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */
+ c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10));
+#else /* EBCDIC coding */
+ if (cc >= CHAR_a && cc <= CHAR_z) cc += 64; /* Convert to upper case */
+ c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10));
+#endif
+
+#if defined COMPILE_PCRE8
+ if (c > (utf ? 0x10ffffU : 0xffU)) { overflow = TRUE; break; }
+#elif defined COMPILE_PCRE16
+ if (c > (utf ? 0x10ffffU : 0xffffU)) { overflow = TRUE; break; }
+#elif defined COMPILE_PCRE32
+ if (utf && c > 0x10ffffU) { overflow = TRUE; break; }
+#endif
+ }
+
+ if (overflow)
+ {
+ while (MAX_255(*ptr) && (digitab[*ptr] & ctype_xdigit) != 0) ptr++;
+ *errorcodeptr = ERR34;
+ }
+
+ else if (*ptr == CHAR_RIGHT_CURLY_BRACKET)
+ {
+ if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73;
+ }
+
+ /* If the sequence of hex digits does not end with '}', give an error.
+ We used just to recognize this construct and fall through to the normal
+ \x handling, but nowadays Perl gives an error, which seems much more
+ sensible, so we do too. */
+
+ else *errorcodeptr = ERR79;
+ } /* End of \x{} processing */
+
+ /* Read a single-byte hex-defined char (up to two hex digits after \x) */
+
+ else
+ {
+ c = 0;
+ while (i++ < 2 && MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0)
+ {
+ pcre_uint32 cc; /* Some compilers don't like */
+ cc = *(++ptr); /* ++ in initializers */
+#ifndef EBCDIC /* ASCII/UTF-8 coding */
+ if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */
+ c = c * 16 + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10));
+#else /* EBCDIC coding */
+ if (cc <= CHAR_z) cc += 64; /* Convert to upper case */
+ c = c * 16 + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10));
+#endif
+ }
+ } /* End of \xdd handling */
+ } /* End of Perl-style \x handling */
+ break;
+
+ /* For \c, a following letter is upper-cased; then the 0x40 bit is flipped.
+ An error is given if the byte following \c is not an ASCII character. This
+ coding is ASCII-specific, but then the whole concept of \cx is
+ ASCII-specific. (However, an EBCDIC equivalent has now been added.) */
+
+ case CHAR_c:
+ c = *(++ptr);
+ if (c == CHAR_NULL)
+ {
+ *errorcodeptr = ERR2;
+ break;
+ }
+#ifndef EBCDIC /* ASCII/UTF-8 coding */
+ if (c > 127) /* Excludes all non-ASCII in either mode */
+ {
+ *errorcodeptr = ERR68;
+ break;
+ }
+ if (c >= CHAR_a && c <= CHAR_z) c -= 32;
+ c ^= 0x40;
+#else /* EBCDIC coding */
+ if (c >= CHAR_a && c <= CHAR_z) c += 64;
+ c ^= 0xC0;
+#endif
+ break;
+
+ /* PCRE_EXTRA enables extensions to Perl in the matter of escapes. Any
+ other alphanumeric following \ is an error if PCRE_EXTRA was set;
+ otherwise, for Perl compatibility, it is a literal. This code looks a bit
+ odd, but there used to be some cases other than the default, and there may
+ be again in future, so I haven't "optimized" it. */
+
+ default:
+ if ((options & PCRE_EXTRA) != 0) switch(c)
+ {
+ default:
+ *errorcodeptr = ERR3;
+ break;
+ }
+ break;
+ }
+ }
+
+/* Perl supports \N{name} for character names, as well as plain \N for "not
+newline". PCRE does not support \N{name}. However, it does support
+quantification such as \N{2,3}. */
+
+if (escape == ESC_N && ptr[1] == CHAR_LEFT_CURLY_BRACKET &&
+ !is_counted_repeat(ptr+2))
+ *errorcodeptr = ERR37;
+
+/* If PCRE_UCP is set, we change the values for \d etc. */
+
+if ((options & PCRE_UCP) != 0 && escape >= ESC_D && escape <= ESC_w)
+ escape += (ESC_DU - ESC_D);
+
+/* Set the pointer to the final character before returning. */
+
+*ptrptr = ptr;
+*chptr = c;
+return escape;
+}
+
+
+
+#ifdef SUPPORT_UCP
+/*************************************************
+* Handle \P and \p *
+*************************************************/
+
+/* This function is called after \P or \p has been encountered, provided that
+PCRE is compiled with support for Unicode properties. On entry, ptrptr is
+pointing at the P or p. On exit, it is pointing at the final character of the
+escape sequence.
+
+Argument:
+ ptrptr points to the pattern position pointer
+ negptr points to a boolean that is set TRUE for negation else FALSE
+ ptypeptr points to an unsigned int that is set to the type value
+ pdataptr points to an unsigned int that is set to the detailed property value
+ errorcodeptr points to the error code variable
+
+Returns: TRUE if the type value was found, or FALSE for an invalid type
+*/
+
+static BOOL
+get_ucp(const pcre_uchar **ptrptr, BOOL *negptr, unsigned int *ptypeptr,
+ unsigned int *pdataptr, int *errorcodeptr)
+{
+pcre_uchar c;
+int i, bot, top;
+const pcre_uchar *ptr = *ptrptr;
+pcre_uchar name[32];
+
+c = *(++ptr);
+if (c == CHAR_NULL) goto ERROR_RETURN;
+
+*negptr = FALSE;
+
+/* \P or \p can be followed by a name in {}, optionally preceded by ^ for
+negation. */
+
+if (c == CHAR_LEFT_CURLY_BRACKET)
+ {
+ if (ptr[1] == CHAR_CIRCUMFLEX_ACCENT)
+ {
+ *negptr = TRUE;
+ ptr++;
+ }
+ for (i = 0; i < (int)(sizeof(name) / sizeof(pcre_uchar)) - 1; i++)
+ {
+ c = *(++ptr);
+ if (c == CHAR_NULL) goto ERROR_RETURN;
+ if (c == CHAR_RIGHT_CURLY_BRACKET) break;
+ name[i] = c;
+ }
+ if (c != CHAR_RIGHT_CURLY_BRACKET) goto ERROR_RETURN;
+ name[i] = 0;
+ }
+
+/* Otherwise there is just one following character */
+
+else
+ {
+ name[0] = c;
+ name[1] = 0;
+ }
+
+*ptrptr = ptr;
+
+/* Search for a recognized property name using binary chop */
+
+bot = 0;
+top = PRIV(utt_size);
+
+while (bot < top)
+ {
+ int r;
+ i = (bot + top) >> 1;
+ r = STRCMP_UC_C8(name, PRIV(utt_names) + PRIV(utt)[i].name_offset);
+ if (r == 0)
+ {
+ *ptypeptr = PRIV(utt)[i].type;
+ *pdataptr = PRIV(utt)[i].value;
+ return TRUE;
+ }
+ if (r > 0) bot = i + 1; else top = i;
+ }
+
+*errorcodeptr = ERR47;
+*ptrptr = ptr;
+return FALSE;
+
+ERROR_RETURN:
+*errorcodeptr = ERR46;
+*ptrptr = ptr;
+return FALSE;
+}
+#endif
+
+
+
+/*************************************************
+* Read repeat counts *
+*************************************************/
+
+/* Read an item of the form {n,m} and return the values. This is called only
+after is_counted_repeat() has confirmed that a repeat-count quantifier exists,
+so the syntax is guaranteed to be correct, but we need to check the values.
+
+Arguments:
+ p pointer to first char after '{'
+ minp pointer to int for min
+ maxp pointer to int for max
+ returned as -1 if no max
+ errorcodeptr points to error code variable
+
+Returns: pointer to '}' on success;
+ current ptr on error, with errorcodeptr set non-zero
+*/
+
+static const pcre_uchar *
+read_repeat_counts(const pcre_uchar *p, int *minp, int *maxp, int *errorcodeptr)
+{
+int min = 0;
+int max = -1;
+
+/* Read the minimum value and do a paranoid check: a negative value indicates
+an integer overflow. */
+
+while (IS_DIGIT(*p)) min = min * 10 + (int)(*p++ - CHAR_0);
+if (min < 0 || min > 65535)
+ {
+ *errorcodeptr = ERR5;
+ return p;
+ }
+
+/* Read the maximum value if there is one, and again do a paranoid on its size.
+Also, max must not be less than min. */
+
+if (*p == CHAR_RIGHT_CURLY_BRACKET) max = min; else
+ {
+ if (*(++p) != CHAR_RIGHT_CURLY_BRACKET)
+ {
+ max = 0;
+ while(IS_DIGIT(*p)) max = max * 10 + (int)(*p++ - CHAR_0);
+ if (max < 0 || max > 65535)
+ {
+ *errorcodeptr = ERR5;
+ return p;
+ }
+ if (max < min)
+ {
+ *errorcodeptr = ERR4;
+ return p;
+ }
+ }
+ }
+
+/* Fill in the required variables, and pass back the pointer to the terminating
+'}'. */
+
+*minp = min;
+*maxp = max;
+return p;
+}
+
+
+
+/*************************************************
+* Find first significant op code *
+*************************************************/
+
+/* This is called by several functions that scan a compiled expression looking
+for a fixed first character, or an anchoring op code etc. It skips over things
+that do not influence this. For some calls, it makes sense to skip negative
+forward and all backward assertions, and also the \b assertion; for others it
+does not.
+
+Arguments:
+ code pointer to the start of the group
+ skipassert TRUE if certain assertions are to be skipped
+
+Returns: pointer to the first significant opcode
+*/
+
+static const pcre_uchar*
+first_significant_code(const pcre_uchar *code, BOOL skipassert)
+{
+for (;;)
+ {
+ switch ((int)*code)
+ {
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ if (!skipassert) return code;
+ do code += GET(code, 1); while (*code == OP_ALT);
+ code += PRIV(OP_lengths)[*code];
+ break;
+
+ case OP_WORD_BOUNDARY:
+ case OP_NOT_WORD_BOUNDARY:
+ if (!skipassert) return code;
+ /* Fall through */
+
+ case OP_CALLOUT:
+ case OP_CREF:
+ case OP_DNCREF:
+ case OP_RREF:
+ case OP_DNRREF:
+ case OP_DEF:
+ code += PRIV(OP_lengths)[*code];
+ break;
+
+ default:
+ return code;
+ }
+ }
+/* Control never reaches here */
+}
+
+
+
+/*************************************************
+* Find the fixed length of a branch *
+*************************************************/
+
+/* Scan a branch and compute the fixed length of subject that will match it,
+if the length is fixed. This is needed for dealing with backward assertions.
+In UTF8 mode, the result is in characters rather than bytes. The branch is
+temporarily terminated with OP_END when this function is called.
+
+This function is called when a backward assertion is encountered, so that if it
+fails, the error message can point to the correct place in the pattern.
+However, we cannot do this when the assertion contains subroutine calls,
+because they can be forward references. We solve this by remembering this case
+and doing the check at the end; a flag specifies which mode we are running in.
+
+Arguments:
+ code points to the start of the pattern (the bracket)
+ utf TRUE in UTF-8 / UTF-16 / UTF-32 mode
+ atend TRUE if called when the pattern is complete
+ cd the "compile data" structure
+
+Returns: the fixed length,
+ or -1 if there is no fixed length,
+ or -2 if \C was encountered (in UTF-8 mode only)
+ or -3 if an OP_RECURSE item was encountered and atend is FALSE
+ or -4 if an unknown opcode was encountered (internal error)
+*/
+
+static int
+find_fixedlength(pcre_uchar *code, BOOL utf, BOOL atend, compile_data *cd)
+{
+int length = -1;
+
+register int branchlength = 0;
+register pcre_uchar *cc = code + 1 + LINK_SIZE;
+
+/* 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. */
+
+for (;;)
+ {
+ int d;
+ pcre_uchar *ce, *cs;
+ register pcre_uchar op = *cc;
+
+ switch (op)
+ {
+ /* We only need to continue for OP_CBRA (normal capturing bracket) and
+ OP_BRA (normal non-capturing bracket) because the other variants of these
+ opcodes are all concerned with unlimited repeated groups, which of course
+ are not of fixed length. */
+
+ case OP_CBRA:
+ case OP_BRA:
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ case OP_COND:
+ d = find_fixedlength(cc + ((op == OP_CBRA)? IMM2_SIZE : 0), utf, atend, cd);
+ if (d < 0) return d;
+ branchlength += d;
+ do cc += GET(cc, 1); while (*cc == OP_ALT);
+ cc += 1 + LINK_SIZE;
+ break;
+
+ /* 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. An ACCEPT is effectively
+ an ALT. If it is END it's the end of the outer call. All can be handled by
+ the same code. Note that we must not include the OP_KETRxxx opcodes here,
+ because they all imply an unlimited repeat. */
+
+ case OP_ALT:
+ case OP_KET:
+ case OP_END:
+ case OP_ACCEPT:
+ case OP_ASSERT_ACCEPT:
+ if (length < 0) length = branchlength;
+ else if (length != branchlength) return -1;
+ if (*cc != OP_ALT) return length;
+ cc += 1 + LINK_SIZE;
+ branchlength = 0;
+ break;
+
+ /* A true recursion implies not fixed length, but a subroutine call may
+ be OK. If the subroutine is a forward reference, we can't deal with
+ it until the end of the pattern, so return -3. */
+
+ case OP_RECURSE:
+ if (!atend) return -3;
+ cs = ce = (pcre_uchar *)cd->start_code + GET(cc, 1); /* Start subpattern */
+ do ce += GET(ce, 1); while (*ce == OP_ALT); /* End subpattern */
+ if (cc > cs && cc < ce) return -1; /* Recursion */
+ d = find_fixedlength(cs + IMM2_SIZE, utf, atend, cd);
+ if (d < 0) return d;
+ branchlength += d;
+ cc += 1 + LINK_SIZE;
+ break;
+
+ /* Skip over assertive subpatterns */
+
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ do cc += GET(cc, 1); while (*cc == OP_ALT);
+ cc += PRIV(OP_lengths)[*cc];
+ break;
+
+ /* Skip over things that don't match chars */
+
+ case OP_MARK:
+ case OP_PRUNE_ARG:
+ case OP_SKIP_ARG:
+ case OP_THEN_ARG:
+ cc += cc[1] + PRIV(OP_lengths)[*cc];
+ break;
+
+ case OP_CALLOUT:
+ case OP_CIRC:
+ case OP_CIRCM:
+ case OP_CLOSE:
+ case OP_COMMIT:
+ case OP_CREF:
+ case OP_DEF:
+ case OP_DNCREF:
+ case OP_DNRREF:
+ case OP_DOLL:
+ case OP_DOLLM:
+ case OP_EOD:
+ case OP_EODN:
+ case OP_FAIL:
+ case OP_NOT_WORD_BOUNDARY:
+ case OP_PRUNE:
+ case OP_REVERSE:
+ case OP_RREF:
+ case OP_SET_SOM:
+ case OP_SKIP:
+ case OP_SOD:
+ case OP_SOM:
+ case OP_THEN:
+ case OP_WORD_BOUNDARY:
+ cc += PRIV(OP_lengths)[*cc];
+ break;
+
+ /* Handle literal characters */
+
+ case OP_CHAR:
+ case OP_CHARI:
+ case OP_NOT:
+ case OP_NOTI:
+ branchlength++;
+ cc += 2;
+#ifdef SUPPORT_UTF
+ if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ break;
+
+ /* Handle exact repetitions. The count is already in characters, but we
+ need to skip over a multibyte character in UTF8 mode. */
+
+ case OP_EXACT:
+ case OP_EXACTI:
+ case OP_NOTEXACT:
+ case OP_NOTEXACTI:
+ branchlength += (int)GET2(cc,1);
+ cc += 2 + IMM2_SIZE;
+#ifdef SUPPORT_UTF
+ if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ break;
+
+ case OP_TYPEEXACT:
+ branchlength += GET2(cc,1);
+ if (cc[1 + IMM2_SIZE] == OP_PROP || cc[1 + IMM2_SIZE] == OP_NOTPROP)
+ cc += 2;
+ cc += 1 + IMM2_SIZE + 1;
+ break;
+
+ /* Handle single-char matchers */
+
+ case OP_PROP:
+ case OP_NOTPROP:
+ cc += 2;
+ /* Fall through */
+
+ case OP_HSPACE:
+ case OP_VSPACE:
+ case OP_NOT_HSPACE:
+ case OP_NOT_VSPACE:
+ case OP_NOT_DIGIT:
+ case OP_DIGIT:
+ case OP_NOT_WHITESPACE:
+ case OP_WHITESPACE:
+ case OP_NOT_WORDCHAR:
+ case OP_WORDCHAR:
+ case OP_ANY:
+ case OP_ALLANY:
+ branchlength++;
+ cc++;
+ break;
+
+ /* The single-byte matcher isn't allowed. This only happens in UTF-8 mode;
+ otherwise \C is coded as OP_ALLANY. */
+
+ case OP_ANYBYTE:
+ return -2;
+
+ /* Check a class for variable quantification */
+
+ case OP_CLASS:
+ case OP_NCLASS:
+#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ case OP_XCLASS:
+ /* The original code caused an unsigned overflow in 64 bit systems,
+ so now we use a conditional statement. */
+ if (op == OP_XCLASS)
+ cc += GET(cc, 1);
+ else
+ cc += PRIV(OP_lengths)[OP_CLASS];
+#else
+ cc += PRIV(OP_lengths)[OP_CLASS];
+#endif
+
+ switch (*cc)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ case OP_CRPOSSTAR:
+ case OP_CRPOSPLUS:
+ case OP_CRPOSQUERY:
+ return -1;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ case OP_CRPOSRANGE:
+ if (GET2(cc,1) != GET2(cc,1+IMM2_SIZE)) return -1;
+ branchlength += (int)GET2(cc,1);
+ cc += 1 + 2 * IMM2_SIZE;
+ break;
+
+ default:
+ branchlength++;
+ }
+ break;
+
+ /* Anything else is variable length */
+
+ case OP_ANYNL:
+ case OP_BRAMINZERO:
+ case OP_BRAPOS:
+ case OP_BRAPOSZERO:
+ case OP_BRAZERO:
+ case OP_CBRAPOS:
+ case OP_EXTUNI:
+ case OP_KETRMAX:
+ case OP_KETRMIN:
+ case OP_KETRPOS:
+ case OP_MINPLUS:
+ case OP_MINPLUSI:
+ case OP_MINQUERY:
+ case OP_MINQUERYI:
+ case OP_MINSTAR:
+ case OP_MINSTARI:
+ case OP_MINUPTO:
+ case OP_MINUPTOI:
+ case OP_NOTMINPLUS:
+ case OP_NOTMINPLUSI:
+ case OP_NOTMINQUERY:
+ case OP_NOTMINQUERYI:
+ case OP_NOTMINSTAR:
+ case OP_NOTMINSTARI:
+ case OP_NOTMINUPTO:
+ case OP_NOTMINUPTOI:
+ case OP_NOTPLUS:
+ case OP_NOTPLUSI:
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSPLUSI:
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSQUERYI:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSSTARI:
+ case OP_NOTPOSUPTO:
+ case OP_NOTPOSUPTOI:
+ case OP_NOTQUERY:
+ case OP_NOTQUERYI:
+ case OP_NOTSTAR:
+ case OP_NOTSTARI:
+ case OP_NOTUPTO:
+ case OP_NOTUPTOI:
+ case OP_PLUS:
+ case OP_PLUSI:
+ case OP_POSPLUS:
+ case OP_POSPLUSI:
+ case OP_POSQUERY:
+ case OP_POSQUERYI:
+ case OP_POSSTAR:
+ case OP_POSSTARI:
+ case OP_POSUPTO:
+ case OP_POSUPTOI:
+ case OP_QUERY:
+ case OP_QUERYI:
+ case OP_REF:
+ case OP_REFI:
+ case OP_DNREF:
+ case OP_DNREFI:
+ case OP_SBRA:
+ case OP_SBRAPOS:
+ case OP_SCBRA:
+ case OP_SCBRAPOS:
+ case OP_SCOND:
+ case OP_SKIPZERO:
+ case OP_STAR:
+ case OP_STARI:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEMINQUERY:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEMINUPTO:
+ case OP_TYPEPLUS:
+ case OP_TYPEPOSPLUS:
+ case OP_TYPEPOSQUERY:
+ case OP_TYPEPOSSTAR:
+ case OP_TYPEPOSUPTO:
+ case OP_TYPEQUERY:
+ case OP_TYPESTAR:
+ case OP_TYPEUPTO:
+ case OP_UPTO:
+ case OP_UPTOI:
+ return -1;
+
+ /* Catch unrecognized opcodes so that when new ones are added they
+ are not forgotten, as has happened in the past. */
+
+ default:
+ return -4;
+ }
+ }
+/* Control never gets here */
+}
+
+
+
+/*************************************************
+* Scan compiled regex for specific bracket *
+*************************************************/
+
+/* This little function scans through a compiled pattern until it finds a
+capturing bracket with the given number, or, if the number is negative, an
+instance of OP_REVERSE for a lookbehind. The function is global in the C sense
+so that it can be called from pcre_study() when finding the minimum matching
+length.
+
+Arguments:
+ code points to start of expression
+ utf TRUE in UTF-8 / UTF-16 / UTF-32 mode
+ number the required bracket number or negative to find a lookbehind
+
+Returns: pointer to the opcode for the bracket, or NULL if not found
+*/
+
+const pcre_uchar *
+PRIV(find_bracket)(const pcre_uchar *code, BOOL utf, int number)
+{
+for (;;)
+ {
+ register pcre_uchar c = *code;
+
+ if (c == OP_END) return NULL;
+
+ /* XCLASS is used for classes that cannot be represented just by a bit
+ map. This includes negated single high-valued characters. The length in
+ the table is zero; the actual length is stored in the compiled code. */
+
+ if (c == OP_XCLASS) code += GET(code, 1);
+
+ /* Handle recursion */
+
+ else if (c == OP_REVERSE)
+ {
+ if (number < 0) return (pcre_uchar *)code;
+ code += PRIV(OP_lengths)[c];
+ }
+
+ /* Handle capturing bracket */
+
+ else if (c == OP_CBRA || c == OP_SCBRA ||
+ c == OP_CBRAPOS || c == OP_SCBRAPOS)
+ {
+ int n = (int)GET2(code, 1+LINK_SIZE);
+ if (n == number) return (pcre_uchar *)code;
+ code += PRIV(OP_lengths)[c];
+ }
+
+ /* Otherwise, we can get the item's length from the table, except that for
+ repeated character types, we have to test for \p and \P, which have an extra
+ two bytes of parameters, and for MARK/PRUNE/SKIP/THEN with an argument, we
+ must add in its length. */
+
+ else
+ {
+ switch(c)
+ {
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ case OP_TYPEPOSSTAR:
+ case OP_TYPEPOSPLUS:
+ case OP_TYPEPOSQUERY:
+ if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
+ break;
+
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ case OP_TYPEEXACT:
+ case OP_TYPEPOSUPTO:
+ if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
+ code += 2;
+ break;
+
+ case OP_MARK:
+ case OP_PRUNE_ARG:
+ case OP_SKIP_ARG:
+ case OP_THEN_ARG:
+ code += code[1];
+ break;
+ }
+
+ /* Add in the fixed length from the table */
+
+ code += PRIV(OP_lengths)[c];
+
+ /* In UTF-8 mode, opcodes that are followed by a character may be followed by
+ a multi-byte character. The length in the table is a minimum, so we have to
+ arrange to skip the extra bytes. */
+
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (utf) switch(c)
+ {
+ case OP_CHAR:
+ case OP_CHARI:
+ case OP_EXACT:
+ case OP_EXACTI:
+ case OP_UPTO:
+ case OP_UPTOI:
+ case OP_MINUPTO:
+ case OP_MINUPTOI:
+ case OP_POSUPTO:
+ case OP_POSUPTOI:
+ case OP_STAR:
+ case OP_STARI:
+ case OP_MINSTAR:
+ case OP_MINSTARI:
+ case OP_POSSTAR:
+ case OP_POSSTARI:
+ case OP_PLUS:
+ case OP_PLUSI:
+ case OP_MINPLUS:
+ case OP_MINPLUSI:
+ case OP_POSPLUS:
+ case OP_POSPLUSI:
+ case OP_QUERY:
+ case OP_QUERYI:
+ case OP_MINQUERY:
+ case OP_MINQUERYI:
+ case OP_POSQUERY:
+ case OP_POSQUERYI:
+ if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);
+ break;
+ }
+#else
+ (void)(utf); /* Keep compiler happy by referencing function argument */
+#endif
+ }
+ }
+}
+
+
+
+/*************************************************
+* Scan compiled regex for recursion reference *
+*************************************************/
+
+/* This little function scans through a compiled pattern until it finds an
+instance of OP_RECURSE.
+
+Arguments:
+ code points to start of expression
+ utf TRUE in UTF-8 / UTF-16 / UTF-32 mode
+
+Returns: pointer to the opcode for OP_RECURSE, or NULL if not found
+*/
+
+static const pcre_uchar *
+find_recurse(const pcre_uchar *code, BOOL utf)
+{
+for (;;)
+ {
+ register pcre_uchar c = *code;
+ if (c == OP_END) return NULL;
+ if (c == OP_RECURSE) return code;
+
+ /* XCLASS is used for classes that cannot be represented just by a bit
+ map. This includes negated single high-valued characters. The length in
+ the table is zero; the actual length is stored in the compiled code. */
+
+ if (c == OP_XCLASS) code += GET(code, 1);
+
+ /* Otherwise, we can get the item's length from the table, except that for
+ repeated character types, we have to test for \p and \P, which have an extra
+ two bytes of parameters, and for MARK/PRUNE/SKIP/THEN with an argument, we
+ must add in its length. */
+
+ else
+ {
+ switch(c)
+ {
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ case OP_TYPEPOSSTAR:
+ case OP_TYPEPOSPLUS:
+ case OP_TYPEPOSQUERY:
+ if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
+ break;
+
+ case OP_TYPEPOSUPTO:
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ case OP_TYPEEXACT:
+ if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
+ code += 2;
+ break;
+
+ case OP_MARK:
+ case OP_PRUNE_ARG:
+ case OP_SKIP_ARG:
+ case OP_THEN_ARG:
+ code += code[1];
+ break;
+ }
+
+ /* Add in the fixed length from the table */
+
+ code += PRIV(OP_lengths)[c];
+
+ /* In UTF-8 mode, opcodes that are followed by a character may be followed
+ by a multi-byte character. The length in the table is a minimum, so we have
+ to arrange to skip the extra bytes. */
+
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (utf) switch(c)
+ {
+ case OP_CHAR:
+ case OP_CHARI:
+ case OP_NOT:
+ case OP_NOTI:
+ case OP_EXACT:
+ case OP_EXACTI:
+ case OP_NOTEXACT:
+ case OP_NOTEXACTI:
+ case OP_UPTO:
+ case OP_UPTOI:
+ case OP_NOTUPTO:
+ case OP_NOTUPTOI:
+ case OP_MINUPTO:
+ case OP_MINUPTOI:
+ case OP_NOTMINUPTO:
+ case OP_NOTMINUPTOI:
+ case OP_POSUPTO:
+ case OP_POSUPTOI:
+ case OP_NOTPOSUPTO:
+ case OP_NOTPOSUPTOI:
+ case OP_STAR:
+ case OP_STARI:
+ case OP_NOTSTAR:
+ case OP_NOTSTARI:
+ case OP_MINSTAR:
+ case OP_MINSTARI:
+ case OP_NOTMINSTAR:
+ case OP_NOTMINSTARI:
+ case OP_POSSTAR:
+ case OP_POSSTARI:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSSTARI:
+ case OP_PLUS:
+ case OP_PLUSI:
+ case OP_NOTPLUS:
+ case OP_NOTPLUSI:
+ case OP_MINPLUS:
+ case OP_MINPLUSI:
+ case OP_NOTMINPLUS:
+ case OP_NOTMINPLUSI:
+ case OP_POSPLUS:
+ case OP_POSPLUSI:
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSPLUSI:
+ case OP_QUERY:
+ case OP_QUERYI:
+ case OP_NOTQUERY:
+ case OP_NOTQUERYI:
+ case OP_MINQUERY:
+ case OP_MINQUERYI:
+ case OP_NOTMINQUERY:
+ case OP_NOTMINQUERYI:
+ case OP_POSQUERY:
+ case OP_POSQUERYI:
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSQUERYI:
+ if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);
+ break;
+ }
+#else
+ (void)(utf); /* Keep compiler happy by referencing function argument */
+#endif
+ }
+ }
+}
+
+
+
+/*************************************************
+* Scan compiled branch for non-emptiness *
+*************************************************/
+
+/* This function scans through a branch of a compiled pattern to see whether it
+can match the empty string or not. It is called from could_be_empty()
+below and from compile_branch() when checking for an unlimited repeat of a
+group that can match nothing. Note that first_significant_code() skips over
+backward and negative forward assertions when its final argument is TRUE. If we
+hit an unclosed bracket, we return "empty" - this means we've struck an inner
+bracket whose current branch will already have been scanned.
+
+Arguments:
+ code points to start of search
+ endcode points to where to stop
+ utf TRUE if in UTF-8 / UTF-16 / UTF-32 mode
+ cd contains pointers to tables etc.
+ recurses chain of recurse_check to catch mutual recursion
+
+Returns: TRUE if what is matched could be empty
+*/
+
+typedef struct recurse_check {
+ struct recurse_check *prev;
+ const pcre_uchar *group;
+} recurse_check;
+
+static BOOL
+could_be_empty_branch(const pcre_uchar *code, const pcre_uchar *endcode,
+ BOOL utf, compile_data *cd, recurse_check *recurses)
+{
+register pcre_uchar c;
+recurse_check this_recurse;
+
+for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
+ code < endcode;
+ code = first_significant_code(code + PRIV(OP_lengths)[c], TRUE))
+ {
+ const pcre_uchar *ccode;
+
+ c = *code;
+
+ /* Skip over forward assertions; the other assertions are skipped by
+ first_significant_code() with a TRUE final argument. */
+
+ if (c == OP_ASSERT)
+ {
+ do code += GET(code, 1); while (*code == OP_ALT);
+ c = *code;
+ continue;
+ }
+
+ /* For a recursion/subroutine call, if its end has been reached, which
+ implies a backward reference subroutine call, we can scan it. If it's a
+ forward reference subroutine call, we can't. To detect forward reference
+ we have to scan up the list that is kept in the workspace. This function is
+ called only when doing the real compile, not during the pre-compile that
+ measures the size of the compiled pattern. */
+
+ if (c == OP_RECURSE)
+ {
+ const pcre_uchar *scode = cd->start_code + GET(code, 1);
+ BOOL empty_branch;
+
+ /* Test for forward reference or uncompleted reference. This is disabled
+ when called to scan a completed pattern by setting cd->start_workspace to
+ NULL. */
+
+ if (cd->start_workspace != NULL)
+ {
+ const pcre_uchar *tcode;
+ for (tcode = cd->start_workspace; tcode < cd->hwm; tcode += LINK_SIZE)
+ if ((int)GET(tcode, 0) == (int)(code + 1 - cd->start_code)) return TRUE;
+ if (GET(scode, 1) == 0) return TRUE; /* Unclosed */
+ }
+
+ /* If we are scanning a completed pattern, there are no forward references
+ and all groups are complete. We need to detect whether this is a recursive
+ call, as otherwise there will be an infinite loop. If it is a recursion,
+ just skip over it. Simple recursions are easily detected. For mutual
+ recursions we keep a chain on the stack. */
+
+ else
+ {
+ recurse_check *r = recurses;
+ const pcre_uchar *endgroup = scode;
+
+ do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT);
+ if (code >= scode && code <= endgroup) continue; /* Simple recursion */
+
+ for (r = recurses; r != NULL; r = r->prev)
+ if (r->group == scode) break;
+ if (r != NULL) continue; /* Mutual recursion */
+ }
+
+ /* Completed reference; scan the referenced group, remembering it on the
+ stack chain to detect mutual recursions. */
+
+ empty_branch = FALSE;
+ this_recurse.prev = recurses;
+ this_recurse.group = scode;
+
+ do
+ {
+ if (could_be_empty_branch(scode, endcode, utf, cd, &this_recurse))
+ {
+ empty_branch = TRUE;
+ break;
+ }
+ scode += GET(scode, 1);
+ }
+ while (*scode == OP_ALT);
+
+ if (!empty_branch) return FALSE; /* All branches are non-empty */
+ continue;
+ }
+
+ /* Groups with zero repeats can of course be empty; skip them. */
+
+ if (c == OP_BRAZERO || c == OP_BRAMINZERO || c == OP_SKIPZERO ||
+ c == OP_BRAPOSZERO)
+ {
+ code += PRIV(OP_lengths)[c];
+ do code += GET(code, 1); while (*code == OP_ALT);
+ c = *code;
+ continue;
+ }
+
+ /* A nested group that is already marked as "could be empty" can just be
+ skipped. */
+
+ if (c == OP_SBRA || c == OP_SBRAPOS ||
+ c == OP_SCBRA || c == OP_SCBRAPOS)
+ {
+ do code += GET(code, 1); while (*code == OP_ALT);
+ c = *code;
+ continue;
+ }
+
+ /* For other groups, scan the branches. */
+
+ if (c == OP_BRA || c == OP_BRAPOS ||
+ c == OP_CBRA || c == OP_CBRAPOS ||
+ c == OP_ONCE || c == OP_ONCE_NC ||
+ c == OP_COND)
+ {
+ BOOL empty_branch;
+ if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */
+
+ /* If a conditional group has only one branch, there is a second, implied,
+ empty branch, so just skip over the conditional, because it could be empty.
+ Otherwise, scan the individual branches of the group. */
+
+ if (c == OP_COND && code[GET(code, 1)] != OP_ALT)
+ code += GET(code, 1);
+ else
+ {
+ empty_branch = FALSE;
+ do
+ {
+ if (!empty_branch && could_be_empty_branch(code, endcode, utf, cd, NULL))
+ empty_branch = TRUE;
+ code += GET(code, 1);
+ }
+ while (*code == OP_ALT);
+ if (!empty_branch) return FALSE; /* All branches are non-empty */
+ }
+
+ c = *code;
+ continue;
+ }
+
+ /* Handle the other opcodes */
+
+ switch (c)
+ {
+ /* Check for quantifiers after a class. XCLASS is used for classes that
+ cannot be represented just by a bit map. This includes negated single
+ high-valued characters. The length in PRIV(OP_lengths)[] is zero; the
+ actual length is stored in the compiled code, so we must update "code"
+ here. */
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+ ccode = code += GET(code, 1);
+ goto CHECK_CLASS_REPEAT;
+#endif
+
+ case OP_CLASS:
+ case OP_NCLASS:
+ ccode = code + PRIV(OP_lengths)[OP_CLASS];
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ CHECK_CLASS_REPEAT:
+#endif
+
+ switch (*ccode)
+ {
+ case OP_CRSTAR: /* These could be empty; continue */
+ case OP_CRMINSTAR:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ case OP_CRPOSSTAR:
+ case OP_CRPOSQUERY:
+ break;
+
+ default: /* Non-repeat => class must match */
+ case OP_CRPLUS: /* These repeats aren't empty */
+ case OP_CRMINPLUS:
+ case OP_CRPOSPLUS:
+ return FALSE;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ case OP_CRPOSRANGE:
+ if (GET2(ccode, 1) > 0) return FALSE; /* Minimum > 0 */
+ break;
+ }
+ break;
+
+ /* Opcodes that must match a character */
+
+ case OP_ANY:
+ case OP_ALLANY:
+ case OP_ANYBYTE:
+
+ case OP_PROP:
+ case OP_NOTPROP:
+ case OP_ANYNL:
+
+ case OP_NOT_HSPACE:
+ case OP_HSPACE:
+ case OP_NOT_VSPACE:
+ case OP_VSPACE:
+ case OP_EXTUNI:
+
+ case OP_NOT_DIGIT:
+ case OP_DIGIT:
+ case OP_NOT_WHITESPACE:
+ case OP_WHITESPACE:
+ case OP_NOT_WORDCHAR:
+ case OP_WORDCHAR:
+
+ case OP_CHAR:
+ case OP_CHARI:
+ case OP_NOT:
+ case OP_NOTI:
+
+ case OP_PLUS:
+ case OP_PLUSI:
+ case OP_MINPLUS:
+ case OP_MINPLUSI:
+
+ case OP_NOTPLUS:
+ case OP_NOTPLUSI:
+ case OP_NOTMINPLUS:
+ case OP_NOTMINPLUSI:
+
+ case OP_POSPLUS:
+ case OP_POSPLUSI:
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSPLUSI:
+
+ case OP_EXACT:
+ case OP_EXACTI:
+ case OP_NOTEXACT:
+ case OP_NOTEXACTI:
+
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEPOSPLUS:
+ case OP_TYPEEXACT:
+
+ return FALSE;
+
+ /* These are going to continue, as they may be empty, but we have to
+ fudge the length for the \p and \P cases. */
+
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPOSSTAR:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ case OP_TYPEPOSQUERY:
+ if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
+ break;
+
+ /* Same for these */
+
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ case OP_TYPEPOSUPTO:
+ if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
+ code += 2;
+ break;
+
+ /* End of branch */
+
+ case OP_KET:
+ case OP_KETRMAX:
+ case OP_KETRMIN:
+ case OP_KETRPOS:
+ case OP_ALT:
+ return TRUE;
+
+ /* In UTF-8 mode, STAR, MINSTAR, POSSTAR, QUERY, MINQUERY, POSQUERY, UPTO,
+ MINUPTO, and POSUPTO and their caseless and negative versions may be
+ followed by a multibyte character. */
+
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ case OP_STAR:
+ case OP_STARI:
+ case OP_NOTSTAR:
+ case OP_NOTSTARI:
+
+ case OP_MINSTAR:
+ case OP_MINSTARI:
+ case OP_NOTMINSTAR:
+ case OP_NOTMINSTARI:
+
+ case OP_POSSTAR:
+ case OP_POSSTARI:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSSTARI:
+
+ case OP_QUERY:
+ case OP_QUERYI:
+ case OP_NOTQUERY:
+ case OP_NOTQUERYI:
+
+ case OP_MINQUERY:
+ case OP_MINQUERYI:
+ case OP_NOTMINQUERY:
+ case OP_NOTMINQUERYI:
+
+ case OP_POSQUERY:
+ case OP_POSQUERYI:
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSQUERYI:
+
+ if (utf && HAS_EXTRALEN(code[1])) code += GET_EXTRALEN(code[1]);
+ break;
+
+ case OP_UPTO:
+ case OP_UPTOI:
+ case OP_NOTUPTO:
+ case OP_NOTUPTOI:
+
+ case OP_MINUPTO:
+ case OP_MINUPTOI:
+ case OP_NOTMINUPTO:
+ case OP_NOTMINUPTOI:
+
+ case OP_POSUPTO:
+ case OP_POSUPTOI:
+ case OP_NOTPOSUPTO:
+ case OP_NOTPOSUPTOI:
+
+ if (utf && HAS_EXTRALEN(code[1 + IMM2_SIZE])) code += GET_EXTRALEN(code[1 + IMM2_SIZE]);
+ break;
+#endif
+
+ /* MARK, and PRUNE/SKIP/THEN with an argument must skip over the argument
+ string. */
+
+ case OP_MARK:
+ case OP_PRUNE_ARG:
+ case OP_SKIP_ARG:
+ case OP_THEN_ARG:
+ code += code[1];
+ break;
+
+ /* None of the remaining opcodes are required to match a character. */
+
+ default:
+ break;
+ }
+ }
+
+return TRUE;
+}
+
+
+
+/*************************************************
+* Scan compiled regex for non-emptiness *
+*************************************************/
+
+/* This function is called to check for left recursive calls. We want to check
+the current branch of the current pattern to see if it could match the empty
+string. If it could, we must look outwards for branches at other levels,
+stopping when we pass beyond the bracket which is the subject of the recursion.
+This function is called only during the real compile, not during the
+pre-compile.
+
+Arguments:
+ code points to start of the recursion
+ endcode points to where to stop (current RECURSE item)
+ bcptr points to the chain of current (unclosed) branch starts
+ utf TRUE if in UTF-8 / UTF-16 / UTF-32 mode
+ cd pointers to tables etc
+
+Returns: TRUE if what is matched could be empty
+*/
+
+static BOOL
+could_be_empty(const pcre_uchar *code, const pcre_uchar *endcode,
+ branch_chain *bcptr, BOOL utf, compile_data *cd)
+{
+while (bcptr != NULL && bcptr->current_branch >= code)
+ {
+ if (!could_be_empty_branch(bcptr->current_branch, endcode, utf, cd, NULL))
+ return FALSE;
+ bcptr = bcptr->outer;
+ }
+return TRUE;
+}
+
+
+
+/*************************************************
+* Base opcode of repeated opcodes *
+*************************************************/
+
+/* Returns the base opcode for repeated single character type opcodes. If the
+opcode is not a repeated character type, it returns with the original value.
+
+Arguments: c opcode
+Returns: base opcode for the type
+*/
+
+static pcre_uchar
+get_repeat_base(pcre_uchar c)
+{
+return (c > OP_TYPEPOSUPTO)? c :
+ (c >= OP_TYPESTAR)? OP_TYPESTAR :
+ (c >= OP_NOTSTARI)? OP_NOTSTARI :
+ (c >= OP_NOTSTAR)? OP_NOTSTAR :
+ (c >= OP_STARI)? OP_STARI :
+ OP_STAR;
+}
+
+
+
+#ifdef SUPPORT_UCP
+/*************************************************
+* Check a character and a property *
+*************************************************/
+
+/* This function is called by check_auto_possessive() when a property item
+is adjacent to a fixed character.
+
+Arguments:
+ c the character
+ ptype the property type
+ pdata the data for the type
+ negated TRUE if it's a negated property (\P or \p{^)
+
+Returns: TRUE if auto-possessifying is OK
+*/
+
+static BOOL
+check_char_prop(pcre_uint32 c, unsigned int ptype, unsigned int pdata,
+ BOOL negated)
+{
+const pcre_uint32 *p;
+const ucd_record *prop = GET_UCD(c);
+
+switch(ptype)
+ {
+ case PT_LAMP:
+ return (prop->chartype == ucp_Lu ||
+ prop->chartype == ucp_Ll ||
+ prop->chartype == ucp_Lt) == negated;
+
+ case PT_GC:
+ return (pdata == PRIV(ucp_gentype)[prop->chartype]) == negated;
+
+ case PT_PC:
+ return (pdata == prop->chartype) == negated;
+
+ case PT_SC:
+ return (pdata == prop->script) == negated;
+
+ /* These are specials */
+
+ case PT_ALNUM:
+ return (PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N) == negated;
+
+ /* Perl space used to exclude VT, but from Perl 5.18 it is included, which
+ means that Perl space and POSIX space are now identical. PCRE was changed
+ at release 8.34. */
+
+ case PT_SPACE: /* Perl space */
+ case PT_PXSPACE: /* POSIX space */
+ switch(c)
+ {
+ HSPACE_CASES:
+ VSPACE_CASES:
+ return negated;
+
+ default:
+ return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == negated;
+ }
+ break; /* Control never reaches here */
+
+ case PT_WORD:
+ return (PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
+ c == CHAR_UNDERSCORE) == negated;
+
+ case PT_CLIST:
+ p = PRIV(ucd_caseless_sets) + prop->caseset;
+ for (;;)
+ {
+ if (c < *p) return !negated;
+ if (c == *p++) return negated;
+ }
+ break; /* Control never reaches here */
+ }
+
+return FALSE;
+}
+#endif /* SUPPORT_UCP */
+
+
+
+/*************************************************
+* Fill the character property list *
+*************************************************/
+
+/* Checks whether the code points to an opcode that can take part in auto-
+possessification, and if so, fills a list with its properties.
+
+Arguments:
+ code points to start of expression
+ utf TRUE if in UTF-8 / UTF-16 / UTF-32 mode
+ fcc points to case-flipping table
+ list points to output list
+ list[0] will be filled with the opcode
+ list[1] will be non-zero if this opcode
+ can match an empty character string
+ list[2..7] depends on the opcode
+
+Returns: points to the start of the next opcode if *code is accepted
+ NULL if *code is not accepted
+*/
+
+static const pcre_uchar *
+get_chr_property_list(const pcre_uchar *code, BOOL utf,
+ const pcre_uint8 *fcc, pcre_uint32 *list)
+{
+pcre_uchar c = *code;
+pcre_uchar base;
+const pcre_uchar *end;
+pcre_uint32 chr;
+
+#ifdef SUPPORT_UCP
+pcre_uint32 *clist_dest;
+const pcre_uint32 *clist_src;
+#else
+utf = utf; /* Suppress "unused parameter" compiler warning */
+#endif
+
+list[0] = c;
+list[1] = FALSE;
+code++;
+
+if (c >= OP_STAR && c <= OP_TYPEPOSUPTO)
+ {
+ base = get_repeat_base(c);
+ c -= (base - OP_STAR);
+
+ if (c == OP_UPTO || c == OP_MINUPTO || c == OP_EXACT || c == OP_POSUPTO)
+ code += IMM2_SIZE;
+
+ list[1] = (c != OP_PLUS && c != OP_MINPLUS && c != OP_EXACT && c != OP_POSPLUS);
+
+ switch(base)
+ {
+ case OP_STAR:
+ list[0] = OP_CHAR;
+ break;
+
+ case OP_STARI:
+ list[0] = OP_CHARI;
+ break;
+
+ case OP_NOTSTAR:
+ list[0] = OP_NOT;
+ break;
+
+ case OP_NOTSTARI:
+ list[0] = OP_NOTI;
+ break;
+
+ case OP_TYPESTAR:
+ list[0] = *code;
+ code++;
+ break;
+ }
+ c = list[0];
+ }
+
+switch(c)
+ {
+ case OP_NOT_DIGIT:
+ case OP_DIGIT:
+ case OP_NOT_WHITESPACE:
+ case OP_WHITESPACE:
+ case OP_NOT_WORDCHAR:
+ case OP_WORDCHAR:
+ case OP_ANY:
+ case OP_ALLANY:
+ case OP_ANYNL:
+ case OP_NOT_HSPACE:
+ case OP_HSPACE:
+ case OP_NOT_VSPACE:
+ case OP_VSPACE:
+ case OP_EXTUNI:
+ case OP_EODN:
+ case OP_EOD:
+ case OP_DOLL:
+ case OP_DOLLM:
+ return code;
+
+ case OP_CHAR:
+ case OP_NOT:
+ GETCHARINCTEST(chr, code);
+ list[2] = chr;
+ list[3] = NOTACHAR;
+ return code;
+
+ case OP_CHARI:
+ case OP_NOTI:
+ list[0] = (c == OP_CHARI) ? OP_CHAR : OP_NOT;
+ GETCHARINCTEST(chr, code);
+ list[2] = chr;
+
+#ifdef SUPPORT_UCP
+ if (chr < 128 || (chr < 256 && !utf))
+ list[3] = fcc[chr];
+ else
+ list[3] = UCD_OTHERCASE(chr);
+#elif defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ list[3] = (chr < 256) ? fcc[chr] : chr;
+#else
+ list[3] = fcc[chr];
+#endif
+
+ /* The othercase might be the same value. */
+
+ if (chr == list[3])
+ list[3] = NOTACHAR;
+ else
+ list[4] = NOTACHAR;
+ return code;
+
+#ifdef SUPPORT_UCP
+ case OP_PROP:
+ case OP_NOTPROP:
+ if (code[0] != PT_CLIST)
+ {
+ list[2] = code[0];
+ list[3] = code[1];
+ return code + 2;
+ }
+
+ /* Convert only if we have enough space. */
+
+ clist_src = PRIV(ucd_caseless_sets) + code[1];
+ clist_dest = list + 2;
+ code += 2;
+
+ do {
+ if (clist_dest >= list + 8)
+ {
+ /* Early return if there is not enough space. This should never
+ happen, since all clists are shorter than 5 character now. */
+ list[2] = code[0];
+ list[3] = code[1];
+ return code;
+ }
+ *clist_dest++ = *clist_src;
+ }
+ while(*clist_src++ != NOTACHAR);
+
+ /* All characters are stored. The terminating NOTACHAR
+ is copied form the clist itself. */
+
+ list[0] = (c == OP_PROP) ? OP_CHAR : OP_NOT;
+ return code;
+#endif
+
+ case OP_NCLASS:
+ case OP_CLASS:
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+ if (c == OP_XCLASS)
+ end = code + GET(code, 0) - 1;
+ else
+#endif
+ end = code + 32 / sizeof(pcre_uchar);
+
+ switch(*end)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ case OP_CRPOSSTAR:
+ case OP_CRPOSQUERY:
+ list[1] = TRUE;
+ end++;
+ break;
+
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ case OP_CRPOSPLUS:
+ end++;
+ break;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ case OP_CRPOSRANGE:
+ list[1] = (GET2(end, 1) == 0);
+ end += 1 + 2 * IMM2_SIZE;
+ break;
+ }
+ list[2] = end - code;
+ return end;
+ }
+return NULL; /* Opcode not accepted */
+}
+
+
+
+/*************************************************
+* Scan further character sets for match *
+*************************************************/
+
+/* Checks whether the base and the current opcode have a common character, in
+which case the base cannot be possessified.
+
+Arguments:
+ code points to the byte code
+ utf TRUE in UTF-8 / UTF-16 / UTF-32 mode
+ cd static compile data
+ base_list the data list of the base opcode
+
+Returns: TRUE if the auto-possessification is possible
+*/
+
+static BOOL
+compare_opcodes(const pcre_uchar *code, BOOL utf, const compile_data *cd,
+ const pcre_uint32 *base_list, const pcre_uchar *base_end)
+{
+pcre_uchar c;
+pcre_uint32 list[8];
+const pcre_uint32 *chr_ptr;
+const pcre_uint32 *ochr_ptr;
+const pcre_uint32 *list_ptr;
+const pcre_uchar *next_code;
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+const pcre_uchar *xclass_flags;
+#endif
+const pcre_uint8 *class_bitset;
+const pcre_uint8 *set1, *set2, *set_end;
+pcre_uint32 chr;
+BOOL accepted, invert_bits;
+
+/* Note: the base_list[1] contains whether the current opcode has greedy
+(represented by a non-zero value) quantifier. This is a different from
+other character type lists, which stores here that the character iterator
+matches to an empty string (also represented by a non-zero value). */
+
+for(;;)
+ {
+ /* All operations move the code pointer forward.
+ Therefore infinite recursions are not possible. */
+
+ c = *code;
+
+ /* Skip over callouts */
+
+ if (c == OP_CALLOUT)
+ {
+ code += PRIV(OP_lengths)[c];
+ continue;
+ }
+
+ if (c == OP_ALT)
+ {
+ do code += GET(code, 1); while (*code == OP_ALT);
+ c = *code;
+ }
+
+ switch(c)
+ {
+ case OP_END:
+ case OP_KETRPOS:
+ /* TRUE only in greedy case. The non-greedy case could be replaced by
+ an OP_EXACT, but it is probably not worth it. (And note that OP_EXACT
+ uses more memory, which we cannot get at this stage.) */
+
+ return base_list[1] != 0;
+
+ case OP_KET:
+ /* If the bracket is capturing, and referenced by an OP_RECURSE, or
+ it is an atomic sub-pattern (assert, once, etc.) the non-greedy case
+ cannot be converted to a possessive form. */
+
+ if (base_list[1] == 0) return FALSE;
+
+ switch(*(code - GET(code, 1)))
+ {
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ /* Atomic sub-patterns and assertions can always auto-possessify their
+ last iterator. */
+ return TRUE;
+ }
+
+ code += PRIV(OP_lengths)[c];
+ continue;
+
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ case OP_BRA:
+ case OP_CBRA:
+ next_code = code + GET(code, 1);
+ code += PRIV(OP_lengths)[c];
+
+ while (*next_code == OP_ALT)
+ {
+ if (!compare_opcodes(code, utf, cd, base_list, base_end)) return FALSE;
+ code = next_code + 1 + LINK_SIZE;
+ next_code += GET(next_code, 1);
+ }
+ continue;
+
+ case OP_BRAZERO:
+ case OP_BRAMINZERO:
+
+ next_code = code + 1;
+ if (*next_code != OP_BRA && *next_code != OP_CBRA
+ && *next_code != OP_ONCE && *next_code != OP_ONCE_NC) return FALSE;
+
+ do next_code += GET(next_code, 1); while (*next_code == OP_ALT);
+
+ /* The bracket content will be checked by the
+ OP_BRA/OP_CBRA case above. */
+ next_code += 1 + LINK_SIZE;
+ if (!compare_opcodes(next_code, utf, cd, base_list, base_end))
+ return FALSE;
+
+ code += PRIV(OP_lengths)[c];
+ continue;
+ }
+
+ /* Check for a supported opcode, and load its properties. */
+
+ code = get_chr_property_list(code, utf, cd->fcc, list);
+ if (code == NULL) return FALSE; /* Unsupported */
+
+ /* If either opcode is a small character list, set pointers for comparing
+ characters from that list with another list, or with a property. */
+
+ if (base_list[0] == OP_CHAR)
+ {
+ chr_ptr = base_list + 2;
+ list_ptr = list;
+ }
+ else if (list[0] == OP_CHAR)
+ {
+ chr_ptr = list + 2;
+ list_ptr = base_list;
+ }
+
+ /* Character bitsets can also be compared to certain opcodes. */
+
+ else if (base_list[0] == OP_CLASS || list[0] == OP_CLASS
+#ifdef COMPILE_PCRE8
+ /* In 8 bit, non-UTF mode, OP_CLASS and OP_NCLASS are the same. */
+ || (!utf && (base_list[0] == OP_NCLASS || list[0] == OP_NCLASS))
+#endif
+ )
+ {
+#ifdef COMPILE_PCRE8
+ if (base_list[0] == OP_CLASS || (!utf && base_list[0] == OP_NCLASS))
+#else
+ if (base_list[0] == OP_CLASS)
+#endif
+ {
+ set1 = (pcre_uint8 *)(base_end - base_list[2]);
+ list_ptr = list;
+ }
+ else
+ {
+ set1 = (pcre_uint8 *)(code - list[2]);
+ list_ptr = base_list;
+ }
+
+ invert_bits = FALSE;
+ switch(list_ptr[0])
+ {
+ case OP_CLASS:
+ case OP_NCLASS:
+ set2 = (pcre_uint8 *)
+ ((list_ptr == list ? code : base_end) - list_ptr[2]);
+ break;
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+ xclass_flags = (list_ptr == list ? code : base_end) - list_ptr[2] + LINK_SIZE;
+ if ((*xclass_flags & XCL_HASPROP) != 0) return FALSE;
+ if ((*xclass_flags & XCL_MAP) == 0)
+ {
+ /* No bits are set for characters < 256. */
+ if (list[1] == 0) return TRUE;
+ /* Might be an empty repeat. */
+ continue;
+ }
+ set2 = (pcre_uint8 *)(xclass_flags + 1);
+ break;
+#endif
+
+ case OP_NOT_DIGIT:
+ invert_bits = TRUE;
+ /* Fall through */
+ case OP_DIGIT:
+ set2 = (pcre_uint8 *)(cd->cbits + cbit_digit);
+ break;
+
+ case OP_NOT_WHITESPACE:
+ invert_bits = TRUE;
+ /* Fall through */
+ case OP_WHITESPACE:
+ set2 = (pcre_uint8 *)(cd->cbits + cbit_space);
+ break;
+
+ case OP_NOT_WORDCHAR:
+ invert_bits = TRUE;
+ /* Fall through */
+ case OP_WORDCHAR:
+ set2 = (pcre_uint8 *)(cd->cbits + cbit_word);
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ /* Because the sets are unaligned, we need
+ to perform byte comparison here. */
+ set_end = set1 + 32;
+ if (invert_bits)
+ {
+ do
+ {
+ if ((*set1++ & ~(*set2++)) != 0) return FALSE;
+ }
+ while (set1 < set_end);
+ }
+ else
+ {
+ do
+ {
+ if ((*set1++ & *set2++) != 0) return FALSE;
+ }
+ while (set1 < set_end);
+ }
+
+ if (list[1] == 0) return TRUE;
+ /* Might be an empty repeat. */
+ continue;
+ }
+
+ /* Some property combinations also acceptable. Unicode property opcodes are
+ processed specially; the rest can be handled with a lookup table. */
+
+ else
+ {
+ pcre_uint32 leftop, rightop;
+
+ leftop = base_list[0];
+ rightop = list[0];
+
+#ifdef SUPPORT_UCP
+ accepted = FALSE; /* Always set in non-unicode case. */
+ if (leftop == OP_PROP || leftop == OP_NOTPROP)
+ {
+ if (rightop == OP_EOD)
+ accepted = TRUE;
+ else if (rightop == OP_PROP || rightop == OP_NOTPROP)
+ {
+ int n;
+ const pcre_uint8 *p;
+ BOOL same = leftop == rightop;
+ BOOL lisprop = leftop == OP_PROP;
+ BOOL risprop = rightop == OP_PROP;
+ BOOL bothprop = lisprop && risprop;
+
+ /* There's a table that specifies how each combination is to be
+ processed:
+ 0 Always return FALSE (never auto-possessify)
+ 1 Character groups are distinct (possessify if both are OP_PROP)
+ 2 Check character categories in the same group (general or particular)
+ 3 Return TRUE if the two opcodes are not the same
+ ... see comments below
+ */
+
+ n = propposstab[base_list[2]][list[2]];
+ switch(n)
+ {
+ case 0: break;
+ case 1: accepted = bothprop; break;
+ case 2: accepted = (base_list[3] == list[3]) != same; break;
+ case 3: accepted = !same; break;
+
+ case 4: /* Left general category, right particular category */
+ accepted = risprop && catposstab[base_list[3]][list[3]] == same;
+ break;
+
+ case 5: /* Right general category, left particular category */
+ accepted = lisprop && catposstab[list[3]][base_list[3]] == same;
+ break;
+
+ /* This code is logically tricky. Think hard before fiddling with it.
+ The posspropstab table has four entries per row. Each row relates to
+ one of PCRE's special properties such as ALNUM or SPACE or WORD.
+ Only WORD actually needs all four entries, but using repeats for the
+ others means they can all use the same code below.
+
+ The first two entries in each row are Unicode general categories, and
+ apply always, because all the characters they include are part of the
+ PCRE character set. The third and fourth entries are a general and a
+ particular category, respectively, that include one or more relevant
+ characters. One or the other is used, depending on whether the check
+ is for a general or a particular category. However, in both cases the
+ category contains more characters than the specials that are defined
+ for the property being tested against. Therefore, it cannot be used
+ in a NOTPROP case.
+
+ Example: the row for WORD contains ucp_L, ucp_N, ucp_P, ucp_Po.
+ Underscore is covered by ucp_P or ucp_Po. */
+
+ case 6: /* Left alphanum vs right general category */
+ case 7: /* Left space vs right general category */
+ case 8: /* Left word vs right general category */
+ p = posspropstab[n-6];
+ accepted = risprop && lisprop ==
+ (list[3] != p[0] &&
+ list[3] != p[1] &&
+ (list[3] != p[2] || !lisprop));
+ break;
+
+ case 9: /* Right alphanum vs left general category */
+ case 10: /* Right space vs left general category */
+ case 11: /* Right word vs left general category */
+ p = posspropstab[n-9];
+ accepted = lisprop && risprop ==
+ (base_list[3] != p[0] &&
+ base_list[3] != p[1] &&
+ (base_list[3] != p[2] || !risprop));
+ break;
+
+ case 12: /* Left alphanum vs right particular category */
+ case 13: /* Left space vs right particular category */
+ case 14: /* Left word vs right particular category */
+ p = posspropstab[n-12];
+ accepted = risprop && lisprop ==
+ (catposstab[p[0]][list[3]] &&
+ catposstab[p[1]][list[3]] &&
+ (list[3] != p[3] || !lisprop));
+ break;
+
+ case 15: /* Right alphanum vs left particular category */
+ case 16: /* Right space vs left particular category */
+ case 17: /* Right word vs left particular category */
+ p = posspropstab[n-15];
+ accepted = lisprop && risprop ==
+ (catposstab[p[0]][base_list[3]] &&
+ catposstab[p[1]][base_list[3]] &&
+ (base_list[3] != p[3] || !risprop));
+ break;
+ }
+ }
+ }
+
+ else
+#endif /* SUPPORT_UCP */
+
+ accepted = leftop >= FIRST_AUTOTAB_OP && leftop <= LAST_AUTOTAB_LEFT_OP &&
+ rightop >= FIRST_AUTOTAB_OP && rightop <= LAST_AUTOTAB_RIGHT_OP &&
+ autoposstab[leftop - FIRST_AUTOTAB_OP][rightop - FIRST_AUTOTAB_OP];
+
+ if (!accepted)
+ return FALSE;
+
+ if (list[1] == 0) return TRUE;
+ /* Might be an empty repeat. */
+ continue;
+ }
+
+ /* Control reaches here only if one of the items is a small character list.
+ All characters are checked against the other side. */
+
+ do
+ {
+ chr = *chr_ptr;
+
+ switch(list_ptr[0])
+ {
+ case OP_CHAR:
+ ochr_ptr = list_ptr + 2;
+ do
+ {
+ if (chr == *ochr_ptr) return FALSE;
+ ochr_ptr++;
+ }
+ while(*ochr_ptr != NOTACHAR);
+ break;
+
+ case OP_NOT:
+ ochr_ptr = list_ptr + 2;
+ do
+ {
+ if (chr == *ochr_ptr)
+ break;
+ ochr_ptr++;
+ }
+ while(*ochr_ptr != NOTACHAR);
+ if (*ochr_ptr == NOTACHAR) return FALSE; /* Not found */
+ break;
+
+ /* Note that OP_DIGIT etc. are generated only when PCRE_UCP is *not*
+ set. When it is set, \d etc. are converted into OP_(NOT_)PROP codes. */
+
+ case OP_DIGIT:
+ if (chr < 256 && (cd->ctypes[chr] & ctype_digit) != 0) return FALSE;
+ break;
+
+ case OP_NOT_DIGIT:
+ if (chr > 255 || (cd->ctypes[chr] & ctype_digit) == 0) return FALSE;
+ break;
+
+ case OP_WHITESPACE:
+ if (chr < 256 && (cd->ctypes[chr] & ctype_space) != 0) return FALSE;
+ break;
+
+ case OP_NOT_WHITESPACE:
+ if (chr > 255 || (cd->ctypes[chr] & ctype_space) == 0) return FALSE;
+ break;
+
+ case OP_WORDCHAR:
+ if (chr < 255 && (cd->ctypes[chr] & ctype_word) != 0) return FALSE;
+ break;
+
+ case OP_NOT_WORDCHAR:
+ if (chr > 255 || (cd->ctypes[chr] & ctype_word) == 0) return FALSE;
+ break;
+
+ case OP_HSPACE:
+ switch(chr)
+ {
+ HSPACE_CASES: return FALSE;
+ default: break;
+ }
+ break;
+
+ case OP_NOT_HSPACE:
+ switch(chr)
+ {
+ HSPACE_CASES: break;
+ default: return FALSE;
+ }
+ break;
+
+ case OP_ANYNL:
+ case OP_VSPACE:
+ switch(chr)
+ {
+ VSPACE_CASES: return FALSE;
+ default: break;
+ }
+ break;
+
+ case OP_NOT_VSPACE:
+ switch(chr)
+ {
+ VSPACE_CASES: break;
+ default: return FALSE;
+ }
+ break;
+
+ case OP_DOLL:
+ case OP_EODN:
+ switch (chr)
+ {
+ case CHAR_CR:
+ case CHAR_LF:
+ case CHAR_VT:
+ case CHAR_FF:
+ case CHAR_NEL:
+#ifndef EBCDIC
+ case 0x2028:
+ case 0x2029:
+#endif /* Not EBCDIC */
+ return FALSE;
+ }
+ break;
+
+ case OP_EOD: /* Can always possessify before \z */
+ break;
+
+#ifdef SUPPORT_UCP
+ case OP_PROP:
+ case OP_NOTPROP:
+ if (!check_char_prop(chr, list_ptr[2], list_ptr[3],
+ list_ptr[0] == OP_NOTPROP))
+ return FALSE;
+ break;
+#endif
+
+ case OP_NCLASS:
+ if (chr > 255) return FALSE;
+ /* Fall through */
+
+ case OP_CLASS:
+ if (chr > 255) break;
+ class_bitset = (pcre_uint8 *)
+ ((list_ptr == list ? code : base_end) - list_ptr[2]);
+ if ((class_bitset[chr >> 3] & (1 << (chr & 7))) != 0) return FALSE;
+ break;
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+ if (PRIV(xclass)(chr, (list_ptr == list ? code : base_end) -
+ list_ptr[2] + LINK_SIZE, utf)) return FALSE;
+ break;
+#endif
+
+ default:
+ return FALSE;
+ }
+
+ chr_ptr++;
+ }
+ while(*chr_ptr != NOTACHAR);
+
+ /* At least one character must be matched from this opcode. */
+
+ if (list[1] == 0) return TRUE;
+ }
+
+/* Control never reaches here. There used to be a fail-save return FALSE; here,
+but some compilers complain about an unreachable statement. */
+
+}
+
+
+
+/*************************************************
+* Scan compiled regex for auto-possession *
+*************************************************/
+
+/* Replaces single character iterations with their possessive alternatives
+if appropriate. This function modifies the compiled opcode!
+
+Arguments:
+ code points to start of the byte code
+ utf TRUE in UTF-8 / UTF-16 / UTF-32 mode
+ cd static compile data
+
+Returns: nothing
+*/
+
+static void
+auto_possessify(pcre_uchar *code, BOOL utf, const compile_data *cd)
+{
+register pcre_uchar c;
+const pcre_uchar *end;
+pcre_uchar *repeat_opcode;
+pcre_uint32 list[8];
+
+for (;;)
+ {
+ c = *code;
+
+ if (c >= OP_STAR && c <= OP_TYPEPOSUPTO)
+ {
+ c -= get_repeat_base(c) - OP_STAR;
+ end = (c <= OP_MINUPTO) ?
+ get_chr_property_list(code, utf, cd->fcc, list) : NULL;
+ list[1] = c == OP_STAR || c == OP_PLUS || c == OP_QUERY || c == OP_UPTO;
+
+ if (end != NULL && compare_opcodes(end, utf, cd, list, end))
+ {
+ switch(c)
+ {
+ case OP_STAR:
+ *code += OP_POSSTAR - OP_STAR;
+ break;
+
+ case OP_MINSTAR:
+ *code += OP_POSSTAR - OP_MINSTAR;
+ break;
+
+ case OP_PLUS:
+ *code += OP_POSPLUS - OP_PLUS;
+ break;
+
+ case OP_MINPLUS:
+ *code += OP_POSPLUS - OP_MINPLUS;
+ break;
+
+ case OP_QUERY:
+ *code += OP_POSQUERY - OP_QUERY;
+ break;
+
+ case OP_MINQUERY:
+ *code += OP_POSQUERY - OP_MINQUERY;
+ break;
+
+ case OP_UPTO:
+ *code += OP_POSUPTO - OP_UPTO;
+ break;
+
+ case OP_MINUPTO:
+ *code += OP_POSUPTO - OP_MINUPTO;
+ break;
+ }
+ }
+ c = *code;
+ }
+ else if (c == OP_CLASS || c == OP_NCLASS || c == OP_XCLASS)
+ {
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ if (c == OP_XCLASS)
+ repeat_opcode = code + GET(code, 1);
+ else
+#endif
+ repeat_opcode = code + 1 + (32 / sizeof(pcre_uchar));
+
+ c = *repeat_opcode;
+ if (c >= OP_CRSTAR && c <= OP_CRMINRANGE)
+ {
+ /* end must not be NULL. */
+ end = get_chr_property_list(code, utf, cd->fcc, list);
+
+ list[1] = (c & 1) == 0;
+
+ if (compare_opcodes(end, utf, cd, list, end))
+ {
+ switch (c)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ *repeat_opcode = OP_CRPOSSTAR;
+ break;
+
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ *repeat_opcode = OP_CRPOSPLUS;
+ break;
+
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ *repeat_opcode = OP_CRPOSQUERY;
+ break;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ *repeat_opcode = OP_CRPOSRANGE;
+ break;
+ }
+ }
+ }
+ c = *code;
+ }
+
+ switch(c)
+ {
+ case OP_END:
+ return;
+
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ case OP_TYPEPOSSTAR:
+ case OP_TYPEPOSPLUS:
+ case OP_TYPEPOSQUERY:
+ if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
+ break;
+
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ case OP_TYPEEXACT:
+ case OP_TYPEPOSUPTO:
+ if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
+ code += 2;
+ break;
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+ code += GET(code, 1);
+ break;
+#endif
+
+ case OP_MARK:
+ case OP_PRUNE_ARG:
+ case OP_SKIP_ARG:
+ case OP_THEN_ARG:
+ code += code[1];
+ break;
+ }
+
+ /* Add in the fixed length from the table */
+
+ code += PRIV(OP_lengths)[c];
+
+ /* In UTF-8 mode, opcodes that are followed by a character may be followed by
+ a multi-byte character. The length in the table is a minimum, so we have to
+ arrange to skip the extra bytes. */
+
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (utf) switch(c)
+ {
+ case OP_CHAR:
+ case OP_CHARI:
+ case OP_NOT:
+ case OP_NOTI:
+ case OP_STAR:
+ case OP_MINSTAR:
+ case OP_PLUS:
+ case OP_MINPLUS:
+ case OP_QUERY:
+ case OP_MINQUERY:
+ case OP_UPTO:
+ case OP_MINUPTO:
+ case OP_EXACT:
+ case OP_POSSTAR:
+ case OP_POSPLUS:
+ case OP_POSQUERY:
+ case OP_POSUPTO:
+ case OP_STARI:
+ case OP_MINSTARI:
+ case OP_PLUSI:
+ case OP_MINPLUSI:
+ case OP_QUERYI:
+ case OP_MINQUERYI:
+ case OP_UPTOI:
+ case OP_MINUPTOI:
+ case OP_EXACTI:
+ case OP_POSSTARI:
+ case OP_POSPLUSI:
+ case OP_POSQUERYI:
+ case OP_POSUPTOI:
+ case OP_NOTSTAR:
+ case OP_NOTMINSTAR:
+ case OP_NOTPLUS:
+ case OP_NOTMINPLUS:
+ case OP_NOTQUERY:
+ case OP_NOTMINQUERY:
+ case OP_NOTUPTO:
+ case OP_NOTMINUPTO:
+ case OP_NOTEXACT:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSUPTO:
+ case OP_NOTSTARI:
+ case OP_NOTMINSTARI:
+ case OP_NOTPLUSI:
+ case OP_NOTMINPLUSI:
+ case OP_NOTQUERYI:
+ case OP_NOTMINQUERYI:
+ case OP_NOTUPTOI:
+ case OP_NOTMINUPTOI:
+ case OP_NOTEXACTI:
+ case OP_NOTPOSSTARI:
+ case OP_NOTPOSPLUSI:
+ case OP_NOTPOSQUERYI:
+ case OP_NOTPOSUPTOI:
+ if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);
+ break;
+ }
+#else
+ (void)(utf); /* Keep compiler happy by referencing function argument */
+#endif
+ }
+}
+
+
+
+/*************************************************
+* Check for POSIX class syntax *
+*************************************************/
+
+/* This function is called when the sequence "[:" or "[." or "[=" is
+encountered in a character class. It checks whether this is followed by a
+sequence of characters terminated by a matching ":]" or ".]" or "=]". If we
+reach an unescaped ']' without the special preceding character, return FALSE.
+
+Originally, this function only recognized a sequence of letters between the
+terminators, but it seems that Perl recognizes any sequence of characters,
+though of course unknown POSIX names are subsequently rejected. Perl gives an
+"Unknown POSIX class" error for [:f\oo:] for example, where previously PCRE
+didn't consider this to be a POSIX class. Likewise for [:1234:].
+
+The problem in trying to be exactly like Perl is in the handling of escapes. We
+have to be sure that [abc[:x\]pqr] is *not* treated as containing a POSIX
+class, but [abc[:x\]pqr:]] is (so that an error can be generated). The code
+below handles the special case of \], but does not try to do any other escape
+processing. This makes it different from Perl for cases such as [:l\ower:]
+where Perl recognizes it as the POSIX class "lower" but PCRE does not recognize
+"l\ower". This is a lesser evil than not diagnosing bad classes when Perl does,
+I think.
+
+A user pointed out that PCRE was rejecting [:a[:digit:]] whereas Perl was not.
+It seems that the appearance of a nested POSIX class supersedes an apparent
+external class. For example, [:a[:digit:]b:] matches "a", "b", ":", or
+a digit.
+
+In Perl, unescaped square brackets may also appear as part of class names. For
+example, [:a[:abc]b:] gives unknown POSIX class "[:abc]b:]". However, for
+[:a[:abc]b][b:] it gives unknown POSIX class "[:abc]b][b:]", which does not
+seem right at all. PCRE does not allow closing square brackets in POSIX class
+names.
+
+Arguments:
+ ptr pointer to the initial [
+ endptr where to return the end pointer
+
+Returns: TRUE or FALSE
+*/
+
+static BOOL
+check_posix_syntax(const pcre_uchar *ptr, const pcre_uchar **endptr)
+{
+pcre_uchar terminator; /* Don't combine these lines; the Solaris cc */
+terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */
+for (++ptr; *ptr != CHAR_NULL; ptr++)
+ {
+ if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
+ ptr++;
+ else if (*ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE;
+ else
+ {
+ if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
+ {
+ *endptr = ptr;
+ return TRUE;
+ }
+ if (*ptr == CHAR_LEFT_SQUARE_BRACKET &&
+ (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT ||
+ ptr[1] == CHAR_EQUALS_SIGN) &&
+ check_posix_syntax(ptr, endptr))
+ return FALSE;
+ }
+ }
+return FALSE;
+}
+
+
+
+
+/*************************************************
+* Check POSIX class name *
+*************************************************/
+
+/* This function is called to check the name given in a POSIX-style class entry
+such as [:alnum:].
+
+Arguments:
+ ptr points to the first letter
+ len the length of the name
+
+Returns: a value representing the name, or -1 if unknown
+*/
+
+static int
+check_posix_name(const pcre_uchar *ptr, int len)
+{
+const char *pn = posix_names;
+register int yield = 0;
+while (posix_name_lengths[yield] != 0)
+ {
+ if (len == posix_name_lengths[yield] &&
+ STRNCMP_UC_C8(ptr, pn, (unsigned int)len) == 0) return yield;
+ pn += posix_name_lengths[yield] + 1;
+ yield++;
+ }
+return -1;
+}
+
+
+/*************************************************
+* Adjust OP_RECURSE items in repeated group *
+*************************************************/
+
+/* OP_RECURSE items contain an offset from the start of the regex to the group
+that is referenced. This means that groups can be replicated for fixed
+repetition simply by copying (because the recursion is allowed to refer to
+earlier groups that are outside the current group). However, when a group is
+optional (i.e. the minimum quantifier is zero), OP_BRAZERO or OP_SKIPZERO is
+inserted before it, after it has been compiled. This means that any OP_RECURSE
+items within it that refer to the group itself or any contained groups have to
+have their offsets adjusted. That one of the jobs of this function. Before it
+is called, the partially compiled regex must be temporarily terminated with
+OP_END.
+
+This function has been extended with the possibility of forward references for
+recursions and subroutine calls. It must also check the list of such references
+for the group we are dealing with. If it finds that one of the recursions in
+the current group is on this list, it adjusts the offset in the list, not the
+value in the reference (which is a group number).
+
+Arguments:
+ group points to the start of the group
+ adjust the amount by which the group is to be moved
+ utf TRUE in UTF-8 / UTF-16 / UTF-32 mode
+ cd contains pointers to tables etc.
+ save_hwm the hwm forward reference pointer at the start of the group
+
+Returns: nothing
+*/
+
+static void
+adjust_recurse(pcre_uchar *group, int adjust, BOOL utf, compile_data *cd,
+ pcre_uchar *save_hwm)
+{
+pcre_uchar *ptr = group;
+
+while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL)
+ {
+ int offset;
+ pcre_uchar *hc;
+
+ /* See if this recursion is on the forward reference list. If so, adjust the
+ reference. */
+
+ for (hc = save_hwm; hc < cd->hwm; hc += LINK_SIZE)
+ {
+ offset = (int)GET(hc, 0);
+ if (cd->start_code + offset == ptr + 1)
+ {
+ PUT(hc, 0, offset + adjust);
+ break;
+ }
+ }
+
+ /* Otherwise, adjust the recursion offset if it's after the start of this
+ group. */
+
+ if (hc >= cd->hwm)
+ {
+ offset = (int)GET(ptr, 1);
+ if (cd->start_code + offset >= group) PUT(ptr, 1, offset + adjust);
+ }
+
+ ptr += 1 + LINK_SIZE;
+ }
+}
+
+
+
+/*************************************************
+* Insert an automatic callout point *
+*************************************************/
+
+/* This function is called when the PCRE_AUTO_CALLOUT option is set, to insert
+callout points before each pattern item.
+
+Arguments:
+ code current code pointer
+ ptr current pattern pointer
+ cd pointers to tables etc
+
+Returns: new code pointer
+*/
+
+static pcre_uchar *
+auto_callout(pcre_uchar *code, const pcre_uchar *ptr, compile_data *cd)
+{
+*code++ = OP_CALLOUT;
+*code++ = 255;
+PUT(code, 0, (int)(ptr - cd->start_pattern)); /* Pattern offset */
+PUT(code, LINK_SIZE, 0); /* Default length */
+return code + 2 * LINK_SIZE;
+}
+
+
+
+/*************************************************
+* Complete a callout item *
+*************************************************/
+
+/* A callout item contains the length of the next item in the pattern, which
+we can't fill in till after we have reached the relevant point. This is used
+for both automatic and manual callouts.
+
+Arguments:
+ previous_callout points to previous callout item
+ ptr current pattern pointer
+ cd pointers to tables etc
+
+Returns: nothing
+*/
+
+static void
+complete_callout(pcre_uchar *previous_callout, const pcre_uchar *ptr, compile_data *cd)
+{
+int length = (int)(ptr - cd->start_pattern - GET(previous_callout, 2));
+PUT(previous_callout, 2 + LINK_SIZE, length);
+}
+
+
+
+#ifdef SUPPORT_UCP
+/*************************************************
+* Get othercase range *
+*************************************************/
+
+/* This function is passed the start and end of a class range, in UTF-8 mode
+with UCP support. It searches up the characters, looking for ranges of
+characters in the "other" case. Each call returns the next one, updating the
+start address. A character with multiple other cases is returned on its own
+with a special return value.
+
+Arguments:
+ cptr points to starting character value; updated
+ d end value
+ ocptr where to put start of othercase range
+ odptr where to put end of othercase range
+
+Yield: -1 when no more
+ 0 when a range is returned
+ >0 the CASESET offset for char with multiple other cases
+ in this case, ocptr contains the original
+*/
+
+static int
+get_othercase_range(pcre_uint32 *cptr, pcre_uint32 d, pcre_uint32 *ocptr,
+ pcre_uint32 *odptr)
+{
+pcre_uint32 c, othercase, next;
+unsigned int co;
+
+/* Find the first character that has an other case. If it has multiple other
+cases, return its case offset value. */
+
+for (c = *cptr; c <= d; c++)
+ {
+ if ((co = UCD_CASESET(c)) != 0)
+ {
+ *ocptr = c++; /* Character that has the set */
+ *cptr = c; /* Rest of input range */
+ return (int)co;
+ }
+ if ((othercase = UCD_OTHERCASE(c)) != c) break;
+ }
+
+if (c > d) return -1; /* Reached end of range */
+
+/* Found a character that has a single other case. Search for the end of the
+range, which is either the end of the input range, or a character that has zero
+or more than one other cases. */
+
+*ocptr = othercase;
+next = othercase + 1;
+
+for (++c; c <= d; c++)
+ {
+ if ((co = UCD_CASESET(c)) != 0 || UCD_OTHERCASE(c) != next) break;
+ next++;
+ }
+
+*odptr = next - 1; /* End of othercase range */
+*cptr = c; /* Rest of input range */
+return 0;
+}
+#endif /* SUPPORT_UCP */
+
+
+
+/*************************************************
+* Add a character or range to a class *
+*************************************************/
+
+/* This function packages up the logic of adding a character or range of
+characters to a class. The character values in the arguments will be within the
+valid values for the current mode (8-bit, 16-bit, UTF, etc). This function is
+mutually recursive with the function immediately below.
+
+Arguments:
+ classbits the bit map for characters < 256
+ uchardptr points to the pointer for extra data
+ options the options word
+ cd contains pointers to tables etc.
+ start start of range character
+ end end of range character
+
+Returns: the number of < 256 characters added
+ the pointer to extra data is updated
+*/
+
+static int
+add_to_class(pcre_uint8 *classbits, pcre_uchar **uchardptr, int options,
+ compile_data *cd, pcre_uint32 start, pcre_uint32 end)
+{
+pcre_uint32 c;
+pcre_uint32 classbits_end = (end <= 0xff ? end : 0xff);
+int n8 = 0;
+
+/* If caseless matching is required, scan the range and process alternate
+cases. In Unicode, there are 8-bit characters that have alternate cases that
+are greater than 255 and vice-versa. Sometimes we can just extend the original
+range. */
+
+if ((options & PCRE_CASELESS) != 0)
+ {
+#ifdef SUPPORT_UCP
+ if ((options & PCRE_UTF8) != 0)
+ {
+ int rc;
+ pcre_uint32 oc, od;
+
+ options &= ~PCRE_CASELESS; /* Remove for recursive calls */
+ c = start;
+
+ while ((rc = get_othercase_range(&c, end, &oc, &od)) >= 0)
+ {
+ /* Handle a single character that has more than one other case. */
+
+ if (rc > 0) n8 += add_list_to_class(classbits, uchardptr, options, cd,
+ PRIV(ucd_caseless_sets) + rc, oc);
+
+ /* Do nothing if the other case range is within the original range. */
+
+ else if (oc >= start && od <= end) continue;
+
+ /* Extend the original range if there is overlap, noting that if oc < c, we
+ can't have od > end because a subrange is always shorter than the basic
+ range. Otherwise, use a recursive call to add the additional range. */
+
+ else if (oc < start && od >= start - 1) start = oc; /* Extend downwards */
+ else if (od > end && oc <= end + 1) end = od; /* Extend upwards */
+ else n8 += add_to_class(classbits, uchardptr, options, cd, oc, od);
+ }
+ }
+ else
+#endif /* SUPPORT_UCP */
+
+ /* Not UTF-mode, or no UCP */
+
+ for (c = start; c <= classbits_end; c++)
+ {
+ SETBIT(classbits, cd->fcc[c]);
+ n8++;
+ }
+ }
+
+/* Now handle the original range. Adjust the final value according to the bit
+length - this means that the same lists of (e.g.) horizontal spaces can be used
+in all cases. */
+
+#if defined COMPILE_PCRE8
+#ifdef SUPPORT_UTF
+ if ((options & PCRE_UTF8) == 0)
+#endif
+ if (end > 0xff) end = 0xff;
+
+#elif defined COMPILE_PCRE16
+#ifdef SUPPORT_UTF
+ if ((options & PCRE_UTF16) == 0)
+#endif
+ if (end > 0xffff) end = 0xffff;
+
+#endif /* COMPILE_PCRE[8|16] */
+
+/* Use the bitmap for characters < 256. Otherwise use extra data.*/
+
+for (c = start; c <= classbits_end; c++)
+ {
+ /* Regardless of start, c will always be <= 255. */
+ SETBIT(classbits, c);
+ n8++;
+ }
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+if (start <= 0xff) start = 0xff + 1;
+
+if (end >= start)
+ {
+ pcre_uchar *uchardata = *uchardptr;
+#ifdef SUPPORT_UTF
+ if ((options & PCRE_UTF8) != 0) /* All UTFs use the same flag bit */
+ {
+ if (start < end)
+ {
+ *uchardata++ = XCL_RANGE;
+ uchardata += PRIV(ord2utf)(start, uchardata);
+ uchardata += PRIV(ord2utf)(end, uchardata);
+ }
+ else if (start == end)
+ {
+ *uchardata++ = XCL_SINGLE;
+ uchardata += PRIV(ord2utf)(start, uchardata);
+ }
+ }
+ else
+#endif /* SUPPORT_UTF */
+
+ /* Without UTF support, character values are constrained by the bit length,
+ and can only be > 256 for 16-bit and 32-bit libraries. */
+
+#ifdef COMPILE_PCRE8
+ {}
+#else
+ if (start < end)
+ {
+ *uchardata++ = XCL_RANGE;
+ *uchardata++ = start;
+ *uchardata++ = end;
+ }
+ else if (start == end)
+ {
+ *uchardata++ = XCL_SINGLE;
+ *uchardata++ = start;
+ }
+#endif
+
+ *uchardptr = uchardata; /* Updata extra data pointer */
+ }
+#endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
+
+return n8; /* Number of 8-bit characters */
+}
+
+
+
+
+/*************************************************
+* Add a list of characters to a class *
+*************************************************/
+
+/* This function is used for adding a list of case-equivalent characters to a
+class, and also for adding a list of horizontal or vertical whitespace. If the
+list is in order (which it should be), ranges of characters are detected and
+handled appropriately. This function is mutually recursive with the function
+above.
+
+Arguments:
+ classbits the bit map for characters < 256
+ uchardptr points to the pointer for extra data
+ options the options word
+ cd contains pointers to tables etc.
+ p points to row of 32-bit values, terminated by NOTACHAR
+ except character to omit; this is used when adding lists of
+ case-equivalent characters to avoid including the one we
+ already know about
+
+Returns: the number of < 256 characters added
+ the pointer to extra data is updated
+*/
+
+static int
+add_list_to_class(pcre_uint8 *classbits, pcre_uchar **uchardptr, int options,
+ compile_data *cd, const pcre_uint32 *p, unsigned int except)
+{
+int n8 = 0;
+while (p[0] < NOTACHAR)
+ {
+ int n = 0;
+ if (p[0] != except)
+ {
+ while(p[n+1] == p[0] + n + 1) n++;
+ n8 += add_to_class(classbits, uchardptr, options, cd, p[0], p[n]);
+ }
+ p += n + 1;
+ }
+return n8;
+}
+
+
+
+/*************************************************
+* Add characters not in a list to a class *
+*************************************************/
+
+/* This function is used for adding the complement of a list of horizontal or
+vertical whitespace to a class. The list must be in order.
+
+Arguments:
+ classbits the bit map for characters < 256
+ uchardptr points to the pointer for extra data
+ options the options word
+ cd contains pointers to tables etc.
+ p points to row of 32-bit values, terminated by NOTACHAR
+
+Returns: the number of < 256 characters added
+ the pointer to extra data is updated
+*/
+
+static int
+add_not_list_to_class(pcre_uint8 *classbits, pcre_uchar **uchardptr,
+ int options, compile_data *cd, const pcre_uint32 *p)
+{
+BOOL utf = (options & PCRE_UTF8) != 0;
+int n8 = 0;
+if (p[0] > 0)
+ n8 += add_to_class(classbits, uchardptr, options, cd, 0, p[0] - 1);
+while (p[0] < NOTACHAR)
+ {
+ while (p[1] == p[0] + 1) p++;
+ n8 += add_to_class(classbits, uchardptr, options, cd, p[0] + 1,
+ (p[1] == NOTACHAR) ? (utf ? 0x10ffffu : 0xffffffffu) : p[1] - 1);
+ p++;
+ }
+return n8;
+}
+
+
+
+/*************************************************
+* Compile one branch *
+*************************************************/
+
+/* Scan the pattern, compiling it into the a vector. If the options are
+changed during the branch, the pointer is used to change the external options
+bits. This function is used during the pre-compile phase when we are trying
+to find out the amount of memory needed, as well as during the real compile
+phase. The value of lengthptr distinguishes the two phases.
+
+Arguments:
+ optionsptr pointer to the option bits
+ codeptr points to the pointer to the current code point
+ ptrptr points to the current pattern pointer
+ errorcodeptr points to error code variable
+ firstcharptr place to put the first required character
+ firstcharflagsptr place to put the first character flags, or a negative number
+ reqcharptr place to put the last required character
+ reqcharflagsptr place to put the last required character flags, or a negative number
+ bcptr points to current branch chain
+ cond_depth conditional nesting depth
+ cd contains pointers to tables etc.
+ lengthptr NULL during the real compile phase
+ points to length accumulator during pre-compile phase
+
+Returns: TRUE on success
+ FALSE, with *errorcodeptr set non-zero on error
+*/
+
+static BOOL
+compile_branch(int *optionsptr, pcre_uchar **codeptr,
+ const pcre_uchar **ptrptr, int *errorcodeptr,
+ pcre_uint32 *firstcharptr, pcre_int32 *firstcharflagsptr,
+ pcre_uint32 *reqcharptr, pcre_int32 *reqcharflagsptr,
+ branch_chain *bcptr, int cond_depth,
+ compile_data *cd, int *lengthptr)
+{
+int repeat_type, op_type;
+int repeat_min = 0, repeat_max = 0; /* To please picky compilers */
+int bravalue = 0;
+int greedy_default, greedy_non_default;
+pcre_uint32 firstchar, reqchar;
+pcre_int32 firstcharflags, reqcharflags;
+pcre_uint32 zeroreqchar, zerofirstchar;
+pcre_int32 zeroreqcharflags, zerofirstcharflags;
+pcre_int32 req_caseopt, reqvary, tempreqvary;
+int options = *optionsptr; /* May change dynamically */
+int after_manual_callout = 0;
+int length_prevgroup = 0;
+register pcre_uint32 c;
+int escape;
+register pcre_uchar *code = *codeptr;
+pcre_uchar *last_code = code;
+pcre_uchar *orig_code = code;
+pcre_uchar *tempcode;
+BOOL inescq = FALSE;
+BOOL groupsetfirstchar = FALSE;
+const pcre_uchar *ptr = *ptrptr;
+const pcre_uchar *tempptr;
+const pcre_uchar *nestptr = NULL;
+pcre_uchar *previous = NULL;
+pcre_uchar *previous_callout = NULL;
+pcre_uchar *save_hwm = NULL;
+pcre_uint8 classbits[32];
+
+/* We can fish out the UTF-8 setting once and for all into a BOOL, but we
+must not do this for other options (e.g. PCRE_EXTENDED) because they may change
+dynamically as we process the pattern. */
+
+#ifdef SUPPORT_UTF
+/* PCRE_UTF[16|32] have the same value as PCRE_UTF8. */
+BOOL utf = (options & PCRE_UTF8) != 0;
+#ifndef COMPILE_PCRE32
+pcre_uchar utf_chars[6];
+#endif
+#else
+BOOL utf = FALSE;
+#endif
+
+/* Helper variables for OP_XCLASS opcode (for characters > 255). We define
+class_uchardata always so that it can be passed to add_to_class() always,
+though it will not be used in non-UTF 8-bit cases. This avoids having to supply
+alternative calls for the different cases. */
+
+pcre_uchar *class_uchardata;
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+BOOL xclass;
+pcre_uchar *class_uchardata_base;
+#endif
+
+#ifdef PCRE_DEBUG
+if (lengthptr != NULL) DPRINTF((">> start branch\n"));
+#endif
+
+/* Set up the default and non-default settings for greediness */
+
+greedy_default = ((options & PCRE_UNGREEDY) != 0);
+greedy_non_default = greedy_default ^ 1;
+
+/* Initialize no first byte, no required byte. REQ_UNSET means "no char
+matching encountered yet". It gets changed to REQ_NONE if we hit something that
+matches a non-fixed char first char; reqchar just remains unset if we never
+find one.
+
+When we hit a repeat whose minimum is zero, we may have to adjust these values
+to take the zero repeat into account. This is implemented by setting them to
+zerofirstbyte and zeroreqchar when such a repeat is encountered. The individual
+item types that can be repeated set these backoff variables appropriately. */
+
+firstchar = reqchar = zerofirstchar = zeroreqchar = 0;
+firstcharflags = reqcharflags = zerofirstcharflags = zeroreqcharflags = REQ_UNSET;
+
+/* The variable req_caseopt contains either the REQ_CASELESS value
+or zero, according to the current setting of the caseless flag. The
+REQ_CASELESS leaves the lower 28 bit empty. It is added into the
+firstchar or reqchar variables to record the case status of the
+value. This is used only for ASCII characters. */
+
+req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS:0;
+
+/* Switch on next character until the end of the branch */
+
+for (;; ptr++)
+ {
+ BOOL negate_class;
+ BOOL should_flip_negation;
+ BOOL possessive_quantifier;
+ BOOL is_quantifier;
+ BOOL is_recurse;
+ BOOL reset_bracount;
+ int class_has_8bitchar;
+ int class_one_char;
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ BOOL xclass_has_prop;
+#endif
+ int newoptions;
+ int recno;
+ int refsign;
+ int skipbytes;
+ pcre_uint32 subreqchar, subfirstchar;
+ pcre_int32 subreqcharflags, subfirstcharflags;
+ int terminator;
+ unsigned int mclength;
+ unsigned int tempbracount;
+ pcre_uint32 ec;
+ pcre_uchar mcbuffer[8];
+
+ /* Get next character in the pattern */
+
+ c = *ptr;
+
+ /* If we are at the end of a nested substitution, revert to the outer level
+ string. Nesting only happens one level deep. */
+
+ if (c == CHAR_NULL && nestptr != NULL)
+ {
+ ptr = nestptr;
+ nestptr = NULL;
+ c = *ptr;
+ }
+
+ /* If we are in the pre-compile phase, accumulate the length used for the
+ previous cycle of this loop. */
+
+ if (lengthptr != NULL)
+ {
+#ifdef PCRE_DEBUG
+ if (code > cd->hwm) cd->hwm = code; /* High water info */
+#endif
+ if (code > cd->start_workspace + cd->workspace_size -
+ WORK_SIZE_SAFETY_MARGIN) /* Check for overrun */
+ {
+ *errorcodeptr = ERR52;
+ goto FAILED;
+ }
+
+ /* There is at least one situation where code goes backwards: this is the
+ case of a zero quantifier after a class (e.g. [ab]{0}). At compile time,
+ the class is simply eliminated. However, it is created first, so we have to
+ allow memory for it. Therefore, don't ever reduce the length at this point.
+ */
+
+ if (code < last_code) code = last_code;
+
+ /* Paranoid check for integer overflow */
+
+ if (OFLOW_MAX - *lengthptr < code - last_code)
+ {
+ *errorcodeptr = ERR20;
+ goto FAILED;
+ }
+
+ *lengthptr += (int)(code - last_code);
+ DPRINTF(("length=%d added %d c=%c (0x%x)\n", *lengthptr,
+ (int)(code - last_code), c, c));
+
+ /* If "previous" is set and it is not at the start of the work space, move
+ it back to there, in order to avoid filling up the work space. Otherwise,
+ if "previous" is NULL, reset the current code pointer to the start. */
+
+ if (previous != NULL)
+ {
+ if (previous > orig_code)
+ {
+ memmove(orig_code, previous, IN_UCHARS(code - previous));
+ code -= previous - orig_code;
+ previous = orig_code;
+ }
+ }
+ else code = orig_code;
+
+ /* Remember where this code item starts so we can pick up the length
+ next time round. */
+
+ last_code = code;
+ }
+
+ /* In the real compile phase, just check the workspace used by the forward
+ reference list. */
+
+ else if (cd->hwm > cd->start_workspace + cd->workspace_size -
+ WORK_SIZE_SAFETY_MARGIN)
+ {
+ *errorcodeptr = ERR52;
+ goto FAILED;
+ }
+
+ /* If in \Q...\E, check for the end; if not, we have a literal */
+
+ if (inescq && c != CHAR_NULL)
+ {
+ if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E)
+ {
+ inescq = FALSE;
+ ptr++;
+ continue;
+ }
+ else
+ {
+ if (previous_callout != NULL)
+ {
+ if (lengthptr == NULL) /* Don't attempt in pre-compile phase */
+ complete_callout(previous_callout, ptr, cd);
+ previous_callout = NULL;
+ }
+ if ((options & PCRE_AUTO_CALLOUT) != 0)
+ {
+ previous_callout = code;
+ code = auto_callout(code, ptr, cd);
+ }
+ goto NORMAL_CHAR;
+ }
+ /* Control does not reach here. */
+ }
+
+ /* In extended mode, skip white space and comments. We need a loop in order
+ to check for more white space and more comments after a comment. */
+
+ if ((options & PCRE_EXTENDED) != 0)
+ {
+ for (;;)
+ {
+ while (MAX_255(c) && (cd->ctypes[c] & ctype_space) != 0) c = *(++ptr);
+ if (c != CHAR_NUMBER_SIGN) break;
+ ptr++;
+ while (*ptr != CHAR_NULL)
+ {
+ if (IS_NEWLINE(ptr)) /* For non-fixed-length newline cases, */
+ { /* IS_NEWLINE sets cd->nllen. */
+ ptr += cd->nllen;
+ break;
+ }
+ ptr++;
+#ifdef SUPPORT_UTF
+ if (utf) FORWARDCHAR(ptr);
+#endif
+ }
+ c = *ptr; /* Either NULL or the char after a newline */
+ }
+ }
+
+ /* See if the next thing is a quantifier. */
+
+ is_quantifier =
+ c == CHAR_ASTERISK || c == CHAR_PLUS || c == CHAR_QUESTION_MARK ||
+ (c == CHAR_LEFT_CURLY_BRACKET && is_counted_repeat(ptr+1));
+
+ /* Fill in length of a previous callout, except when the next thing is a
+ quantifier or when processing a property substitution string in UCP mode. */
+
+ if (!is_quantifier && previous_callout != NULL && nestptr == NULL &&
+ after_manual_callout-- <= 0)
+ {
+ if (lengthptr == NULL) /* Don't attempt in pre-compile phase */
+ complete_callout(previous_callout, ptr, cd);
+ previous_callout = NULL;
+ }
+
+ /* Create auto callout, except for quantifiers, or while processing property
+ strings that are substituted for \w etc in UCP mode. */
+
+ if ((options & PCRE_AUTO_CALLOUT) != 0 && !is_quantifier && nestptr == NULL)
+ {
+ previous_callout = code;
+ code = auto_callout(code, ptr, cd);
+ }
+
+ /* Process the next pattern item. */
+
+ switch(c)
+ {
+ /* ===================================================================*/
+ case CHAR_NULL: /* The branch terminates at string end */
+ case CHAR_VERTICAL_LINE: /* or | or ) */
+ case CHAR_RIGHT_PARENTHESIS:
+ *firstcharptr = firstchar;
+ *firstcharflagsptr = firstcharflags;
+ *reqcharptr = reqchar;
+ *reqcharflagsptr = reqcharflags;
+ *codeptr = code;
+ *ptrptr = ptr;
+ if (lengthptr != NULL)
+ {
+ if (OFLOW_MAX - *lengthptr < code - last_code)
+ {
+ *errorcodeptr = ERR20;
+ goto FAILED;
+ }
+ *lengthptr += (int)(code - last_code); /* To include callout length */
+ DPRINTF((">> end branch\n"));
+ }
+ return TRUE;
+
+
+ /* ===================================================================*/
+ /* Handle single-character metacharacters. In multiline mode, ^ disables
+ the setting of any following char as a first character. */
+
+ case CHAR_CIRCUMFLEX_ACCENT:
+ previous = NULL;
+ if ((options & PCRE_MULTILINE) != 0)
+ {
+ if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
+ *code++ = OP_CIRCM;
+ }
+ else *code++ = OP_CIRC;
+ break;
+
+ case CHAR_DOLLAR_SIGN:
+ previous = NULL;
+ *code++ = ((options & PCRE_MULTILINE) != 0)? OP_DOLLM : OP_DOLL;
+ break;
+
+ /* There can never be a first char if '.' is first, whatever happens about
+ repeats. The value of reqchar doesn't change either. */
+
+ case CHAR_DOT:
+ if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
+ zerofirstchar = firstchar;
+ zerofirstcharflags = firstcharflags;
+ zeroreqchar = reqchar;
+ zeroreqcharflags = reqcharflags;
+ previous = code;
+ *code++ = ((options & PCRE_DOTALL) != 0)? OP_ALLANY: OP_ANY;
+ break;
+
+
+ /* ===================================================================*/
+ /* Character classes. If the included characters are all < 256, we build a
+ 32-byte bitmap of the permitted characters, except in the special case
+ where there is only one such character. For negated classes, we build the
+ map as usual, then invert it at the end. However, we use a different opcode
+ so that data characters > 255 can be handled correctly.
+
+ If the class contains characters outside the 0-255 range, a different
+ opcode is compiled. It may optionally have a bit map for characters < 256,
+ but those above are are explicitly listed afterwards. A flag byte tells
+ whether the bitmap is present, and whether this is a negated class or not.
+
+ In JavaScript compatibility mode, an isolated ']' causes an error. In
+ default (Perl) mode, it is treated as a data character. */
+
+ case CHAR_RIGHT_SQUARE_BRACKET:
+ if ((cd->external_options & PCRE_JAVASCRIPT_COMPAT) != 0)
+ {
+ *errorcodeptr = ERR64;
+ goto FAILED;
+ }
+ goto NORMAL_CHAR;
+
+ /* In another (POSIX) regex library, the ugly syntax [[:<:]] and [[:>:]] is
+ used for "start of word" and "end of word". As these are otherwise illegal
+ sequences, we don't break anything by recognizing them. They are replaced
+ by \b(?=\w) and \b(?<=\w) respectively. Sequences like [a[:<:]] are
+ erroneous and are handled by the normal code below. */
+
+ case CHAR_LEFT_SQUARE_BRACKET:
+ if (STRNCMP_UC_C8(ptr+1, STRING_WEIRD_STARTWORD, 6) == 0)
+ {
+ nestptr = ptr + 7;
+ ptr = sub_start_of_word - 1;
+ continue;
+ }
+
+ if (STRNCMP_UC_C8(ptr+1, STRING_WEIRD_ENDWORD, 6) == 0)
+ {
+ nestptr = ptr + 7;
+ ptr = sub_end_of_word - 1;
+ continue;
+ }
+
+ /* Handle a real character class. */
+
+ previous = code;
+
+ /* PCRE supports POSIX class stuff inside a class. Perl gives an error if
+ they are encountered at the top level, so we'll do that too. */
+
+ if ((ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT ||
+ ptr[1] == CHAR_EQUALS_SIGN) &&
+ check_posix_syntax(ptr, &tempptr))
+ {
+ *errorcodeptr = (ptr[1] == CHAR_COLON)? ERR13 : ERR31;
+ goto FAILED;
+ }
+
+ /* If the first character is '^', set the negation flag and skip it. Also,
+ if the first few characters (either before or after ^) are \Q\E or \E we
+ skip them too. This makes for compatibility with Perl. */
+
+ negate_class = FALSE;
+ for (;;)
+ {
+ c = *(++ptr);
+ if (c == CHAR_BACKSLASH)
+ {
+ if (ptr[1] == CHAR_E)
+ ptr++;
+ else if (STRNCMP_UC_C8(ptr + 1, STR_Q STR_BACKSLASH STR_E, 3) == 0)
+ ptr += 3;
+ else
+ break;
+ }
+ else if (!negate_class && c == CHAR_CIRCUMFLEX_ACCENT)
+ negate_class = TRUE;
+ else break;
+ }
+
+ /* Empty classes are allowed in JavaScript compatibility mode. Otherwise,
+ an initial ']' is taken as a data character -- the code below handles
+ that. In JS mode, [] must always fail, so generate OP_FAIL, whereas
+ [^] must match any character, so generate OP_ALLANY. */
+
+ if (c == CHAR_RIGHT_SQUARE_BRACKET &&
+ (cd->external_options & PCRE_JAVASCRIPT_COMPAT) != 0)
+ {
+ *code++ = negate_class? OP_ALLANY : OP_FAIL;
+ if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
+ zerofirstchar = firstchar;
+ zerofirstcharflags = firstcharflags;
+ break;
+ }
+
+ /* If a class contains a negative special such as \S, we need to flip the
+ negation flag at the end, so that support for characters > 255 works
+ correctly (they are all included in the class). */
+
+ should_flip_negation = FALSE;
+
+ /* Extended class (xclass) will be used when characters > 255
+ might match. */
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ xclass = FALSE;
+ class_uchardata = code + LINK_SIZE + 2; /* For XCLASS items */
+ class_uchardata_base = class_uchardata; /* Save the start */
+#endif
+
+ /* For optimization purposes, we track some properties of the class:
+ class_has_8bitchar will be non-zero if the class contains at least one <
+ 256 character; class_one_char will be 1 if the class contains just one
+ character; xclass_has_prop will be TRUE if unicode property checks
+ are present in the class. */
+
+ class_has_8bitchar = 0;
+ class_one_char = 0;
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ xclass_has_prop = FALSE;
+#endif
+
+ /* Initialize the 32-char bit map to all zeros. We build the map in a
+ temporary bit of memory, in case the class contains fewer than two
+ 8-bit characters because in that case the compiled code doesn't use the bit
+ map. */
+
+ memset(classbits, 0, 32 * sizeof(pcre_uint8));
+
+ /* Process characters until ] is reached. By writing this as a "do" it
+ means that an initial ] is taken as a data character. At the start of the
+ loop, c contains the first byte of the character. */
+
+ if (c != CHAR_NULL) do
+ {
+ const pcre_uchar *oldptr;
+
+#ifdef SUPPORT_UTF
+ if (utf && HAS_EXTRALEN(c))
+ { /* Braces are required because the */
+ GETCHARLEN(c, ptr, ptr); /* macro generates multiple statements */
+ }
+#endif
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ /* In the pre-compile phase, accumulate the length of any extra
+ data and reset the pointer. This is so that very large classes that
+ contain a zillion > 255 characters no longer overwrite the work space
+ (which is on the stack). We have to remember that there was XCLASS data,
+ however. */
+
+ if (lengthptr != NULL && class_uchardata > class_uchardata_base)
+ {
+ xclass = TRUE;
+ *lengthptr += class_uchardata - class_uchardata_base;
+ class_uchardata = class_uchardata_base;
+ }
+#endif
+
+ /* Inside \Q...\E everything is literal except \E */
+
+ if (inescq)
+ {
+ if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E) /* If we are at \E */
+ {
+ inescq = FALSE; /* Reset literal state */
+ ptr++; /* Skip the 'E' */
+ continue; /* Carry on with next */
+ }
+ goto CHECK_RANGE; /* Could be range if \E follows */
+ }
+
+ /* Handle POSIX class names. Perl allows a negation extension of the
+ form [:^name:]. A square bracket that doesn't match the syntax is
+ treated as a literal. We also recognize the POSIX constructions
+ [.ch.] and [=ch=] ("collating elements") and fault them, as Perl
+ 5.6 and 5.8 do. */
+
+ if (c == CHAR_LEFT_SQUARE_BRACKET &&
+ (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT ||
+ ptr[1] == CHAR_EQUALS_SIGN) && check_posix_syntax(ptr, &tempptr))
+ {
+ BOOL local_negate = FALSE;
+ int posix_class, taboffset, tabopt;
+ register const pcre_uint8 *cbits = cd->cbits;
+ pcre_uint8 pbits[32];
+
+ if (ptr[1] != CHAR_COLON)
+ {
+ *errorcodeptr = ERR31;
+ goto FAILED;
+ }
+
+ ptr += 2;
+ if (*ptr == CHAR_CIRCUMFLEX_ACCENT)
+ {
+ local_negate = TRUE;
+ should_flip_negation = TRUE; /* Note negative special */
+ ptr++;
+ }
+
+ posix_class = check_posix_name(ptr, (int)(tempptr - ptr));
+ if (posix_class < 0)
+ {
+ *errorcodeptr = ERR30;
+ goto FAILED;
+ }
+
+ /* If matching is caseless, upper and lower are converted to
+ alpha. This relies on the fact that the class table starts with
+ alpha, lower, upper as the first 3 entries. */
+
+ if ((options & PCRE_CASELESS) != 0 && posix_class <= 2)
+ posix_class = 0;
+
+ /* When PCRE_UCP is set, some of the POSIX classes are converted to
+ different escape sequences that use Unicode properties \p or \P. Others
+ that are not available via \p or \P generate XCL_PROP/XCL_NOTPROP
+ directly. */
+
+#ifdef SUPPORT_UCP
+ if ((options & PCRE_UCP) != 0)
+ {
+ unsigned int ptype = 0;
+ int pc = posix_class + ((local_negate)? POSIX_SUBSIZE/2 : 0);
+
+ /* The posix_substitutes table specifies which POSIX classes can be
+ converted to \p or \P items. */
+
+ if (posix_substitutes[pc] != NULL)
+ {
+ nestptr = tempptr + 1;
+ ptr = posix_substitutes[pc] - 1;
+ continue;
+ }
+
+ /* There are three other classes that generate special property calls
+ that are recognized only in an XCLASS. */
+
+ else switch(posix_class)
+ {
+ case PC_GRAPH:
+ ptype = PT_PXGRAPH;
+ /* Fall through */
+ case PC_PRINT:
+ if (ptype == 0) ptype = PT_PXPRINT;
+ /* Fall through */
+ case PC_PUNCT:
+ if (ptype == 0) ptype = PT_PXPUNCT;
+ *class_uchardata++ = local_negate? XCL_NOTPROP : XCL_PROP;
+ *class_uchardata++ = ptype;
+ *class_uchardata++ = 0;
+ xclass_has_prop = TRUE;
+ ptr = tempptr + 1;
+ continue;
+
+ /* For all other POSIX classes, no special action is taken in UCP
+ mode. Fall through to the non_UCP case. */
+
+ default:
+ break;
+ }
+ }
+#endif
+ /* In the non-UCP case, or when UCP makes no difference, we build the
+ bit map for the POSIX class in a chunk of local store because we may be
+ adding and subtracting from it, and we don't want to subtract bits that
+ may be in the main map already. At the end we or the result into the
+ bit map that is being built. */
+
+ posix_class *= 3;
+
+ /* Copy in the first table (always present) */
+
+ memcpy(pbits, cbits + posix_class_maps[posix_class],
+ 32 * sizeof(pcre_uint8));
+
+ /* If there is a second table, add or remove it as required. */
+
+ taboffset = posix_class_maps[posix_class + 1];
+ tabopt = posix_class_maps[posix_class + 2];
+
+ if (taboffset >= 0)
+ {
+ if (tabopt >= 0)
+ for (c = 0; c < 32; c++) pbits[c] |= cbits[c + taboffset];
+ else
+ for (c = 0; c < 32; c++) pbits[c] &= ~cbits[c + taboffset];
+ }
+
+ /* Now see if we need to remove any special characters. An option
+ value of 1 removes vertical space and 2 removes underscore. */
+
+ if (tabopt < 0) tabopt = -tabopt;
+ if (tabopt == 1) pbits[1] &= ~0x3c;
+ else if (tabopt == 2) pbits[11] &= 0x7f;
+
+ /* Add the POSIX table or its complement into the main table that is
+ being built and we are done. */
+
+ if (local_negate)
+ for (c = 0; c < 32; c++) classbits[c] |= ~pbits[c];
+ else
+ for (c = 0; c < 32; c++) classbits[c] |= pbits[c];
+
+ ptr = tempptr + 1;
+ /* Every class contains at least one < 256 character. */
+ class_has_8bitchar = 1;
+ /* Every class contains at least two characters. */
+ class_one_char = 2;
+ continue; /* End of POSIX syntax handling */
+ }
+
+ /* Backslash may introduce a single character, or it may introduce one
+ of the specials, which just set a flag. The sequence \b is a special
+ case. Inside a class (and only there) it is treated as backspace. We
+ assume that other escapes have more than one character in them, so
+ speculatively set both class_has_8bitchar and class_one_char bigger
+ than one. Unrecognized escapes fall through and are either treated
+ as literal characters (by default), or are faulted if
+ PCRE_EXTRA is set. */
+
+ if (c == CHAR_BACKSLASH)
+ {
+ escape = check_escape(&ptr, &ec, errorcodeptr, cd->bracount, options,
+ TRUE);
+ if (*errorcodeptr != 0) goto FAILED;
+ if (escape == 0) c = ec;
+ else if (escape == ESC_b) c = CHAR_BS; /* \b is backspace in a class */
+ else if (escape == ESC_N) /* \N is not supported in a class */
+ {
+ *errorcodeptr = ERR71;
+ goto FAILED;
+ }
+ else if (escape == ESC_Q) /* Handle start of quoted string */
+ {
+ if (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E)
+ {
+ ptr += 2; /* avoid empty string */
+ }
+ else inescq = TRUE;
+ continue;
+ }
+ else if (escape == ESC_E) continue; /* Ignore orphan \E */
+
+ else
+ {
+ register const pcre_uint8 *cbits = cd->cbits;
+ /* Every class contains at least two < 256 characters. */
+ class_has_8bitchar++;
+ /* Every class contains at least two characters. */
+ class_one_char += 2;
+
+ switch (escape)
+ {
+#ifdef SUPPORT_UCP
+ case ESC_du: /* These are the values given for \d etc */
+ case ESC_DU: /* when PCRE_UCP is set. We replace the */
+ case ESC_wu: /* escape sequence with an appropriate \p */
+ case ESC_WU: /* or \P to test Unicode properties instead */
+ case ESC_su: /* of the default ASCII testing. */
+ case ESC_SU:
+ nestptr = ptr;
+ ptr = substitutes[escape - ESC_DU] - 1; /* Just before substitute */
+ class_has_8bitchar--; /* Undo! */
+ continue;
+#endif
+ case ESC_d:
+ for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_digit];
+ continue;
+
+ case ESC_D:
+ should_flip_negation = TRUE;
+ for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_digit];
+ continue;
+
+ case ESC_w:
+ for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_word];
+ continue;
+
+ case ESC_W:
+ should_flip_negation = TRUE;
+ for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_word];
+ continue;
+
+ /* Perl 5.004 onwards omitted VT from \s, but restored it at Perl
+ 5.18. Before PCRE 8.34, we had to preserve the VT bit if it was
+ previously set by something earlier in the character class.
+ Luckily, the value of CHAR_VT is 0x0b in both ASCII and EBCDIC, so
+ we could just adjust the appropriate bit. From PCRE 8.34 we no
+ longer treat \s and \S specially. */
+
+ case ESC_s:
+ for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_space];
+ continue;
+
+ case ESC_S:
+ should_flip_negation = TRUE;
+ for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_space];
+ continue;
+
+ /* The rest apply in both UCP and non-UCP cases. */
+
+ case ESC_h:
+ (void)add_list_to_class(classbits, &class_uchardata, options, cd,
+ PRIV(hspace_list), NOTACHAR);
+ continue;
+
+ case ESC_H:
+ (void)add_not_list_to_class(classbits, &class_uchardata, options,
+ cd, PRIV(hspace_list));
+ continue;
+
+ case ESC_v:
+ (void)add_list_to_class(classbits, &class_uchardata, options, cd,
+ PRIV(vspace_list), NOTACHAR);
+ continue;
+
+ case ESC_V:
+ (void)add_not_list_to_class(classbits, &class_uchardata, options,
+ cd, PRIV(vspace_list));
+ continue;
+
+#ifdef SUPPORT_UCP
+ case ESC_p:
+ case ESC_P:
+ {
+ BOOL negated;
+ unsigned int ptype = 0, pdata = 0;
+ if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr))
+ goto FAILED;
+ *class_uchardata++ = ((escape == ESC_p) != negated)?
+ XCL_PROP : XCL_NOTPROP;
+ *class_uchardata++ = ptype;
+ *class_uchardata++ = pdata;
+ xclass_has_prop = TRUE;
+ class_has_8bitchar--; /* Undo! */
+ continue;
+ }
+#endif
+ /* Unrecognized escapes are faulted if PCRE is running in its
+ strict mode. By default, for compatibility with Perl, they are
+ treated as literals. */
+
+ default:
+ if ((options & PCRE_EXTRA) != 0)
+ {
+ *errorcodeptr = ERR7;
+ goto FAILED;
+ }
+ class_has_8bitchar--; /* Undo the speculative increase. */
+ class_one_char -= 2; /* Undo the speculative increase. */
+ c = *ptr; /* Get the final character and fall through */
+ break;
+ }
+ }
+
+ /* Fall through if the escape just defined a single character (c >= 0).
+ This may be greater than 256. */
+
+ escape = 0;
+
+ } /* End of backslash handling */
+
+ /* A character may be followed by '-' to form a range. However, Perl does
+ not permit ']' to be the end of the range. A '-' character at the end is
+ treated as a literal. Perl ignores orphaned \E sequences entirely. The
+ code for handling \Q and \E is messy. */
+
+ CHECK_RANGE:
+ while (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E)
+ {
+ inescq = FALSE;
+ ptr += 2;
+ }
+ oldptr = ptr;
+
+ /* Remember if \r or \n were explicitly used */
+
+ if (c == CHAR_CR || c == CHAR_NL) cd->external_flags |= PCRE_HASCRORLF;
+
+ /* Check for range */
+
+ if (!inescq && ptr[1] == CHAR_MINUS)
+ {
+ pcre_uint32 d;
+ ptr += 2;
+ while (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_E) ptr += 2;
+
+ /* If we hit \Q (not followed by \E) at this point, go into escaped
+ mode. */
+
+ while (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_Q)
+ {
+ ptr += 2;
+ if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_E)
+ { ptr += 2; continue; }
+ inescq = TRUE;
+ break;
+ }
+
+ /* Minus (hyphen) at the end of a class is treated as a literal, so put
+ back the pointer and jump to handle the character that preceded it. */
+
+ if (*ptr == CHAR_NULL || (!inescq && *ptr == CHAR_RIGHT_SQUARE_BRACKET))
+ {
+ ptr = oldptr;
+ goto CLASS_SINGLE_CHARACTER;
+ }
+
+ /* Otherwise, we have a potential range; pick up the next character */
+
+#ifdef SUPPORT_UTF
+ if (utf)
+ { /* Braces are required because the */
+ GETCHARLEN(d, ptr, ptr); /* macro generates multiple statements */
+ }
+ else
+#endif
+ d = *ptr; /* Not UTF-8 mode */
+
+ /* The second part of a range can be a single-character escape
+ sequence, but not any of the other escapes. Perl treats a hyphen as a
+ literal in such circumstances. However, in Perl's warning mode, a
+ warning is given, so PCRE now faults it as it is almost certainly a
+ mistake on the user's part. */
+
+ if (!inescq)
+ {
+ if (d == CHAR_BACKSLASH)
+ {
+ int descape;
+ descape = check_escape(&ptr, &d, errorcodeptr, cd->bracount, options, TRUE);
+ if (*errorcodeptr != 0) goto FAILED;
+
+ /* 0 means a character was put into d; \b is backspace; any other
+ special causes an error. */
+
+ if (descape != 0)
+ {
+ if (descape == ESC_b) d = CHAR_BS; else
+ {
+ *errorcodeptr = ERR83;
+ goto FAILED;
+ }
+ }
+ }
+
+ /* A hyphen followed by a POSIX class is treated in the same way. */
+
+ else if (d == CHAR_LEFT_SQUARE_BRACKET &&
+ (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT ||
+ ptr[1] == CHAR_EQUALS_SIGN) &&
+ check_posix_syntax(ptr, &tempptr))
+ {
+ *errorcodeptr = ERR83;
+ goto FAILED;
+ }
+ }
+
+ /* Check that the two values are in the correct order. Optimize
+ one-character ranges. */
+
+ if (d < c)
+ {
+ *errorcodeptr = ERR8;
+ goto FAILED;
+ }
+ if (d == c) goto CLASS_SINGLE_CHARACTER; /* A few lines below */
+
+ /* We have found a character range, so single character optimizations
+ cannot be done anymore. Any value greater than 1 indicates that there
+ is more than one character. */
+
+ class_one_char = 2;
+
+ /* Remember an explicit \r or \n, and add the range to the class. */
+
+ if (d == CHAR_CR || d == CHAR_NL) cd->external_flags |= PCRE_HASCRORLF;
+
+ class_has_8bitchar +=
+ add_to_class(classbits, &class_uchardata, options, cd, c, d);
+
+ continue; /* Go get the next char in the class */
+ }
+
+ /* Handle a single character - we can get here for a normal non-escape
+ char, or after \ that introduces a single character or for an apparent
+ range that isn't. Only the value 1 matters for class_one_char, so don't
+ increase it if it is already 2 or more ... just in case there's a class
+ with a zillion characters in it. */
+
+ CLASS_SINGLE_CHARACTER:
+ if (class_one_char < 2) class_one_char++;
+
+ /* If class_one_char is 1, we have the first single character in the
+ class, and there have been no prior ranges, or XCLASS items generated by
+ escapes. If this is the final character in the class, we can optimize by
+ turning the item into a 1-character OP_CHAR[I] if it's positive, or
+ OP_NOT[I] if it's negative. In the positive case, it can cause firstchar
+ to be set. Otherwise, there can be no first char if this item is first,
+ whatever repeat count may follow. In the case of reqchar, save the
+ previous value for reinstating. */
+
+ if (class_one_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
+ {
+ ptr++;
+ zeroreqchar = reqchar;
+ zeroreqcharflags = reqcharflags;
+
+ if (negate_class)
+ {
+#ifdef SUPPORT_UCP
+ int d;
+#endif
+ if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
+ zerofirstchar = firstchar;
+ zerofirstcharflags = firstcharflags;
+
+ /* For caseless UTF-8 mode when UCP support is available, check
+ whether this character has more than one other case. If so, generate
+ a special OP_NOTPROP item instead of OP_NOTI. */
+
+#ifdef SUPPORT_UCP
+ if (utf && (options & PCRE_CASELESS) != 0 &&
+ (d = UCD_CASESET(c)) != 0)
+ {
+ *code++ = OP_NOTPROP;
+ *code++ = PT_CLIST;
+ *code++ = d;
+ }
+ else
+#endif
+ /* Char has only one other case, or UCP not available */
+
+ {
+ *code++ = ((options & PCRE_CASELESS) != 0)? OP_NOTI: OP_NOT;
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR)
+ code += PRIV(ord2utf)(c, code);
+ else
+#endif
+ *code++ = c;
+ }
+
+ /* We are finished with this character class */
+
+ goto END_CLASS;
+ }
+
+ /* For a single, positive character, get the value into mcbuffer, and
+ then we can handle this with the normal one-character code. */
+
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR)
+ mclength = PRIV(ord2utf)(c, mcbuffer);
+ else
+#endif
+ {
+ mcbuffer[0] = c;
+ mclength = 1;
+ }
+ goto ONE_CHAR;
+ } /* End of 1-char optimization */
+
+ /* There is more than one character in the class, or an XCLASS item
+ has been generated. Add this character to the class. */
+
+ class_has_8bitchar +=
+ add_to_class(classbits, &class_uchardata, options, cd, c, c);
+ }
+
+ /* Loop until ']' reached. This "while" is the end of the "do" far above.
+ If we are at the end of an internal nested string, revert to the outer
+ string. */
+
+ while (((c = *(++ptr)) != CHAR_NULL ||
+ (nestptr != NULL &&
+ (ptr = nestptr, nestptr = NULL, c = *(++ptr)) != CHAR_NULL)) &&
+ (c != CHAR_RIGHT_SQUARE_BRACKET || inescq));
+
+ /* Check for missing terminating ']' */
+
+ if (c == CHAR_NULL)
+ {
+ *errorcodeptr = ERR6;
+ goto FAILED;
+ }
+
+ /* We will need an XCLASS if data has been placed in class_uchardata. In
+ the second phase this is a sufficient test. However, in the pre-compile
+ phase, class_uchardata gets emptied to prevent workspace overflow, so it
+ only if the very last character in the class needs XCLASS will it contain
+ anything at this point. For this reason, xclass gets set TRUE above when
+ uchar_classdata is emptied, and that's why this code is the way it is here
+ instead of just doing a test on class_uchardata below. */
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ if (class_uchardata > class_uchardata_base) xclass = TRUE;
+#endif
+
+ /* If this is the first thing in the branch, there can be no first char
+ setting, whatever the repeat count. Any reqchar setting must remain
+ unchanged after any kind of repeat. */
+
+ if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
+ zerofirstchar = firstchar;
+ zerofirstcharflags = firstcharflags;
+ zeroreqchar = reqchar;
+ zeroreqcharflags = reqcharflags;
+
+ /* If there are characters with values > 255, we have to compile an
+ extended class, with its own opcode, unless there was a negated special
+ such as \S in the class, and PCRE_UCP is not set, because in that case all
+ characters > 255 are in the class, so any that were explicitly given as
+ well can be ignored. If (when there are explicit characters > 255 that must
+ be listed) there are no characters < 256, we can omit the bitmap in the
+ actual compiled code. */
+
+#ifdef SUPPORT_UTF
+ if (xclass && (!should_flip_negation || (options & PCRE_UCP) != 0))
+#elif !defined COMPILE_PCRE8
+ if (xclass && !should_flip_negation)
+#endif
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ {
+ *class_uchardata++ = XCL_END; /* Marks the end of extra data */
+ *code++ = OP_XCLASS;
+ code += LINK_SIZE;
+ *code = negate_class? XCL_NOT:0;
+ if (xclass_has_prop) *code |= XCL_HASPROP;
+
+ /* If the map is required, move up the extra data to make room for it;
+ otherwise just move the code pointer to the end of the extra data. */
+
+ if (class_has_8bitchar > 0)
+ {
+ *code++ |= XCL_MAP;
+ memmove(code + (32 / sizeof(pcre_uchar)), code,
+ IN_UCHARS(class_uchardata - code));
+ if (negate_class && !xclass_has_prop)
+ for (c = 0; c < 32; c++) classbits[c] = ~classbits[c];
+ memcpy(code, classbits, 32);
+ code = class_uchardata + (32 / sizeof(pcre_uchar));
+ }
+ else code = class_uchardata;
+
+ /* Now fill in the complete length of the item */
+
+ PUT(previous, 1, (int)(code - previous));
+ break; /* End of class handling */
+ }
+#endif
+
+ /* If there are no characters > 255, or they are all to be included or
+ excluded, set the opcode to OP_CLASS or OP_NCLASS, depending on whether the
+ whole class was negated and whether there were negative specials such as \S
+ (non-UCP) in the class. Then copy the 32-byte map into the code vector,
+ negating it if necessary. */
+
+ *code++ = (negate_class == should_flip_negation) ? OP_CLASS : OP_NCLASS;
+ if (lengthptr == NULL) /* Save time in the pre-compile phase */
+ {
+ if (negate_class)
+ for (c = 0; c < 32; c++) classbits[c] = ~classbits[c];
+ memcpy(code, classbits, 32);
+ }
+ code += 32 / sizeof(pcre_uchar);
+
+ END_CLASS:
+ break;
+
+
+ /* ===================================================================*/
+ /* Various kinds of repeat; '{' is not necessarily a quantifier, but this
+ has been tested above. */
+
+ case CHAR_LEFT_CURLY_BRACKET:
+ if (!is_quantifier) goto NORMAL_CHAR;
+ ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorcodeptr);
+ if (*errorcodeptr != 0) goto FAILED;
+ goto REPEAT;
+
+ case CHAR_ASTERISK:
+ repeat_min = 0;
+ repeat_max = -1;
+ goto REPEAT;
+
+ case CHAR_PLUS:
+ repeat_min = 1;
+ repeat_max = -1;
+ goto REPEAT;
+
+ case CHAR_QUESTION_MARK:
+ repeat_min = 0;
+ repeat_max = 1;
+
+ REPEAT:
+ if (previous == NULL)
+ {
+ *errorcodeptr = ERR9;
+ goto FAILED;
+ }
+
+ if (repeat_min == 0)
+ {
+ firstchar = zerofirstchar; /* Adjust for zero repeat */
+ firstcharflags = zerofirstcharflags;
+ reqchar = zeroreqchar; /* Ditto */
+ reqcharflags = zeroreqcharflags;
+ }
+
+ /* Remember whether this is a variable length repeat */
+
+ reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY;
+
+ op_type = 0; /* Default single-char op codes */
+ possessive_quantifier = FALSE; /* Default not possessive quantifier */
+
+ /* Save start of previous item, in case we have to move it up in order to
+ insert something before it. */
+
+ tempcode = previous;
+
+ /* Before checking for a possessive quantifier, we must skip over
+ whitespace and comments in extended mode because Perl allows white space at
+ this point. */
+
+ if ((options & PCRE_EXTENDED) != 0)
+ {
+ const pcre_uchar *p = ptr + 1;
+ for (;;)
+ {
+ while (MAX_255(*p) && (cd->ctypes[*p] & ctype_space) != 0) p++;
+ if (*p != CHAR_NUMBER_SIGN) break;
+ p++;
+ while (*p != CHAR_NULL)
+ {
+ if (IS_NEWLINE(p)) /* For non-fixed-length newline cases, */
+ { /* IS_NEWLINE sets cd->nllen. */
+ p += cd->nllen;
+ break;
+ }
+ p++;
+#ifdef SUPPORT_UTF
+ if (utf) FORWARDCHAR(p);
+#endif
+ } /* Loop for comment characters */
+ } /* Loop for multiple comments */
+ ptr = p - 1; /* Character before the next significant one. */
+ }
+
+ /* If the next character is '+', we have a possessive quantifier. This
+ implies greediness, whatever the setting of the PCRE_UNGREEDY option.
+ If the next character is '?' this is a minimizing repeat, by default,
+ but if PCRE_UNGREEDY is set, it works the other way round. We change the
+ repeat type to the non-default. */
+
+ if (ptr[1] == CHAR_PLUS)
+ {
+ repeat_type = 0; /* Force greedy */
+ possessive_quantifier = TRUE;
+ ptr++;
+ }
+ else if (ptr[1] == CHAR_QUESTION_MARK)
+ {
+ repeat_type = greedy_non_default;
+ ptr++;
+ }
+ else repeat_type = greedy_default;
+
+ /* If previous was a recursion call, wrap it in atomic brackets so that
+ previous becomes the atomic group. All recursions were so wrapped in the
+ past, but it no longer happens for non-repeated recursions. In fact, the
+ repeated ones could be re-implemented independently so as not to need this,
+ but for the moment we rely on the code for repeating groups. */
+
+ if (*previous == OP_RECURSE)
+ {
+ memmove(previous + 1 + LINK_SIZE, previous, IN_UCHARS(1 + LINK_SIZE));
+ *previous = OP_ONCE;
+ PUT(previous, 1, 2 + 2*LINK_SIZE);
+ previous[2 + 2*LINK_SIZE] = OP_KET;
+ PUT(previous, 3 + 2*LINK_SIZE, 2 + 2*LINK_SIZE);
+ code += 2 + 2 * LINK_SIZE;
+ length_prevgroup = 3 + 3*LINK_SIZE;
+
+ /* When actually compiling, we need to check whether this was a forward
+ reference, and if so, adjust the offset. */
+
+ if (lengthptr == NULL && cd->hwm >= cd->start_workspace + LINK_SIZE)
+ {
+ int offset = GET(cd->hwm, -LINK_SIZE);
+ if (offset == previous + 1 - cd->start_code)
+ PUT(cd->hwm, -LINK_SIZE, offset + 1 + LINK_SIZE);
+ }
+ }
+
+ /* Now handle repetition for the different types of item. */
+
+ /* If previous was a character or negated character match, abolish the item
+ and generate a repeat item instead. If a char item has a minimum of more
+ than one, ensure that it is set in reqchar - it might not be if a sequence
+ such as x{3} is the first thing in a branch because the x will have gone
+ into firstchar instead. */
+
+ if (*previous == OP_CHAR || *previous == OP_CHARI
+ || *previous == OP_NOT || *previous == OP_NOTI)
+ {
+ switch (*previous)
+ {
+ default: /* Make compiler happy. */
+ case OP_CHAR: op_type = OP_STAR - OP_STAR; break;
+ case OP_CHARI: op_type = OP_STARI - OP_STAR; break;
+ case OP_NOT: op_type = OP_NOTSTAR - OP_STAR; break;
+ case OP_NOTI: op_type = OP_NOTSTARI - OP_STAR; break;
+ }
+
+ /* Deal with UTF characters that take up more than one character. It's
+ easier to write this out separately than try to macrify it. Use c to
+ hold the length of the character in bytes, plus UTF_LENGTH to flag that
+ it's a length rather than a small character. */
+
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (utf && NOT_FIRSTCHAR(code[-1]))
+ {
+ pcre_uchar *lastchar = code - 1;
+ BACKCHAR(lastchar);
+ c = (int)(code - lastchar); /* Length of UTF-8 character */
+ memcpy(utf_chars, lastchar, IN_UCHARS(c)); /* Save the char */
+ c |= UTF_LENGTH; /* Flag c as a length */
+ }
+ else
+#endif /* SUPPORT_UTF */
+
+ /* Handle the case of a single charater - either with no UTF support, or
+ with UTF disabled, or for a single character UTF character. */
+ {
+ c = code[-1];
+ if (*previous <= OP_CHARI && repeat_min > 1)
+ {
+ reqchar = c;
+ reqcharflags = req_caseopt | cd->req_varyopt;
+ }
+ }
+
+ goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */
+ }
+
+ /* If previous was a character type match (\d or similar), abolish it and
+ create a suitable repeat item. The code is shared with single-character
+ repeats by setting op_type to add a suitable offset into repeat_type. Note
+ the the Unicode property types will be present only when SUPPORT_UCP is
+ defined, but we don't wrap the little bits of code here because it just
+ makes it horribly messy. */
+
+ else if (*previous < OP_EODN)
+ {
+ pcre_uchar *oldcode;
+ int prop_type, prop_value;
+ op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */
+ c = *previous;
+
+ OUTPUT_SINGLE_REPEAT:
+ if (*previous == OP_PROP || *previous == OP_NOTPROP)
+ {
+ prop_type = previous[1];
+ prop_value = previous[2];
+ }
+ else prop_type = prop_value = -1;
+
+ oldcode = code;
+ code = previous; /* Usually overwrite previous item */
+
+ /* If the maximum is zero then the minimum must also be zero; Perl allows
+ this case, so we do too - by simply omitting the item altogether. */
+
+ if (repeat_max == 0) goto END_REPEAT;
+
+ /* Combine the op_type with the repeat_type */
+
+ repeat_type += op_type;
+
+ /* A minimum of zero is handled either as the special case * or ?, or as
+ an UPTO, with the maximum given. */
+
+ if (repeat_min == 0)
+ {
+ if (repeat_max == -1) *code++ = OP_STAR + repeat_type;
+ else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type;
+ else
+ {
+ *code++ = OP_UPTO + repeat_type;
+ PUT2INC(code, 0, repeat_max);
+ }
+ }
+
+ /* A repeat minimum of 1 is optimized into some special cases. If the
+ maximum is unlimited, we use OP_PLUS. Otherwise, the original item is
+ left in place and, if the maximum is greater than 1, we use OP_UPTO with
+ one less than the maximum. */
+
+ else if (repeat_min == 1)
+ {
+ if (repeat_max == -1)
+ *code++ = OP_PLUS + repeat_type;
+ else
+ {
+ code = oldcode; /* leave previous item in place */
+ if (repeat_max == 1) goto END_REPEAT;
+ *code++ = OP_UPTO + repeat_type;
+ PUT2INC(code, 0, repeat_max - 1);
+ }
+ }
+
+ /* The case {n,n} is just an EXACT, while the general case {n,m} is
+ handled as an EXACT followed by an UPTO. */
+
+ else
+ {
+ *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */
+ PUT2INC(code, 0, repeat_min);
+
+ /* If the maximum is unlimited, insert an OP_STAR. Before doing so,
+ we have to insert the character for the previous code. For a repeated
+ Unicode property match, there are two extra bytes that define the
+ required property. In UTF-8 mode, long characters have their length in
+ c, with the UTF_LENGTH bit as a flag. */
+
+ if (repeat_max < 0)
+ {
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (utf && (c & UTF_LENGTH) != 0)
+ {
+ memcpy(code, utf_chars, IN_UCHARS(c & 7));
+ code += c & 7;
+ }
+ else
+#endif
+ {
+ *code++ = c;
+ if (prop_type >= 0)
+ {
+ *code++ = prop_type;
+ *code++ = prop_value;
+ }
+ }
+ *code++ = OP_STAR + repeat_type;
+ }
+
+ /* Else insert an UPTO if the max is greater than the min, again
+ preceded by the character, for the previously inserted code. If the
+ UPTO is just for 1 instance, we can use QUERY instead. */
+
+ else if (repeat_max != repeat_min)
+ {
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (utf && (c & UTF_LENGTH) != 0)
+ {
+ memcpy(code, utf_chars, IN_UCHARS(c & 7));
+ code += c & 7;
+ }
+ else
+#endif
+ *code++ = c;
+ if (prop_type >= 0)
+ {
+ *code++ = prop_type;
+ *code++ = prop_value;
+ }
+ repeat_max -= repeat_min;
+
+ if (repeat_max == 1)
+ {
+ *code++ = OP_QUERY + repeat_type;
+ }
+ else
+ {
+ *code++ = OP_UPTO + repeat_type;
+ PUT2INC(code, 0, repeat_max);
+ }
+ }
+ }
+
+ /* The character or character type itself comes last in all cases. */
+
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (utf && (c & UTF_LENGTH) != 0)
+ {
+ memcpy(code, utf_chars, IN_UCHARS(c & 7));
+ code += c & 7;
+ }
+ else
+#endif
+ *code++ = c;
+
+ /* For a repeated Unicode property match, there are two extra bytes that
+ define the required property. */
+
+#ifdef SUPPORT_UCP
+ if (prop_type >= 0)
+ {
+ *code++ = prop_type;
+ *code++ = prop_value;
+ }
+#endif
+ }
+
+ /* If previous was a character class or a back reference, we put the repeat
+ stuff after it, but just skip the item if the repeat was {0,0}. */
+
+ else if (*previous == OP_CLASS || *previous == OP_NCLASS ||
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ *previous == OP_XCLASS ||
+#endif
+ *previous == OP_REF || *previous == OP_REFI ||
+ *previous == OP_DNREF || *previous == OP_DNREFI)
+ {
+ if (repeat_max == 0)
+ {
+ code = previous;
+ goto END_REPEAT;
+ }
+
+ if (repeat_min == 0 && repeat_max == -1)
+ *code++ = OP_CRSTAR + repeat_type;
+ else if (repeat_min == 1 && repeat_max == -1)
+ *code++ = OP_CRPLUS + repeat_type;
+ else if (repeat_min == 0 && repeat_max == 1)
+ *code++ = OP_CRQUERY + repeat_type;
+ else
+ {
+ *code++ = OP_CRRANGE + repeat_type;
+ PUT2INC(code, 0, repeat_min);
+ if (repeat_max == -1) repeat_max = 0; /* 2-byte encoding for max */
+ PUT2INC(code, 0, repeat_max);
+ }
+ }
+
+ /* If previous was a bracket group, we may have to replicate it in certain
+ cases. Note that at this point we can encounter only the "basic" bracket
+ opcodes such as BRA and CBRA, as this is the place where they get converted
+ into the more special varieties such as BRAPOS and SBRA. A test for >=
+ OP_ASSERT and <= OP_COND includes ASSERT, ASSERT_NOT, ASSERTBACK,
+ ASSERTBACK_NOT, ONCE, ONCE_NC, BRA, BRAPOS, CBRA, CBRAPOS, and COND.
+ Originally, PCRE did not allow repetition of assertions, but now it does,
+ for Perl compatibility. */
+
+ else if (*previous >= OP_ASSERT && *previous <= OP_COND)
+ {
+ register int i;
+ int len = (int)(code - previous);
+ pcre_uchar *bralink = NULL;
+ pcre_uchar *brazeroptr = NULL;
+
+ /* Repeating a DEFINE group is pointless, but Perl allows the syntax, so
+ we just ignore the repeat. */
+
+ if (*previous == OP_COND && previous[LINK_SIZE+1] == OP_DEF)
+ goto END_REPEAT;
+
+ /* There is no sense in actually repeating assertions. The only potential
+ use of repetition is in cases when the assertion is optional. Therefore,
+ if the minimum is greater than zero, just ignore the repeat. If the
+ maximum is not zero or one, set it to 1. */
+
+ if (*previous < OP_ONCE) /* Assertion */
+ {
+ if (repeat_min > 0) goto END_REPEAT;
+ if (repeat_max < 0 || repeat_max > 1) repeat_max = 1;
+ }
+
+ /* The case of a zero minimum is special because of the need to stick
+ OP_BRAZERO in front of it, and because the group appears once in the
+ data, whereas in other cases it appears the minimum number of times. For
+ this reason, it is simplest to treat this case separately, as otherwise
+ the code gets far too messy. There are several special subcases when the
+ minimum is zero. */
+
+ if (repeat_min == 0)
+ {
+ /* If the maximum is also zero, we used to just omit the group from the
+ output altogether, like this:
+
+ ** if (repeat_max == 0)
+ ** {
+ ** code = previous;
+ ** goto END_REPEAT;
+ ** }
+
+ However, that fails when a group or a subgroup within it is referenced
+ as a subroutine from elsewhere in the pattern, so now we stick in
+ OP_SKIPZERO in front of it so that it is skipped on execution. As we
+ don't have a list of which groups are referenced, we cannot do this
+ selectively.
+
+ If the maximum is 1 or unlimited, we just have to stick in the BRAZERO
+ and do no more at this point. However, we do need to adjust any
+ OP_RECURSE calls inside the group that refer to the group itself or any
+ internal or forward referenced group, because the offset is from the
+ start of the whole regex. Temporarily terminate the pattern while doing
+ this. */
+
+ if (repeat_max <= 1) /* Covers 0, 1, and unlimited */
+ {
+ *code = OP_END;
+ adjust_recurse(previous, 1, utf, cd, save_hwm);
+ memmove(previous + 1, previous, IN_UCHARS(len));
+ code++;
+ if (repeat_max == 0)
+ {
+ *previous++ = OP_SKIPZERO;
+ goto END_REPEAT;
+ }
+ brazeroptr = previous; /* Save for possessive optimizing */
+ *previous++ = OP_BRAZERO + repeat_type;
+ }
+
+ /* If the maximum is greater than 1 and limited, we have to replicate
+ in a nested fashion, sticking OP_BRAZERO before each set of brackets.
+ The first one has to be handled carefully because it's the original
+ copy, which has to be moved up. The remainder can be handled by code
+ that is common with the non-zero minimum case below. We have to
+ adjust the value or repeat_max, since one less copy is required. Once
+ again, we may have to adjust any OP_RECURSE calls inside the group. */
+
+ else
+ {
+ int offset;
+ *code = OP_END;
+ adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, save_hwm);
+ memmove(previous + 2 + LINK_SIZE, previous, IN_UCHARS(len));
+ code += 2 + LINK_SIZE;
+ *previous++ = OP_BRAZERO + repeat_type;
+ *previous++ = OP_BRA;
+
+ /* We chain together the bracket offset fields that have to be
+ filled in later when the ends of the brackets are reached. */
+
+ offset = (bralink == NULL)? 0 : (int)(previous - bralink);
+ bralink = previous;
+ PUTINC(previous, 0, offset);
+ }
+
+ repeat_max--;
+ }
+
+ /* If the minimum is greater than zero, replicate the group as many
+ times as necessary, and adjust the maximum to the number of subsequent
+ copies that we need. If we set a first char from the group, and didn't
+ set a required char, copy the latter from the former. If there are any
+ forward reference subroutine calls in the group, there will be entries on
+ the workspace list; replicate these with an appropriate increment. */
+
+ else
+ {
+ if (repeat_min > 1)
+ {
+ /* In the pre-compile phase, we don't actually do the replication. We
+ just adjust the length as if we had. Do some paranoid checks for
+ potential integer overflow. The INT64_OR_DOUBLE type is a 64-bit
+ integer type when available, otherwise double. */
+
+ if (lengthptr != NULL)
+ {
+ int delta = (repeat_min - 1)*length_prevgroup;
+ if ((INT64_OR_DOUBLE)(repeat_min - 1)*
+ (INT64_OR_DOUBLE)length_prevgroup >
+ (INT64_OR_DOUBLE)INT_MAX ||
+ OFLOW_MAX - *lengthptr < delta)
+ {
+ *errorcodeptr = ERR20;
+ goto FAILED;
+ }
+ *lengthptr += delta;
+ }
+
+ /* This is compiling for real. If there is a set first byte for
+ the group, and we have not yet set a "required byte", set it. Make
+ sure there is enough workspace for copying forward references before
+ doing the copy. */
+
+ else
+ {
+ if (groupsetfirstchar && reqcharflags < 0)
+ {
+ reqchar = firstchar;
+ reqcharflags = firstcharflags;
+ }
+
+ for (i = 1; i < repeat_min; i++)
+ {
+ pcre_uchar *hc;
+ pcre_uchar *this_hwm = cd->hwm;
+ memcpy(code, previous, IN_UCHARS(len));
+
+ while (cd->hwm > cd->start_workspace + cd->workspace_size -
+ WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm))
+ {
+ int save_offset = save_hwm - cd->start_workspace;
+ int this_offset = this_hwm - cd->start_workspace;
+ *errorcodeptr = expand_workspace(cd);
+ if (*errorcodeptr != 0) goto FAILED;
+ save_hwm = (pcre_uchar *)cd->start_workspace + save_offset;
+ this_hwm = (pcre_uchar *)cd->start_workspace + this_offset;
+ }
+
+ for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE)
+ {
+ PUT(cd->hwm, 0, GET(hc, 0) + len);
+ cd->hwm += LINK_SIZE;
+ }
+ save_hwm = this_hwm;
+ code += len;
+ }
+ }
+ }
+
+ if (repeat_max > 0) repeat_max -= repeat_min;
+ }
+
+ /* This code is common to both the zero and non-zero minimum cases. If
+ the maximum is limited, it replicates the group in a nested fashion,
+ remembering the bracket starts on a stack. In the case of a zero minimum,
+ the first one was set up above. In all cases the repeat_max now specifies
+ the number of additional copies needed. Again, we must remember to
+ replicate entries on the forward reference list. */
+
+ if (repeat_max >= 0)
+ {
+ /* In the pre-compile phase, we don't actually do the replication. We
+ just adjust the length as if we had. For each repetition we must add 1
+ to the length for BRAZERO and for all but the last repetition we must
+ add 2 + 2*LINKSIZE to allow for the nesting that occurs. Do some
+ paranoid checks to avoid integer overflow. The INT64_OR_DOUBLE type is
+ a 64-bit integer type when available, otherwise double. */
+
+ if (lengthptr != NULL && repeat_max > 0)
+ {
+ int delta = repeat_max * (length_prevgroup + 1 + 2 + 2*LINK_SIZE) -
+ 2 - 2*LINK_SIZE; /* Last one doesn't nest */
+ if ((INT64_OR_DOUBLE)repeat_max *
+ (INT64_OR_DOUBLE)(length_prevgroup + 1 + 2 + 2*LINK_SIZE)
+ > (INT64_OR_DOUBLE)INT_MAX ||
+ OFLOW_MAX - *lengthptr < delta)
+ {
+ *errorcodeptr = ERR20;
+ goto FAILED;
+ }
+ *lengthptr += delta;
+ }
+
+ /* This is compiling for real */
+
+ else for (i = repeat_max - 1; i >= 0; i--)
+ {
+ pcre_uchar *hc;
+ pcre_uchar *this_hwm = cd->hwm;
+
+ *code++ = OP_BRAZERO + repeat_type;
+
+ /* All but the final copy start a new nesting, maintaining the
+ chain of brackets outstanding. */
+
+ if (i != 0)
+ {
+ int offset;
+ *code++ = OP_BRA;
+ offset = (bralink == NULL)? 0 : (int)(code - bralink);
+ bralink = code;
+ PUTINC(code, 0, offset);
+ }
+
+ memcpy(code, previous, IN_UCHARS(len));
+
+ /* Ensure there is enough workspace for forward references before
+ copying them. */
+
+ while (cd->hwm > cd->start_workspace + cd->workspace_size -
+ WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm))
+ {
+ int save_offset = save_hwm - cd->start_workspace;
+ int this_offset = this_hwm - cd->start_workspace;
+ *errorcodeptr = expand_workspace(cd);
+ if (*errorcodeptr != 0) goto FAILED;
+ save_hwm = (pcre_uchar *)cd->start_workspace + save_offset;
+ this_hwm = (pcre_uchar *)cd->start_workspace + this_offset;
+ }
+
+ for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE)
+ {
+ PUT(cd->hwm, 0, GET(hc, 0) + len + ((i != 0)? 2+LINK_SIZE : 1));
+ cd->hwm += LINK_SIZE;
+ }
+ save_hwm = this_hwm;
+ code += len;
+ }
+
+ /* Now chain through the pending brackets, and fill in their length
+ fields (which are holding the chain links pro tem). */
+
+ while (bralink != NULL)
+ {
+ int oldlinkoffset;
+ int offset = (int)(code - bralink + 1);
+ pcre_uchar *bra = code - offset;
+ oldlinkoffset = GET(bra, 1);
+ bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset;
+ *code++ = OP_KET;
+ PUTINC(code, 0, offset);
+ PUT(bra, 1, offset);
+ }
+ }
+
+ /* 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.
+
+ 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.]
+
+ 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 pcre_exec(). 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
+ atomic brackets, does not happen. When the minimum is greater than 1,
+ there will be earlier copies of the group, and so we still have to wrap
+ the whole thing. */
+
+ else
+ {
+ pcre_uchar *ketcode = code - 1 - LINK_SIZE;
+ pcre_uchar *bracode = ketcode - GET(ketcode, 1);
+
+ /* Convert possessive ONCE brackets to non-capturing */
+
+ if ((*bracode == OP_ONCE || *bracode == OP_ONCE_NC) &&
+ possessive_quantifier) *bracode = OP_BRA;
+
+ /* For non-possessive ONCE brackets, all we need to do is to
+ set the KET. */
+
+ if (*bracode == OP_ONCE || *bracode == OP_ONCE_NC)
+ *ketcode = OP_KETRMAX + repeat_type;
+
+ /* Handle non-ONCE brackets and possessive ONCEs (which have been
+ converted to non-capturing above). */
+
+ else
+ {
+ /* In the compile phase, check for empty string matching. */
+
+ if (lengthptr == NULL)
+ {
+ pcre_uchar *scode = bracode;
+ do
+ {
+ if (could_be_empty_branch(scode, ketcode, utf, cd, NULL))
+ {
+ *bracode += OP_SBRA - OP_BRA;
+ break;
+ }
+ scode += GET(scode, 1);
+ }
+ while (*scode == OP_ALT);
+ }
+
+ /* Handle possessive quantifiers. */
+
+ if (possessive_quantifier)
+ {
+ /* For COND brackets, we wrap the whole thing in a possessively
+ repeated non-capturing bracket, because we have not invented POS
+ versions of the COND opcodes. Because we are moving code along, we
+ must ensure that any pending recursive references are updated. */
+
+ if (*bracode == OP_COND || *bracode == OP_SCOND)
+ {
+ int nlen = (int)(code - bracode);
+ *code = OP_END;
+ adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, save_hwm);
+ memmove(bracode + 1 + LINK_SIZE, bracode, IN_UCHARS(nlen));
+ code += 1 + LINK_SIZE;
+ nlen += 1 + LINK_SIZE;
+ *bracode = OP_BRAPOS;
+ *code++ = OP_KETRPOS;
+ PUTINC(code, 0, nlen);
+ PUT(bracode, 1, nlen);
+ }
+
+ /* For non-COND brackets, we modify the BRA code and use KETRPOS. */
+
+ else
+ {
+ *bracode += 1; /* Switch to xxxPOS opcodes */
+ *ketcode = OP_KETRPOS;
+ }
+
+ /* If the minimum is zero, mark it as possessive, then unset the
+ possessive flag when the minimum is 0 or 1. */
+
+ if (brazeroptr != NULL) *brazeroptr = OP_BRAPOSZERO;
+ if (repeat_min < 2) possessive_quantifier = FALSE;
+ }
+
+ /* Non-possessive quantifier */
+
+ else *ketcode = OP_KETRMAX + repeat_type;
+ }
+ }
+ }
+
+ /* If previous is OP_FAIL, it was generated by an empty class [] in
+ JavaScript mode. The other ways in which OP_FAIL can be generated, that is
+ by (*FAIL) or (?!) set previous to NULL, which gives a "nothing to repeat"
+ error above. We can just ignore the repeat in JS case. */
+
+ else if (*previous == OP_FAIL) goto END_REPEAT;
+
+ /* Else there's some kind of shambles */
+
+ else
+ {
+ *errorcodeptr = ERR11;
+ goto FAILED;
+ }
+
+ /* If the character following a repeat is '+', possessive_quantifier is
+ TRUE. For some opcodes, there are special alternative opcodes for this
+ case. For anything else, we wrap the entire repeated item inside OP_ONCE
+ brackets. Logically, the '+' notation is just syntactic sugar, taken from
+ Sun's Java package, but the special opcodes can optimize it.
+
+ Some (but not all) possessively repeated subpatterns have already been
+ completely handled in the code just above. For them, possessive_quantifier
+ is always FALSE at this stage. Note that the repeated item starts at
+ tempcode, not at previous, which might be the first part of a string whose
+ (former) last char we repeated. */
+
+ if (possessive_quantifier)
+ {
+ int len;
+
+ /* Possessifying an EXACT quantifier has no effect, so we can ignore it.
+ However, QUERY, STAR, or UPTO may follow (for quantifiers such as {5,6},
+ {5,}, or {5,10}). We skip over an EXACT item; if the length of what
+ remains is greater than zero, there's a further opcode that can be
+ handled. If not, do nothing, leaving the EXACT alone. */
+
+ switch(*tempcode)
+ {
+ case OP_TYPEEXACT:
+ tempcode += PRIV(OP_lengths)[*tempcode] +
+ ((tempcode[1 + IMM2_SIZE] == OP_PROP
+ || tempcode[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0);
+ break;
+
+ /* CHAR opcodes are used for exacts whose count is 1. */
+
+ case OP_CHAR:
+ case OP_CHARI:
+ case OP_NOT:
+ case OP_NOTI:
+ case OP_EXACT:
+ case OP_EXACTI:
+ case OP_NOTEXACT:
+ case OP_NOTEXACTI:
+ tempcode += PRIV(OP_lengths)[*tempcode];
+#ifdef SUPPORT_UTF
+ if (utf && HAS_EXTRALEN(tempcode[-1]))
+ tempcode += GET_EXTRALEN(tempcode[-1]);
+#endif
+ break;
+
+ /* For the class opcodes, the repeat operator appears at the end;
+ adjust tempcode to point to it. */
+
+ case OP_CLASS:
+ case OP_NCLASS:
+ tempcode += 1 + 32/sizeof(pcre_uchar);
+ break;
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+ tempcode += GET(tempcode, 1);
+ break;
+#endif
+ }
+
+ /* If tempcode is equal to code (which points to the end of the repeated
+ item), it means we have skipped an EXACT item but there is no following
+ QUERY, STAR, or UPTO; the value of len will be 0, and we do nothing. In
+ all other cases, tempcode will be pointing to the repeat opcode, and will
+ be less than code, so the value of len will be greater than 0. */
+
+ len = (int)(code - tempcode);
+ if (len > 0)
+ {
+ unsigned int repcode = *tempcode;
+
+ /* There is a table for possessifying opcodes, all of which are less
+ than OP_CALLOUT. A zero entry means there is no possessified version.
+ */
+
+ if (repcode < OP_CALLOUT && opcode_possessify[repcode] > 0)
+ *tempcode = opcode_possessify[repcode];
+
+ /* For opcode without a special possessified version, wrap the item in
+ ONCE brackets. Because we are moving code along, we must ensure that any
+ pending recursive references are updated. */
+
+ else
+ {
+ *code = OP_END;
+ adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm);
+ memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len));
+ code += 1 + LINK_SIZE;
+ len += 1 + LINK_SIZE;
+ tempcode[0] = OP_ONCE;
+ *code++ = OP_KET;
+ PUTINC(code, 0, len);
+ PUT(tempcode, 1, len);
+ }
+ }
+
+#ifdef NEVER
+ if (len > 0) switch (*tempcode)
+ {
+ case OP_STAR: *tempcode = OP_POSSTAR; break;
+ case OP_PLUS: *tempcode = OP_POSPLUS; break;
+ case OP_QUERY: *tempcode = OP_POSQUERY; break;
+ case OP_UPTO: *tempcode = OP_POSUPTO; break;
+
+ case OP_STARI: *tempcode = OP_POSSTARI; break;
+ case OP_PLUSI: *tempcode = OP_POSPLUSI; break;
+ case OP_QUERYI: *tempcode = OP_POSQUERYI; break;
+ case OP_UPTOI: *tempcode = OP_POSUPTOI; break;
+
+ case OP_NOTSTAR: *tempcode = OP_NOTPOSSTAR; break;
+ case OP_NOTPLUS: *tempcode = OP_NOTPOSPLUS; break;
+ case OP_NOTQUERY: *tempcode = OP_NOTPOSQUERY; break;
+ case OP_NOTUPTO: *tempcode = OP_NOTPOSUPTO; break;
+
+ case OP_NOTSTARI: *tempcode = OP_NOTPOSSTARI; break;
+ case OP_NOTPLUSI: *tempcode = OP_NOTPOSPLUSI; break;
+ case OP_NOTQUERYI: *tempcode = OP_NOTPOSQUERYI; break;
+ case OP_NOTUPTOI: *tempcode = OP_NOTPOSUPTOI; break;
+
+ case OP_TYPESTAR: *tempcode = OP_TYPEPOSSTAR; break;
+ case OP_TYPEPLUS: *tempcode = OP_TYPEPOSPLUS; break;
+ case OP_TYPEQUERY: *tempcode = OP_TYPEPOSQUERY; break;
+ case OP_TYPEUPTO: *tempcode = OP_TYPEPOSUPTO; break;
+
+ case OP_CRSTAR: *tempcode = OP_CRPOSSTAR; break;
+ case OP_CRPLUS: *tempcode = OP_CRPOSPLUS; break;
+ case OP_CRQUERY: *tempcode = OP_CRPOSQUERY; break;
+ case OP_CRRANGE: *tempcode = OP_CRPOSRANGE; break;
+
+ /* Because we are moving code along, we must ensure that any
+ pending recursive references are updated. */
+
+ default:
+ *code = OP_END;
+ adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm);
+ memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len));
+ code += 1 + LINK_SIZE;
+ len += 1 + LINK_SIZE;
+ tempcode[0] = OP_ONCE;
+ *code++ = OP_KET;
+ PUTINC(code, 0, len);
+ PUT(tempcode, 1, len);
+ break;
+ }
+#endif
+ }
+
+ /* In all case we no longer have a previous item. We also set the
+ "follows varying string" flag for subsequently encountered reqchars if
+ it isn't already set and we have just passed a varying length item. */
+
+ END_REPEAT:
+ previous = NULL;
+ cd->req_varyopt |= reqvary;
+ break;
+
+
+ /* ===================================================================*/
+ /* Start of nested parenthesized sub-expression, or comment or lookahead or
+ lookbehind or option setting or condition or all the other extended
+ parenthesis forms. */
+
+ case CHAR_LEFT_PARENTHESIS:
+ newoptions = options;
+ skipbytes = 0;
+ bravalue = OP_CBRA;
+ save_hwm = cd->hwm;
+ reset_bracount = FALSE;
+
+ /* First deal with various "verbs" that can be introduced by '*'. */
+
+ ptr++;
+ if (ptr[0] == CHAR_ASTERISK && (ptr[1] == ':'
+ || (MAX_255(ptr[1]) && ((cd->ctypes[ptr[1]] & ctype_letter) != 0))))
+ {
+ int i, namelen;
+ int arglen = 0;
+ const char *vn = verbnames;
+ const pcre_uchar *name = ptr + 1;
+ const pcre_uchar *arg = NULL;
+ previous = NULL;
+ ptr++;
+ while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_letter) != 0) ptr++;
+ namelen = (int)(ptr - name);
+
+ /* It appears that Perl allows any characters whatsoever, other than
+ a closing parenthesis, to appear in arguments, so we no longer insist on
+ letters, digits, and underscores. */
+
+ if (*ptr == CHAR_COLON)
+ {
+ arg = ++ptr;
+ while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
+ arglen = (int)(ptr - arg);
+ if ((unsigned int)arglen > MAX_MARK)
+ {
+ *errorcodeptr = ERR75;
+ goto FAILED;
+ }
+ }
+
+ if (*ptr != CHAR_RIGHT_PARENTHESIS)
+ {
+ *errorcodeptr = ERR60;
+ goto FAILED;
+ }
+
+ /* Scan the table of verb names */
+
+ for (i = 0; i < verbcount; i++)
+ {
+ if (namelen == verbs[i].len &&
+ STRNCMP_UC_C8(name, vn, namelen) == 0)
+ {
+ int setverb;
+
+ /* Check for open captures before ACCEPT and convert it to
+ ASSERT_ACCEPT if in an assertion. */
+
+ if (verbs[i].op == OP_ACCEPT)
+ {
+ open_capitem *oc;
+ if (arglen != 0)
+ {
+ *errorcodeptr = ERR59;
+ goto FAILED;
+ }
+ cd->had_accept = TRUE;
+ for (oc = cd->open_caps; oc != NULL; oc = oc->next)
+ {
+ *code++ = OP_CLOSE;
+ PUT2INC(code, 0, oc->number);
+ }
+ setverb = *code++ =
+ (cd->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT;
+
+ /* Do not set firstchar after *ACCEPT */
+ if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
+ }
+
+ /* Handle other cases with/without an argument */
+
+ else if (arglen == 0)
+ {
+ if (verbs[i].op < 0) /* Argument is mandatory */
+ {
+ *errorcodeptr = ERR66;
+ goto FAILED;
+ }
+ setverb = *code++ = verbs[i].op;
+ }
+
+ else
+ {
+ if (verbs[i].op_arg < 0) /* Argument is forbidden */
+ {
+ *errorcodeptr = ERR59;
+ goto FAILED;
+ }
+ setverb = *code++ = verbs[i].op_arg;
+ *code++ = arglen;
+ memcpy(code, arg, IN_UCHARS(arglen));
+ code += arglen;
+ *code++ = 0;
+ }
+
+ switch (setverb)
+ {
+ case OP_THEN:
+ case OP_THEN_ARG:
+ cd->external_flags |= PCRE_HASTHEN;
+ break;
+
+ case OP_PRUNE:
+ case OP_PRUNE_ARG:
+ case OP_SKIP:
+ case OP_SKIP_ARG:
+ cd->had_pruneorskip = TRUE;
+ break;
+ }
+
+ break; /* Found verb, exit loop */
+ }
+
+ vn += verbs[i].len + 1;
+ }
+
+ if (i < verbcount) continue; /* Successfully handled a verb */
+ *errorcodeptr = ERR60; /* Verb not recognized */
+ goto FAILED;
+ }
+
+ /* Deal with the extended parentheses; all are introduced by '?', and the
+ appearance of any of them means that this is not a capturing group. */
+
+ else if (*ptr == CHAR_QUESTION_MARK)
+ {
+ int i, set, unset, namelen;
+ int *optset;
+ const pcre_uchar *name;
+ pcre_uchar *slot;
+
+ switch (*(++ptr))
+ {
+ case CHAR_NUMBER_SIGN: /* Comment; skip to ket */
+ ptr++;
+ while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
+ if (*ptr == CHAR_NULL)
+ {
+ *errorcodeptr = ERR18;
+ goto FAILED;
+ }
+ continue;
+
+
+ /* ------------------------------------------------------------ */
+ case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */
+ reset_bracount = TRUE;
+ /* Fall through */
+
+ /* ------------------------------------------------------------ */
+ case CHAR_COLON: /* Non-capturing bracket */
+ bravalue = OP_BRA;
+ ptr++;
+ break;
+
+
+ /* ------------------------------------------------------------ */
+ case CHAR_LEFT_PARENTHESIS:
+ bravalue = OP_COND; /* Conditional group */
+ tempptr = ptr;
+
+ /* A condition can be an assertion, a number (referring to a numbered
+ group's having been set), a name (referring to a named group), or 'R',
+ referring to recursion. R<digits> and R&name are also permitted for
+ recursion tests.
+
+ There are ways of testing a named group: (?(name)) is used by Python;
+ Perl 5.10 onwards uses (?(<name>) or (?('name')).
+
+ There is one unfortunate ambiguity, caused by history. 'R' can be the
+ recursive thing or the name 'R' (and similarly for 'R' followed by
+ digits). We look for a name first; if not found, we try the other case.
+
+ For compatibility with auto-callouts, we allow a callout to be
+ specified before a condition that is an assertion. First, check for the
+ syntax of a callout; if found, adjust the temporary pointer that is
+ used to check for an assertion condition. That's all that is needed! */
+
+ if (ptr[1] == CHAR_QUESTION_MARK && ptr[2] == CHAR_C)
+ {
+ for (i = 3;; i++) if (!IS_DIGIT(ptr[i])) break;
+ if (ptr[i] == CHAR_RIGHT_PARENTHESIS)
+ tempptr += i + 1;
+ }
+
+ /* For conditions that are assertions, check the syntax, and then exit
+ the switch. This will take control down to where bracketed groups,
+ including assertions, are processed. */
+
+ if (tempptr[1] == CHAR_QUESTION_MARK &&
+ (tempptr[2] == CHAR_EQUALS_SIGN ||
+ tempptr[2] == CHAR_EXCLAMATION_MARK ||
+ tempptr[2] == CHAR_LESS_THAN_SIGN))
+ break;
+
+ /* Other conditions use OP_CREF/OP_DNCREF/OP_RREF/OP_DNRREF, and all
+ need to skip at least 1+IMM2_SIZE bytes at the start of the group. */
+
+ code[1+LINK_SIZE] = OP_CREF;
+ skipbytes = 1+IMM2_SIZE;
+ refsign = -1; /* => not a number */
+ namelen = -1; /* => not a name; must set to avoid warning */
+ name = NULL; /* Always set to avoid warning */
+ recno = 0; /* Always set to avoid warning */
+
+ /* Check for a test for recursion in a named group. */
+
+ ptr++;
+ if (*ptr == CHAR_R && ptr[1] == CHAR_AMPERSAND)
+ {
+ terminator = -1;
+ ptr += 2;
+ code[1+LINK_SIZE] = OP_RREF; /* Change the type of test */
+ }
+
+ /* Check for a test for a named group's having been set, using the Perl
+ syntax (?(<name>) or (?('name'), and also allow for the original PCRE
+ syntax of (?(name) or for (?(+n), (?(-n), and just (?(n). */
+
+ else if (*ptr == CHAR_LESS_THAN_SIGN)
+ {
+ terminator = CHAR_GREATER_THAN_SIGN;
+ ptr++;
+ }
+ else if (*ptr == CHAR_APOSTROPHE)
+ {
+ terminator = CHAR_APOSTROPHE;
+ ptr++;
+ }
+ else
+ {
+ terminator = CHAR_NULL;
+ if (*ptr == CHAR_MINUS || *ptr == CHAR_PLUS) refsign = *ptr++;
+ else if (IS_DIGIT(*ptr)) refsign = 0;
+ }
+
+ /* Handle a number */
+
+ if (refsign >= 0)
+ {
+ while (IS_DIGIT(*ptr))
+ {
+ recno = recno * 10 + (int)(*ptr - CHAR_0);
+ ptr++;
+ }
+ }
+
+ /* Otherwise we expect to read a name; anything else is an error. When
+ a name is one of a number of duplicates, a different opcode is used and
+ it needs more memory. Unfortunately we cannot tell whether a name is a
+ duplicate in the first pass, so we have to allow for more memory. */
+
+ else
+ {
+ if (IS_DIGIT(*ptr))
+ {
+ *errorcodeptr = ERR84;
+ goto FAILED;
+ }
+ if (!MAX_255(*ptr) || (cd->ctypes[*ptr] & ctype_word) == 0)
+ {
+ *errorcodeptr = ERR28; /* Assertion expected */
+ goto FAILED;
+ }
+ name = ptr++;
+ while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0)
+ {
+ ptr++;
+ }
+ namelen = (int)(ptr - name);
+ if (lengthptr != NULL) *lengthptr += IMM2_SIZE;
+ }
+
+ /* Check the terminator */
+
+ if ((terminator > 0 && *ptr++ != (pcre_uchar)terminator) ||
+ *ptr++ != CHAR_RIGHT_PARENTHESIS)
+ {
+ ptr--; /* Error offset */
+ *errorcodeptr = ERR26; /* Malformed number or name */
+ goto FAILED;
+ }
+
+ /* Do no further checking in the pre-compile phase. */
+
+ if (lengthptr != NULL) break;
+
+ /* In the real compile we do the work of looking for the actual
+ reference. If refsign is not negative, it means we have a number in
+ recno. */
+
+ if (refsign >= 0)
+ {
+ if (recno <= 0)
+ {
+ *errorcodeptr = ERR35;
+ goto FAILED;
+ }
+ if (refsign != 0) recno = (refsign == CHAR_MINUS)?
+ cd->bracount - recno + 1 : recno + cd->bracount;
+ if (recno <= 0 || recno > cd->final_bracount)
+ {
+ *errorcodeptr = ERR15;
+ goto FAILED;
+ }
+ PUT2(code, 2+LINK_SIZE, recno);
+ break;
+ }
+
+ /* Otherwise look for the name. */
+
+ slot = cd->name_table;
+ for (i = 0; i < cd->names_found; i++)
+ {
+ if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) == 0) break;
+ slot += cd->name_entry_size;
+ }
+
+ /* Found the named subpattern. If the name is duplicated, add one to
+ the opcode to change CREF/RREF into DNCREF/DNRREF and insert
+ appropriate data values. Otherwise, just insert the unique subpattern
+ number. */
+
+ if (i < cd->names_found)
+ {
+ int offset = i++;
+ int count = 1;
+ recno = GET2(slot, 0); /* Number from first found */
+ for (; i < cd->names_found; i++)
+ {
+ slot += cd->name_entry_size;
+ if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) != 0) break;
+ count++;
+ }
+ if (count > 1)
+ {
+ PUT2(code, 2+LINK_SIZE, offset);
+ PUT2(code, 2+LINK_SIZE+IMM2_SIZE, count);
+ skipbytes += IMM2_SIZE;
+ code[1+LINK_SIZE]++;
+ }
+ else /* Not a duplicated name */
+ {
+ PUT2(code, 2+LINK_SIZE, recno);
+ }
+ }
+
+ /* If terminator == CHAR_NULL it means that the name followed directly
+ after the opening parenthesis [e.g. (?(abc)...] and in this case there
+ are some further alternatives to try. For the cases where terminator !=
+ CHAR_NULL [things like (?(<name>... or (?('name')... or (?(R&name)... ]
+ we have now checked all the possibilities, so give an error. */
+
+ else if (terminator != CHAR_NULL)
+ {
+ *errorcodeptr = ERR15;
+ goto FAILED;
+ }
+
+ /* Check for (?(R) for recursion. Allow digits after R to specify a
+ specific group number. */
+
+ else if (*name == CHAR_R)
+ {
+ recno = 0;
+ for (i = 1; i < namelen; i++)
+ {
+ if (!IS_DIGIT(name[i]))
+ {
+ *errorcodeptr = ERR15;
+ goto FAILED;
+ }
+ recno = recno * 10 + name[i] - CHAR_0;
+ }
+ if (recno == 0) recno = RREF_ANY;
+ code[1+LINK_SIZE] = OP_RREF; /* Change test type */
+ PUT2(code, 2+LINK_SIZE, recno);
+ }
+
+ /* Similarly, check for the (?(DEFINE) "condition", which is always
+ false. */
+
+ else if (namelen == 6 && STRNCMP_UC_C8(name, STRING_DEFINE, 6) == 0)
+ {
+ code[1+LINK_SIZE] = OP_DEF;
+ skipbytes = 1;
+ }
+
+ /* Reference to an unidentified subpattern. */
+
+ else
+ {
+ *errorcodeptr = ERR15;
+ goto FAILED;
+ }
+ break;
+
+
+ /* ------------------------------------------------------------ */
+ case CHAR_EQUALS_SIGN: /* Positive lookahead */
+ bravalue = OP_ASSERT;
+ cd->assert_depth += 1;
+ ptr++;
+ break;
+
+ /* 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
+ this feature. Not that that applies to a quantified (?!) but we allow
+ it for uniformity. */
+
+ /* ------------------------------------------------------------ */
+ case CHAR_EXCLAMATION_MARK: /* Negative lookahead */
+ ptr++;
+ if (*ptr == CHAR_RIGHT_PARENTHESIS && ptr[1] != CHAR_ASTERISK &&
+ ptr[1] != CHAR_PLUS && ptr[1] != CHAR_QUESTION_MARK &&
+ (ptr[1] != CHAR_LEFT_CURLY_BRACKET || !is_counted_repeat(ptr+2)))
+ {
+ *code++ = OP_FAIL;
+ previous = NULL;
+ continue;
+ }
+ bravalue = OP_ASSERT_NOT;
+ cd->assert_depth += 1;
+ break;
+
+
+ /* ------------------------------------------------------------ */
+ case CHAR_LESS_THAN_SIGN: /* Lookbehind or named define */
+ switch (ptr[1])
+ {
+ case CHAR_EQUALS_SIGN: /* Positive lookbehind */
+ bravalue = OP_ASSERTBACK;
+ cd->assert_depth += 1;
+ ptr += 2;
+ break;
+
+ case CHAR_EXCLAMATION_MARK: /* Negative lookbehind */
+ bravalue = OP_ASSERTBACK_NOT;
+ cd->assert_depth += 1;
+ ptr += 2;
+ break;
+
+ default: /* Could be name define, else bad */
+ if (MAX_255(ptr[1]) && (cd->ctypes[ptr[1]] & ctype_word) != 0)
+ goto DEFINE_NAME;
+ ptr++; /* Correct offset for error */
+ *errorcodeptr = ERR24;
+ goto FAILED;
+ }
+ break;
+
+
+ /* ------------------------------------------------------------ */
+ case CHAR_GREATER_THAN_SIGN: /* One-time brackets */
+ bravalue = OP_ONCE;
+ ptr++;
+ break;
+
+
+ /* ------------------------------------------------------------ */
+ case CHAR_C: /* Callout - may be followed by digits; */
+ previous_callout = code; /* Save for later completion */
+ after_manual_callout = 1; /* Skip one item before completing */
+ *code++ = OP_CALLOUT;
+ {
+ int n = 0;
+ ptr++;
+ while(IS_DIGIT(*ptr))
+ n = n * 10 + *ptr++ - CHAR_0;
+ if (*ptr != CHAR_RIGHT_PARENTHESIS)
+ {
+ *errorcodeptr = ERR39;
+ goto FAILED;
+ }
+ if (n > 255)
+ {
+ *errorcodeptr = ERR38;
+ goto FAILED;
+ }
+ *code++ = n;
+ PUT(code, 0, (int)(ptr - cd->start_pattern + 1)); /* Pattern offset */
+ PUT(code, LINK_SIZE, 0); /* Default length */
+ code += 2 * LINK_SIZE;
+ }
+ previous = NULL;
+ continue;
+
+
+ /* ------------------------------------------------------------ */
+ case CHAR_P: /* Python-style named subpattern handling */
+ if (*(++ptr) == CHAR_EQUALS_SIGN ||
+ *ptr == CHAR_GREATER_THAN_SIGN) /* Reference or recursion */
+ {
+ is_recurse = *ptr == CHAR_GREATER_THAN_SIGN;
+ terminator = CHAR_RIGHT_PARENTHESIS;
+ goto NAMED_REF_OR_RECURSE;
+ }
+ else if (*ptr != CHAR_LESS_THAN_SIGN) /* Test for Python-style defn */
+ {
+ *errorcodeptr = ERR41;
+ goto FAILED;
+ }
+ /* Fall through to handle (?P< as (?< is handled */
+
+
+ /* ------------------------------------------------------------ */
+ DEFINE_NAME: /* Come here from (?< handling */
+ case CHAR_APOSTROPHE:
+ terminator = (*ptr == CHAR_LESS_THAN_SIGN)?
+ CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE;
+ name = ++ptr;
+ if (IS_DIGIT(*ptr))
+ {
+ *errorcodeptr = ERR84; /* Group name must start with non-digit */
+ goto FAILED;
+ }
+ while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) ptr++;
+ namelen = (int)(ptr - name);
+
+ /* In the pre-compile phase, do a syntax check, remember the longest
+ name, and then remember the group in a vector, expanding it if
+ necessary. Duplicates for the same number are skipped; other duplicates
+ are checked for validity. In the actual compile, there is nothing to
+ do. */
+
+ if (lengthptr != NULL)
+ {
+ named_group *ng;
+ pcre_uint32 number = cd->bracount + 1;
+
+ if (*ptr != (pcre_uchar)terminator)
+ {
+ *errorcodeptr = ERR42;
+ goto FAILED;
+ }
+
+ if (cd->names_found >= MAX_NAME_COUNT)
+ {
+ *errorcodeptr = ERR49;
+ goto FAILED;
+ }
+
+ if (namelen + IMM2_SIZE + 1 > cd->name_entry_size)
+ {
+ cd->name_entry_size = namelen + IMM2_SIZE + 1;
+ if (namelen > MAX_NAME_SIZE)
+ {
+ *errorcodeptr = ERR48;
+ goto FAILED;
+ }
+ }
+
+ /* Scan the list to check for duplicates. For duplicate names, if the
+ number is the same, break the loop, which causes the name to be
+ discarded; otherwise, if DUPNAMES is not set, give an error.
+ If it is set, allow the name with a different number, but continue
+ scanning in case this is a duplicate with the same number. For
+ non-duplicate names, give an error if the number is duplicated. */
+
+ ng = cd->named_groups;
+ for (i = 0; i < cd->names_found; i++, ng++)
+ {
+ if (namelen == ng->length &&
+ STRNCMP_UC_UC(name, ng->name, namelen) == 0)
+ {
+ if (ng->number == number) break;
+ if ((options & PCRE_DUPNAMES) == 0)
+ {
+ *errorcodeptr = ERR43;
+ goto FAILED;
+ }
+ cd->dupnames = TRUE; /* Duplicate names exist */
+ }
+ else if (ng->number == number)
+ {
+ *errorcodeptr = ERR65;
+ goto FAILED;
+ }
+ }
+
+ if (i >= cd->names_found) /* Not a duplicate with same number */
+ {
+ /* Increase the list size if necessary */
+
+ if (cd->names_found >= cd->named_group_list_size)
+ {
+ int newsize = cd->named_group_list_size * 2;
+ named_group *newspace = (PUBL(malloc))
+ (newsize * sizeof(named_group));
+
+ if (newspace == NULL)
+ {
+ *errorcodeptr = ERR21;
+ goto FAILED;
+ }
+
+ memcpy(newspace, cd->named_groups,
+ cd->named_group_list_size * sizeof(named_group));
+ if (cd->named_group_list_size > NAMED_GROUP_LIST_SIZE)
+ (PUBL(free))((void *)cd->named_groups);
+ cd->named_groups = newspace;
+ cd->named_group_list_size = newsize;
+ }
+
+ cd->named_groups[cd->names_found].name = name;
+ cd->named_groups[cd->names_found].length = namelen;
+ cd->named_groups[cd->names_found].number = number;
+ cd->names_found++;
+ }
+ }
+
+ ptr++; /* Move past > or ' in both passes. */
+ goto NUMBERED_GROUP;
+
+
+ /* ------------------------------------------------------------ */
+ case CHAR_AMPERSAND: /* Perl recursion/subroutine syntax */
+ terminator = CHAR_RIGHT_PARENTHESIS;
+ is_recurse = TRUE;
+ /* Fall through */
+
+ /* We come here from the Python syntax above that handles both
+ references (?P=name) and recursion (?P>name), as well as falling
+ through from the Perl recursion syntax (?&name). We also come here from
+ the Perl \k<name> or \k'name' back reference syntax and the \k{name}
+ .NET syntax, and the Oniguruma \g<...> and \g'...' subroutine syntax. */
+
+ NAMED_REF_OR_RECURSE:
+ name = ++ptr;
+ if (IS_DIGIT(*ptr))
+ {
+ *errorcodeptr = ERR84; /* Group name must start with non-digit */
+ goto FAILED;
+ }
+ while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) ptr++;
+ namelen = (int)(ptr - name);
+
+ /* In the pre-compile phase, do a syntax check. We used to just set
+ a dummy reference number, because it was not used in the first pass.
+ However, with the change of recursive back references to be atomic,
+ we have to look for the number so that this state can be identified, as
+ otherwise the incorrect length is computed. If it's not a backwards
+ reference, the dummy number will do. */
+
+ if (lengthptr != NULL)
+ {
+ named_group *ng;
+
+ if (namelen == 0)
+ {
+ *errorcodeptr = ERR62;
+ goto FAILED;
+ }
+ if (*ptr != (pcre_uchar)terminator)
+ {
+ *errorcodeptr = ERR42;
+ goto FAILED;
+ }
+ if (namelen > MAX_NAME_SIZE)
+ {
+ *errorcodeptr = ERR48;
+ goto FAILED;
+ }
+
+ /* The name table does not exist in the first pass; instead we must
+ scan the list of names encountered so far in order to get the
+ number. If the name is not found, set the value to 0 for a forward
+ reference. */
+
+ ng = cd->named_groups;
+ for (i = 0; i < cd->names_found; i++, ng++)
+ {
+ if (namelen == ng->length &&
+ STRNCMP_UC_UC(name, ng->name, namelen) == 0)
+ break;
+ }
+ recno = (i < cd->names_found)? ng->number : 0;
+
+ /* Count named back references. */
+
+ if (!is_recurse) cd->namedrefcount++;
+ }
+
+ /* In the real compile, search the name table. We check the name
+ first, and then check that we have reached the end of the name in the
+ table. That way, if the name is longer than any in the table, the
+ comparison will fail without reading beyond the table entry. */
+
+ else
+ {
+ slot = cd->name_table;
+ for (i = 0; i < cd->names_found; i++)
+ {
+ if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) == 0 &&
+ slot[IMM2_SIZE+namelen] == 0)
+ break;
+ slot += cd->name_entry_size;
+ }
+
+ if (i < cd->names_found)
+ {
+ recno = GET2(slot, 0);
+ }
+ else
+ {
+ *errorcodeptr = ERR15;
+ goto FAILED;
+ }
+ }
+
+ /* In both phases, for recursions, we can now go to the code than
+ handles numerical recursion. */
+
+ if (is_recurse) goto HANDLE_RECURSION;
+
+ /* In the second pass we must see if the name is duplicated. If so, we
+ generate a different opcode. */
+
+ if (lengthptr == NULL && cd->dupnames)
+ {
+ int count = 1;
+ unsigned int index = i;
+ pcre_uchar *cslot = slot + cd->name_entry_size;
+
+ for (i++; i < cd->names_found; i++)
+ {
+ if (STRCMP_UC_UC(slot + IMM2_SIZE, cslot + IMM2_SIZE) != 0) break;
+ count++;
+ cslot += cd->name_entry_size;
+ }
+
+ if (count > 1)
+ {
+ if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
+ previous = code;
+ *code++ = ((options & PCRE_CASELESS) != 0)? OP_DNREFI : OP_DNREF;
+ PUT2INC(code, 0, index);
+ PUT2INC(code, 0, count);
+
+ /* Process each potentially referenced group. */
+
+ for (; slot < cslot; slot += cd->name_entry_size)
+ {
+ open_capitem *oc;
+ recno = GET2(slot, 0);
+ cd->backref_map |= (recno < 32)? (1 << recno) : 1;
+ if (recno > cd->top_backref) cd->top_backref = recno;
+
+ /* Check to see if this back reference is recursive, that it, it
+ is inside the group that it references. A flag is set so that the
+ group can be made atomic. */
+
+ for (oc = cd->open_caps; oc != NULL; oc = oc->next)
+ {
+ if (oc->number == recno)
+ {
+ oc->flag = TRUE;
+ break;
+ }
+ }
+ }
+
+ continue; /* End of back ref handling */
+ }
+ }
+
+ /* First pass, or a non-duplicated name. */
+
+ goto HANDLE_REFERENCE;
+
+
+ /* ------------------------------------------------------------ */
+ case CHAR_R: /* Recursion */
+ ptr++; /* Same as (?0) */
+ /* Fall through */
+
+
+ /* ------------------------------------------------------------ */
+ case CHAR_MINUS: case CHAR_PLUS: /* Recursion or subroutine */
+ case CHAR_0: case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4:
+ case CHAR_5: case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9:
+ {
+ const pcre_uchar *called;
+ terminator = CHAR_RIGHT_PARENTHESIS;
+
+ /* Come here from the \g<...> and \g'...' code (Oniguruma
+ compatibility). However, the syntax has been checked to ensure that
+ the ... are a (signed) number, so that neither ERR63 nor ERR29 will
+ be called on this path, nor with the jump to OTHER_CHAR_AFTER_QUERY
+ ever be taken. */
+
+ HANDLE_NUMERICAL_RECURSION:
+
+ if ((refsign = *ptr) == CHAR_PLUS)
+ {
+ ptr++;
+ if (!IS_DIGIT(*ptr))
+ {
+ *errorcodeptr = ERR63;
+ goto FAILED;
+ }
+ }
+ else if (refsign == CHAR_MINUS)
+ {
+ if (!IS_DIGIT(ptr[1]))
+ goto OTHER_CHAR_AFTER_QUERY;
+ ptr++;
+ }
+
+ recno = 0;
+ while(IS_DIGIT(*ptr))
+ recno = recno * 10 + *ptr++ - CHAR_0;
+
+ if (*ptr != (pcre_uchar)terminator)
+ {
+ *errorcodeptr = ERR29;
+ goto FAILED;
+ }
+
+ if (refsign == CHAR_MINUS)
+ {
+ if (recno == 0)
+ {
+ *errorcodeptr = ERR58;
+ goto FAILED;
+ }
+ recno = cd->bracount - recno + 1;
+ if (recno <= 0)
+ {
+ *errorcodeptr = ERR15;
+ goto FAILED;
+ }
+ }
+ else if (refsign == CHAR_PLUS)
+ {
+ if (recno == 0)
+ {
+ *errorcodeptr = ERR58;
+ goto FAILED;
+ }
+ recno += cd->bracount;
+ }
+
+ /* Come here from code above that handles a named recursion */
+
+ HANDLE_RECURSION:
+
+ previous = code;
+ called = cd->start_code;
+
+ /* When we are actually compiling, find the bracket that is being
+ referenced. Temporarily end the regex in case it doesn't exist before
+ this point. If we end up with a forward reference, first check that
+ the bracket does occur later so we can give the error (and position)
+ now. Then remember this forward reference in the workspace so it can
+ be filled in at the end. */
+
+ if (lengthptr == NULL)
+ {
+ *code = OP_END;
+ if (recno != 0)
+ called = PRIV(find_bracket)(cd->start_code, utf, recno);
+
+ /* Forward reference */
+
+ if (called == NULL)
+ {
+ if (recno > cd->final_bracount)
+ {
+ *errorcodeptr = ERR15;
+ goto FAILED;
+ }
+
+ /* Fudge the value of "called" so that when it is inserted as an
+ offset below, what it actually inserted is the reference number
+ of the group. Then remember the forward reference. */
+
+ called = cd->start_code + recno;
+ if (cd->hwm >= cd->start_workspace + cd->workspace_size -
+ WORK_SIZE_SAFETY_MARGIN)
+ {
+ *errorcodeptr = expand_workspace(cd);
+ if (*errorcodeptr != 0) goto FAILED;
+ }
+ PUTINC(cd->hwm, 0, (int)(code + 1 - cd->start_code));
+ }
+
+ /* If not a forward reference, and the subpattern is still open,
+ this is a recursive call. We check to see if this is a left
+ recursion that could loop for ever, and diagnose that case. We
+ must not, however, do this check if we are in a conditional
+ subpattern because the condition might be testing for recursion in
+ a pattern such as /(?(R)a+|(?R)b)/, which is perfectly valid.
+ Forever loops are also detected at runtime, so those that occur in
+ conditional subpatterns will be picked up then. */
+
+ else if (GET(called, 1) == 0 && cond_depth <= 0 &&
+ could_be_empty(called, code, bcptr, utf, cd))
+ {
+ *errorcodeptr = ERR40;
+ goto FAILED;
+ }
+ }
+
+ /* Insert the recursion/subroutine item. It does not have a set first
+ character (relevant if it is repeated, because it will then be
+ wrapped with ONCE brackets). */
+
+ *code = OP_RECURSE;
+ PUT(code, 1, (int)(called - cd->start_code));
+ code += 1 + LINK_SIZE;
+ groupsetfirstchar = FALSE;
+ }
+
+ /* Can't determine a first byte now */
+
+ if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
+ continue;
+
+
+ /* ------------------------------------------------------------ */
+ default: /* Other characters: check option setting */
+ OTHER_CHAR_AFTER_QUERY:
+ set = unset = 0;
+ optset = &set;
+
+ while (*ptr != CHAR_RIGHT_PARENTHESIS && *ptr != CHAR_COLON)
+ {
+ switch (*ptr++)
+ {
+ case CHAR_MINUS: optset = &unset; break;
+
+ case CHAR_J: /* Record that it changed in the external options */
+ *optset |= PCRE_DUPNAMES;
+ cd->external_flags |= PCRE_JCHANGED;
+ break;
+
+ case CHAR_i: *optset |= PCRE_CASELESS; break;
+ case CHAR_m: *optset |= PCRE_MULTILINE; break;
+ case CHAR_s: *optset |= PCRE_DOTALL; break;
+ case CHAR_x: *optset |= PCRE_EXTENDED; break;
+ case CHAR_U: *optset |= PCRE_UNGREEDY; break;
+ case CHAR_X: *optset |= PCRE_EXTRA; break;
+
+ default: *errorcodeptr = ERR12;
+ ptr--; /* Correct the offset */
+ goto FAILED;
+ }
+ }
+
+ /* Set up the changed option bits, but don't change anything yet. */
+
+ newoptions = (options | set) & (~unset);
+
+ /* If the options ended with ')' this is not the start of a nested
+ group with option changes, so the options change at this level. If this
+ item is right at the start of the pattern, the options can be
+ abstracted and made external in the pre-compile phase, and ignored in
+ the compile phase. This can be helpful when matching -- for instance in
+ caseless checking of required bytes.
+
+ If the code pointer is not (cd->start_code + 1 + LINK_SIZE), we are
+ definitely *not* at the start of the pattern because something has been
+ compiled. In the pre-compile phase, however, the code pointer can have
+ that value after the start, because it gets reset as code is discarded
+ during the pre-compile. However, this can happen only at top level - if
+ we are within parentheses, the starting BRA will still be present. At
+ any parenthesis level, the length value can be used to test if anything
+ has been compiled at that level. Thus, a test for both these conditions
+ is necessary to ensure we correctly detect the start of the pattern in
+ both phases.
+
+ If we are not at the pattern start, reset the greedy defaults and the
+ case value for firstchar and reqchar. */
+
+ if (*ptr == CHAR_RIGHT_PARENTHESIS)
+ {
+ if (code == cd->start_code + 1 + LINK_SIZE &&
+ (lengthptr == NULL || *lengthptr == 2 + 2*LINK_SIZE))
+ {
+ cd->external_options = newoptions;
+ }
+ else
+ {
+ greedy_default = ((newoptions & PCRE_UNGREEDY) != 0);
+ greedy_non_default = greedy_default ^ 1;
+ req_caseopt = ((newoptions & PCRE_CASELESS) != 0)? REQ_CASELESS:0;
+ }
+
+ /* Change options at this level, and pass them back for use
+ in subsequent branches. */
+
+ *optionsptr = options = newoptions;
+ previous = NULL; /* This item can't be repeated */
+ continue; /* It is complete */
+ }
+
+ /* If the options ended with ':' we are heading into a nested group
+ with possible change of options. Such groups are non-capturing and are
+ not assertions of any kind. All we need to do is skip over the ':';
+ the newoptions value is handled below. */
+
+ bravalue = OP_BRA;
+ ptr++;
+ } /* End of switch for character following (? */
+ } /* End of (? handling */
+
+ /* Opening parenthesis not followed by '*' or '?'. If PCRE_NO_AUTO_CAPTURE
+ is set, all unadorned brackets become non-capturing and behave like (?:...)
+ brackets. */
+
+ else if ((options & PCRE_NO_AUTO_CAPTURE) != 0)
+ {
+ bravalue = OP_BRA;
+ }
+
+ /* Else we have a capturing group. */
+
+ else
+ {
+ NUMBERED_GROUP:
+ cd->bracount += 1;
+ PUT2(code, 1+LINK_SIZE, cd->bracount);
+ skipbytes = IMM2_SIZE;
+ }
+
+ /* Process nested bracketed regex. First check for parentheses nested too
+ deeply. */
+
+ if ((cd->parens_depth += 1) > PARENS_NEST_LIMIT)
+ {
+ *errorcodeptr = ERR82;
+ goto FAILED;
+ }
+
+ /* Assertions used not to be repeatable, but this was changed for Perl
+ compatibility, so all kinds can now be repeated. We copy code into a
+ non-register variable (tempcode) in order to be able to pass its address
+ because some compilers complain otherwise. */
+
+ previous = code; /* For handling repetition */
+ *code = bravalue;
+ tempcode = code;
+ tempreqvary = cd->req_varyopt; /* Save value before bracket */
+ tempbracount = cd->bracount; /* Save value before bracket */
+ length_prevgroup = 0; /* Initialize for pre-compile phase */
+
+ if (!compile_regex(
+ newoptions, /* The complete new option state */
+ &tempcode, /* Where to put code (updated) */
+ &ptr, /* Input pointer (updated) */
+ errorcodeptr, /* Where to put an error message */
+ (bravalue == OP_ASSERTBACK ||
+ bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */
+ reset_bracount, /* True if (?| group */
+ skipbytes, /* Skip over bracket number */
+ cond_depth +
+ ((bravalue == OP_COND)?1:0), /* Depth of condition subpatterns */
+ &subfirstchar, /* For possible first char */
+ &subfirstcharflags,
+ &subreqchar, /* For possible last char */
+ &subreqcharflags,
+ bcptr, /* Current branch chain */
+ cd, /* Tables block */
+ (lengthptr == NULL)? NULL : /* Actual compile phase */
+ &length_prevgroup /* Pre-compile phase */
+ ))
+ goto FAILED;
+
+ cd->parens_depth -= 1;
+
+ /* If this was an atomic group and there are no capturing groups within it,
+ generate OP_ONCE_NC instead of OP_ONCE. */
+
+ if (bravalue == OP_ONCE && cd->bracount <= tempbracount)
+ *code = OP_ONCE_NC;
+
+ if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NOT)
+ cd->assert_depth -= 1;
+
+ /* At the end of compiling, code is still pointing to the start of the
+ group, while tempcode has been updated to point past the end of the group.
+ The pattern pointer (ptr) is on the bracket.
+
+ If this is a conditional bracket, check that there are no more than
+ two branches in the group, or just one if it's a DEFINE group. We do this
+ in the real compile phase, not in the pre-pass, where the whole group may
+ not be available. */
+
+ if (bravalue == OP_COND && lengthptr == NULL)
+ {
+ pcre_uchar *tc = code;
+ int condcount = 0;
+
+ do {
+ condcount++;
+ tc += GET(tc,1);
+ }
+ while (*tc != OP_KET);
+
+ /* A DEFINE group is never obeyed inline (the "condition" is always
+ false). It must have only one branch. */
+
+ if (code[LINK_SIZE+1] == OP_DEF)
+ {
+ if (condcount > 1)
+ {
+ *errorcodeptr = ERR54;
+ goto FAILED;
+ }
+ bravalue = OP_DEF; /* Just a flag to suppress char handling below */
+ }
+
+ /* A "normal" conditional group. If there is just one branch, we must not
+ make use of its firstchar or reqchar, because this is equivalent to an
+ empty second branch. */
+
+ else
+ {
+ if (condcount > 2)
+ {
+ *errorcodeptr = ERR27;
+ goto FAILED;
+ }
+ if (condcount == 1) subfirstcharflags = subreqcharflags = REQ_NONE;
+ }
+ }
+
+ /* Error if hit end of pattern */
+
+ if (*ptr != CHAR_RIGHT_PARENTHESIS)
+ {
+ *errorcodeptr = ERR14;
+ goto FAILED;
+ }
+
+ /* In the pre-compile phase, update the length by the length of the group,
+ less the brackets at either end. Then reduce the compiled code to just a
+ set of non-capturing brackets so that it doesn't use much memory if it is
+ duplicated by a quantifier.*/
+
+ if (lengthptr != NULL)
+ {
+ if (OFLOW_MAX - *lengthptr < length_prevgroup - 2 - 2*LINK_SIZE)
+ {
+ *errorcodeptr = ERR20;
+ goto FAILED;
+ }
+ *lengthptr += length_prevgroup - 2 - 2*LINK_SIZE;
+ code++; /* This already contains bravalue */
+ PUTINC(code, 0, 1 + LINK_SIZE);
+ *code++ = OP_KET;
+ PUTINC(code, 0, 1 + LINK_SIZE);
+ break; /* No need to waste time with special character handling */
+ }
+
+ /* Otherwise update the main code pointer to the end of the group. */
+
+ code = tempcode;
+
+ /* For a DEFINE group, required and first character settings are not
+ relevant. */
+
+ if (bravalue == OP_DEF) break;
+
+ /* Handle updating of the required and first characters for other types of
+ group. Update for normal brackets of all kinds, and conditions with two
+ branches (see code above). If the bracket is followed by a quantifier with
+ zero repeat, we have to back off. Hence the definition of zeroreqchar and
+ zerofirstchar outside the main loop so that they can be accessed for the
+ back off. */
+
+ zeroreqchar = reqchar;
+ zeroreqcharflags = reqcharflags;
+ zerofirstchar = firstchar;
+ zerofirstcharflags = firstcharflags;
+ groupsetfirstchar = FALSE;
+
+ if (bravalue >= OP_ONCE)
+ {
+ /* If we have not yet set a firstchar in this branch, take it from the
+ subpattern, remembering that it was set here so that a repeat of more
+ than one can replicate it as reqchar if necessary. If the subpattern has
+ no firstchar, set "none" for the whole branch. In both cases, a zero
+ repeat forces firstchar to "none". */
+
+ if (firstcharflags == REQ_UNSET)
+ {
+ if (subfirstcharflags >= 0)
+ {
+ firstchar = subfirstchar;
+ firstcharflags = subfirstcharflags;
+ groupsetfirstchar = TRUE;
+ }
+ else firstcharflags = REQ_NONE;
+ zerofirstcharflags = REQ_NONE;
+ }
+
+ /* If firstchar was previously set, convert the subpattern's firstchar
+ into reqchar if there wasn't one, using the vary flag that was in
+ existence beforehand. */
+
+ else if (subfirstcharflags >= 0 && subreqcharflags < 0)
+ {
+ subreqchar = subfirstchar;
+ subreqcharflags = subfirstcharflags | tempreqvary;
+ }
+
+ /* If the subpattern set a required byte (or set a first byte that isn't
+ really the first byte - see above), set it. */
+
+ if (subreqcharflags >= 0)
+ {
+ reqchar = subreqchar;
+ reqcharflags = subreqcharflags;
+ }
+ }
+
+ /* For a forward assertion, we take the reqchar, if set. This can be
+ helpful if the pattern that follows the assertion doesn't set a different
+ char. For example, it's useful for /(?=abcde).+/. We can't set firstchar
+ for an assertion, however because it leads to incorrect effect for patterns
+ such as /(?=a)a.+/ when the "real" "a" would then become a reqchar instead
+ of a firstchar. This is overcome by a scan at the end if there's no
+ firstchar, looking for an asserted first char. */
+
+ else if (bravalue == OP_ASSERT && subreqcharflags >= 0)
+ {
+ reqchar = subreqchar;
+ reqcharflags = subreqcharflags;
+ }
+ break; /* End of processing '(' */
+
+
+ /* ===================================================================*/
+ /* Handle metasequences introduced by \. For ones like \d, the ESC_ values
+ are arranged to be the negation of the corresponding OP_values in the
+ default case when PCRE_UCP is not set. For the back references, the values
+ are negative the reference number. Only back references and those types
+ that consume a character may be repeated. We can test for values between
+ ESC_b and ESC_Z for the latter; this may have to change if any new ones are
+ ever created. */
+
+ case CHAR_BACKSLASH:
+ tempptr = ptr;
+ escape = check_escape(&ptr, &ec, errorcodeptr, cd->bracount, options, FALSE);
+ if (*errorcodeptr != 0) goto FAILED;
+
+ if (escape == 0) /* The escape coded a single character */
+ c = ec;
+ else
+ {
+ if (escape == ESC_Q) /* Handle start of quoted string */
+ {
+ if (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E)
+ ptr += 2; /* avoid empty string */
+ else inescq = TRUE;
+ continue;
+ }
+
+ if (escape == ESC_E) continue; /* Perl ignores an orphan \E */
+
+ /* For metasequences that actually match a character, we disable the
+ setting of a first character if it hasn't already been set. */
+
+ if (firstcharflags == REQ_UNSET && escape > ESC_b && escape < ESC_Z)
+ firstcharflags = REQ_NONE;
+
+ /* Set values to reset to if this is followed by a zero repeat. */
+
+ zerofirstchar = firstchar;
+ zerofirstcharflags = firstcharflags;
+ zeroreqchar = reqchar;
+ zeroreqcharflags = reqcharflags;
+
+ /* \g<name> or \g'name' is a subroutine call by name and \g<n> or \g'n'
+ is a subroutine call by number (Oniguruma syntax). In fact, the value
+ ESC_g is returned only for these cases. So we don't need to check for <
+ or ' if the value is ESC_g. For the Perl syntax \g{n} the value is
+ -n, and for the Perl syntax \g{name} the result is ESC_k (as
+ that is a synonym for a named back reference). */
+
+ if (escape == ESC_g)
+ {
+ const pcre_uchar *p;
+ pcre_uint32 cf;
+
+ save_hwm = cd->hwm; /* Normally this is set when '(' is read */
+ terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)?
+ CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE;
+
+ /* These two statements stop the compiler for warning about possibly
+ unset variables caused by the jump to HANDLE_NUMERICAL_RECURSION. In
+ fact, because we do the check for a number below, the paths that
+ would actually be in error are never taken. */
+
+ skipbytes = 0;
+ reset_bracount = FALSE;
+
+ /* If it's not a signed or unsigned number, treat it as a name. */
+
+ cf = ptr[1];
+ if (cf != CHAR_PLUS && cf != CHAR_MINUS && !IS_DIGIT(cf))
+ {
+ is_recurse = TRUE;
+ goto NAMED_REF_OR_RECURSE;
+ }
+
+ /* Signed or unsigned number (cf = ptr[1]) is known to be plus or minus
+ or a digit. */
+
+ p = ptr + 2;
+ while (IS_DIGIT(*p)) p++;
+ if (*p != (pcre_uchar)terminator)
+ {
+ *errorcodeptr = ERR57;
+ break;
+ }
+ ptr++;
+ goto HANDLE_NUMERICAL_RECURSION;
+ }
+
+ /* \k<name> or \k'name' is a back reference by name (Perl syntax).
+ We also support \k{name} (.NET syntax). */
+
+ if (escape == ESC_k)
+ {
+ if ((ptr[1] != CHAR_LESS_THAN_SIGN &&
+ ptr[1] != CHAR_APOSTROPHE && ptr[1] != CHAR_LEFT_CURLY_BRACKET))
+ {
+ *errorcodeptr = ERR69;
+ break;
+ }
+ is_recurse = FALSE;
+ terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)?
+ CHAR_GREATER_THAN_SIGN : (*ptr == CHAR_APOSTROPHE)?
+ CHAR_APOSTROPHE : CHAR_RIGHT_CURLY_BRACKET;
+ goto NAMED_REF_OR_RECURSE;
+ }
+
+ /* Back references are handled specially; must disable firstchar if
+ not set to cope with cases like (?=(\w+))\1: which would otherwise set
+ ':' later. */
+
+ if (escape < 0)
+ {
+ open_capitem *oc;
+ recno = -escape;
+
+ /* Come here from named backref handling when the reference is to a
+ single group (i.e. not to a duplicated name. */
+
+ HANDLE_REFERENCE:
+ if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
+ previous = code;
+ *code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF;
+ PUT2INC(code, 0, recno);
+ cd->backref_map |= (recno < 32)? (1 << recno) : 1;
+ if (recno > cd->top_backref) cd->top_backref = recno;
+
+ /* Check to see if this back reference is recursive, that it, it
+ is inside the group that it references. A flag is set so that the
+ group can be made atomic. */
+
+ for (oc = cd->open_caps; oc != NULL; oc = oc->next)
+ {
+ if (oc->number == recno)
+ {
+ oc->flag = TRUE;
+ break;
+ }
+ }
+ }
+
+ /* So are Unicode property matches, if supported. */
+
+#ifdef SUPPORT_UCP
+ else if (escape == ESC_P || escape == ESC_p)
+ {
+ BOOL negated;
+ unsigned int ptype = 0, pdata = 0;
+ if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr))
+ goto FAILED;
+ previous = code;
+ *code++ = ((escape == ESC_p) != negated)? OP_PROP : OP_NOTPROP;
+ *code++ = ptype;
+ *code++ = pdata;
+ }
+#else
+
+ /* If Unicode properties are not supported, \X, \P, and \p are not
+ allowed. */
+
+ else if (escape == ESC_X || escape == ESC_P || escape == ESC_p)
+ {
+ *errorcodeptr = ERR45;
+ goto FAILED;
+ }
+#endif
+
+ /* For the rest (including \X when Unicode properties are supported), we
+ can obtain the OP value by negating the escape value in the default
+ situation when PCRE_UCP is not set. When it *is* set, we substitute
+ Unicode property tests. Note that \b and \B do a one-character
+ lookbehind, and \A also behaves as if it does. */
+
+ else
+ {
+ if ((escape == ESC_b || escape == ESC_B || escape == ESC_A) &&
+ cd->max_lookbehind == 0)
+ cd->max_lookbehind = 1;
+#ifdef SUPPORT_UCP
+ if (escape >= ESC_DU && escape <= ESC_wu)
+ {
+ nestptr = ptr + 1; /* Where to resume */
+ ptr = substitutes[escape - ESC_DU] - 1; /* Just before substitute */
+ }
+ else
+#endif
+ /* In non-UTF-8 mode, we turn \C into OP_ALLANY instead of OP_ANYBYTE
+ so that it works in DFA mode and in lookbehinds. */
+
+ {
+ previous = (escape > ESC_b && escape < ESC_Z)? code : NULL;
+ *code++ = (!utf && escape == ESC_C)? OP_ALLANY : escape;
+ }
+ }
+ continue;
+ }
+
+ /* We have a data character whose value is in c. In UTF-8 mode it may have
+ a value > 127. We set its representation in the length/buffer, and then
+ handle it as a data character. */
+
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR)
+ mclength = PRIV(ord2utf)(c, mcbuffer);
+ else
+#endif
+
+ {
+ mcbuffer[0] = c;
+ mclength = 1;
+ }
+ goto ONE_CHAR;
+
+
+ /* ===================================================================*/
+ /* Handle a literal character. It is guaranteed not to be whitespace or #
+ when the extended flag is set. If we are in a UTF mode, it may be a
+ multi-unit literal character. */
+
+ default:
+ NORMAL_CHAR:
+ mclength = 1;
+ mcbuffer[0] = c;
+
+#ifdef SUPPORT_UTF
+ if (utf && HAS_EXTRALEN(c))
+ ACROSSCHAR(TRUE, ptr[1], mcbuffer[mclength++] = *(++ptr));
+#endif
+
+ /* At this point we have the character's bytes in mcbuffer, and the length
+ in mclength. When not in UTF-8 mode, the length is always 1. */
+
+ ONE_CHAR:
+ previous = code;
+
+ /* For caseless UTF-8 mode when UCP support is available, check whether
+ this character has more than one other case. If so, generate a special
+ OP_PROP item instead of OP_CHARI. */
+
+#ifdef SUPPORT_UCP
+ if (utf && (options & PCRE_CASELESS) != 0)
+ {
+ GETCHAR(c, mcbuffer);
+ if ((c = UCD_CASESET(c)) != 0)
+ {
+ *code++ = OP_PROP;
+ *code++ = PT_CLIST;
+ *code++ = c;
+ if (firstcharflags == REQ_UNSET)
+ firstcharflags = zerofirstcharflags = REQ_NONE;
+ break;
+ }
+ }
+#endif
+
+ /* Caseful matches, or not one of the multicase characters. */
+
+ *code++ = ((options & PCRE_CASELESS) != 0)? OP_CHARI : OP_CHAR;
+ for (c = 0; c < mclength; c++) *code++ = mcbuffer[c];
+
+ /* Remember if \r or \n were seen */
+
+ if (mcbuffer[0] == CHAR_CR || mcbuffer[0] == CHAR_NL)
+ cd->external_flags |= PCRE_HASCRORLF;
+
+ /* Set the first and required bytes appropriately. If no previous first
+ byte, set it from this character, but revert to none on a zero repeat.
+ Otherwise, leave the firstchar value alone, and don't change it on a zero
+ repeat. */
+
+ if (firstcharflags == REQ_UNSET)
+ {
+ zerofirstcharflags = REQ_NONE;
+ zeroreqchar = reqchar;
+ zeroreqcharflags = reqcharflags;
+
+ /* If the character is more than one byte long, we can set firstchar
+ only if it is not to be matched caselessly. */
+
+ if (mclength == 1 || req_caseopt == 0)
+ {
+ firstchar = mcbuffer[0] | req_caseopt;
+ firstchar = mcbuffer[0];
+ firstcharflags = req_caseopt;
+
+ if (mclength != 1)
+ {
+ reqchar = code[-1];
+ reqcharflags = cd->req_varyopt;
+ }
+ }
+ else firstcharflags = reqcharflags = REQ_NONE;
+ }
+
+ /* firstchar was previously set; we can set reqchar only if the length is
+ 1 or the matching is caseful. */
+
+ else
+ {
+ zerofirstchar = firstchar;
+ zerofirstcharflags = firstcharflags;
+ zeroreqchar = reqchar;
+ zeroreqcharflags = reqcharflags;
+ if (mclength == 1 || req_caseopt == 0)
+ {
+ reqchar = code[-1];
+ reqcharflags = req_caseopt | cd->req_varyopt;
+ }
+ }
+
+ break; /* End of literal character handling */
+ }
+ } /* end of big loop */
+
+
+/* Control never reaches here by falling through, only by a goto for all the
+error states. Pass back the position in the pattern so that it can be displayed
+to the user for diagnosing the error. */
+
+FAILED:
+*ptrptr = ptr;
+return FALSE;
+}
+
+
+
+/*************************************************
+* Compile sequence of alternatives *
+*************************************************/
+
+/* On entry, ptr is pointing past the bracket character, but on return it
+points to the closing bracket, or vertical bar, or end of string. The code
+variable is pointing at the byte into which the BRA operator has been stored.
+This function is used during the pre-compile phase when we are trying to find
+out the amount of memory needed, as well as during the real compile phase. The
+value of lengthptr distinguishes the two phases.
+
+Arguments:
+ options option bits, including any changes for this subpattern
+ codeptr -> the address of the current code pointer
+ ptrptr -> the address of the current pattern pointer
+ errorcodeptr -> pointer to error code variable
+ lookbehind TRUE if this is a lookbehind assertion
+ reset_bracount TRUE to reset the count for each branch
+ skipbytes skip this many bytes at start (for brackets and OP_COND)
+ cond_depth depth of nesting for conditional subpatterns
+ firstcharptr place to put the first required character
+ firstcharflagsptr place to put the first character flags, or a negative number
+ reqcharptr place to put the last required character
+ reqcharflagsptr place to put the last required character flags, or a negative number
+ bcptr pointer to the chain of currently open branches
+ cd points to the data block with tables pointers etc.
+ lengthptr NULL during the real compile phase
+ points to length accumulator during pre-compile phase
+
+Returns: TRUE on success
+*/
+
+static BOOL
+compile_regex(int options, pcre_uchar **codeptr, const pcre_uchar **ptrptr,
+ int *errorcodeptr, BOOL lookbehind, BOOL reset_bracount, int skipbytes,
+ int cond_depth,
+ pcre_uint32 *firstcharptr, pcre_int32 *firstcharflagsptr,
+ pcre_uint32 *reqcharptr, pcre_int32 *reqcharflagsptr,
+ branch_chain *bcptr, compile_data *cd, int *lengthptr)
+{
+const pcre_uchar *ptr = *ptrptr;
+pcre_uchar *code = *codeptr;
+pcre_uchar *last_branch = code;
+pcre_uchar *start_bracket = code;
+pcre_uchar *reverse_count = NULL;
+open_capitem capitem;
+int capnumber = 0;
+pcre_uint32 firstchar, reqchar;
+pcre_int32 firstcharflags, reqcharflags;
+pcre_uint32 branchfirstchar, branchreqchar;
+pcre_int32 branchfirstcharflags, branchreqcharflags;
+int length;
+unsigned int orig_bracount;
+unsigned int max_bracount;
+branch_chain bc;
+
+/* If set, call the external function that checks for stack availability. */
+
+if (PUBL(stack_guard) != NULL && PUBL(stack_guard)())
+ {
+ *errorcodeptr= ERR85;
+ return FALSE;
+ }
+
+/* Miscellaneous initialization */
+
+bc.outer = bcptr;
+bc.current_branch = code;
+
+firstchar = reqchar = 0;
+firstcharflags = reqcharflags = REQ_UNSET;
+
+/* Accumulate the length for use in the pre-compile phase. Start with the
+length of the BRA and KET and any extra bytes that are required at the
+beginning. We accumulate in a local variable to save frequent testing of
+lenthptr for NULL. We cannot do this by looking at the value of code at the
+start and end of each alternative, because compiled items are discarded during
+the pre-compile phase so that the work space is not exceeded. */
+
+length = 2 + 2*LINK_SIZE + skipbytes;
+
+/* WARNING: If the above line is changed for any reason, you must also change
+the code that abstracts option settings at the start of the pattern and makes
+them global. It tests the value of length for (2 + 2*LINK_SIZE) in the
+pre-compile phase to find out whether anything has yet been compiled or not. */
+
+/* If this is a capturing subpattern, add to the chain of open capturing items
+so that we can detect them if (*ACCEPT) is encountered. This is also used to
+detect groups that contain recursive back references to themselves. Note that
+only OP_CBRA need be tested here; changing this opcode to one of its variants,
+e.g. OP_SCBRAPOS, happens later, after the group has been compiled. */
+
+if (*code == OP_CBRA)
+ {
+ capnumber = GET2(code, 1 + LINK_SIZE);
+ capitem.number = capnumber;
+ capitem.next = cd->open_caps;
+ capitem.flag = FALSE;
+ cd->open_caps = &capitem;
+ }
+
+/* Offset is set zero to mark that this bracket is still open */
+
+PUT(code, 1, 0);
+code += 1 + LINK_SIZE + skipbytes;
+
+/* Loop for each alternative branch */
+
+orig_bracount = max_bracount = cd->bracount;
+for (;;)
+ {
+ /* For a (?| group, reset the capturing bracket count so that each branch
+ uses the same numbers. */
+
+ if (reset_bracount) cd->bracount = orig_bracount;
+
+ /* Set up dummy OP_REVERSE if lookbehind assertion */
+
+ if (lookbehind)
+ {
+ *code++ = OP_REVERSE;
+ reverse_count = code;
+ PUTINC(code, 0, 0);
+ length += 1 + LINK_SIZE;
+ }
+
+ /* Now compile the branch; in the pre-compile phase its length gets added
+ into the length. */
+
+ if (!compile_branch(&options, &code, &ptr, errorcodeptr, &branchfirstchar,
+ &branchfirstcharflags, &branchreqchar, &branchreqcharflags, &bc,
+ cond_depth, cd, (lengthptr == NULL)? NULL : &length))
+ {
+ *ptrptr = ptr;
+ return FALSE;
+ }
+
+ /* Keep the highest bracket count in case (?| was used and some branch
+ has fewer than the rest. */
+
+ if (cd->bracount > max_bracount) max_bracount = cd->bracount;
+
+ /* In the real compile phase, there is some post-processing to be done. */
+
+ if (lengthptr == NULL)
+ {
+ /* If this is the first branch, the firstchar and reqchar values for the
+ branch become the values for the regex. */
+
+ if (*last_branch != OP_ALT)
+ {
+ firstchar = branchfirstchar;
+ firstcharflags = branchfirstcharflags;
+ reqchar = branchreqchar;
+ reqcharflags = branchreqcharflags;
+ }
+
+ /* If this is not the first branch, the first char and reqchar have to
+ match the values from all the previous branches, except that if the
+ previous value for reqchar didn't have REQ_VARY set, it can still match,
+ and we set REQ_VARY for the regex. */
+
+ else
+ {
+ /* If we previously had a firstchar, but it doesn't match the new branch,
+ we have to abandon the firstchar for the regex, but if there was
+ previously no reqchar, it takes on the value of the old firstchar. */
+
+ if (firstcharflags >= 0 &&
+ (firstcharflags != branchfirstcharflags || firstchar != branchfirstchar))
+ {
+ if (reqcharflags < 0)
+ {
+ reqchar = firstchar;
+ reqcharflags = firstcharflags;
+ }
+ firstcharflags = REQ_NONE;
+ }
+
+ /* If we (now or from before) have no firstchar, a firstchar from the
+ branch becomes a reqchar if there isn't a branch reqchar. */
+
+ if (firstcharflags < 0 && branchfirstcharflags >= 0 && branchreqcharflags < 0)
+ {
+ branchreqchar = branchfirstchar;
+ branchreqcharflags = branchfirstcharflags;
+ }
+
+ /* Now ensure that the reqchars match */
+
+ if (((reqcharflags & ~REQ_VARY) != (branchreqcharflags & ~REQ_VARY)) ||
+ reqchar != branchreqchar)
+ reqcharflags = REQ_NONE;
+ else
+ {
+ reqchar = branchreqchar;
+ reqcharflags |= branchreqcharflags; /* To "or" REQ_VARY */
+ }
+ }
+
+ /* If lookbehind, check that this branch matches a fixed-length string, and
+ put the length into the OP_REVERSE item. Temporarily mark the end of the
+ branch with OP_END. If the branch contains OP_RECURSE, the result is -3
+ because there may be forward references that we can't check here. Set a
+ flag to cause another lookbehind check at the end. Why not do it all at the
+ end? Because common, erroneous checks are picked up here and the offset of
+ the problem can be shown. */
+
+ if (lookbehind)
+ {
+ int fixed_length;
+ *code = OP_END;
+ fixed_length = find_fixedlength(last_branch, (options & PCRE_UTF8) != 0,
+ FALSE, cd);
+ DPRINTF(("fixed length = %d\n", fixed_length));
+ if (fixed_length == -3)
+ {
+ cd->check_lookbehind = TRUE;
+ }
+ else if (fixed_length < 0)
+ {
+ *errorcodeptr = (fixed_length == -2)? ERR36 :
+ (fixed_length == -4)? ERR70: ERR25;
+ *ptrptr = ptr;
+ return FALSE;
+ }
+ else
+ {
+ if (fixed_length > cd->max_lookbehind)
+ cd->max_lookbehind = fixed_length;
+ PUT(reverse_count, 0, fixed_length);
+ }
+ }
+ }
+
+ /* Reached end of expression, either ')' or end of pattern. In the real
+ compile phase, go back through the alternative branches and reverse the chain
+ of offsets, with the field in the BRA item now becoming an offset to the
+ first alternative. If there are no alternatives, it points to the end of the
+ group. The length in the terminating ket is always the length of the whole
+ bracketed item. Return leaving the pointer at the terminating char. */
+
+ if (*ptr != CHAR_VERTICAL_LINE)
+ {
+ if (lengthptr == NULL)
+ {
+ int branch_length = (int)(code - last_branch);
+ do
+ {
+ int prev_length = GET(last_branch, 1);
+ PUT(last_branch, 1, branch_length);
+ branch_length = prev_length;
+ last_branch -= branch_length;
+ }
+ while (branch_length > 0);
+ }
+
+ /* Fill in the ket */
+
+ *code = OP_KET;
+ PUT(code, 1, (int)(code - start_bracket));
+ code += 1 + LINK_SIZE;
+
+ /* If it was a capturing subpattern, check to see if it contained any
+ recursive back references. If so, we must wrap it in atomic brackets.
+ In any event, remove the block from the chain. */
+
+ if (capnumber > 0)
+ {
+ if (cd->open_caps->flag)
+ {
+ memmove(start_bracket + 1 + LINK_SIZE, start_bracket,
+ IN_UCHARS(code - start_bracket));
+ *start_bracket = OP_ONCE;
+ code += 1 + LINK_SIZE;
+ PUT(start_bracket, 1, (int)(code - start_bracket));
+ *code = OP_KET;
+ PUT(code, 1, (int)(code - start_bracket));
+ code += 1 + LINK_SIZE;
+ length += 2 + 2*LINK_SIZE;
+ }
+ cd->open_caps = cd->open_caps->next;
+ }
+
+ /* Retain the highest bracket number, in case resetting was used. */
+
+ cd->bracount = max_bracount;
+
+ /* Set values to pass back */
+
+ *codeptr = code;
+ *ptrptr = ptr;
+ *firstcharptr = firstchar;
+ *firstcharflagsptr = firstcharflags;
+ *reqcharptr = reqchar;
+ *reqcharflagsptr = reqcharflags;
+ if (lengthptr != NULL)
+ {
+ if (OFLOW_MAX - *lengthptr < length)
+ {
+ *errorcodeptr = ERR20;
+ return FALSE;
+ }
+ *lengthptr += length;
+ }
+ return TRUE;
+ }
+
+ /* Another branch follows. In the pre-compile phase, we can move the code
+ pointer back to where it was for the start of the first branch. (That is,
+ pretend that each branch is the only one.)
+
+ In the real compile phase, insert an ALT node. Its length field points back
+ to the previous branch while the bracket remains open. At the end the chain
+ is reversed. It's done like this so that the start of the bracket has a
+ zero offset until it is closed, making it possible to detect recursion. */
+
+ if (lengthptr != NULL)
+ {
+ code = *codeptr + 1 + LINK_SIZE + skipbytes;
+ length += 1 + LINK_SIZE;
+ }
+ else
+ {
+ *code = OP_ALT;
+ PUT(code, 1, (int)(code - last_branch));
+ bc.current_branch = last_branch = code;
+ code += 1 + LINK_SIZE;
+ }
+
+ ptr++;
+ }
+/* Control never reaches here */
+}
+
+
+
+
+/*************************************************
+* Check for anchored expression *
+*************************************************/
+
+/* Try to find out if this is an anchored regular expression. Consider each
+alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket
+all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then
+it's anchored. However, if this is a multiline pattern, then only OP_SOD will
+be found, because ^ generates OP_CIRCM in that mode.
+
+We can also consider a regex to be anchored if OP_SOM starts all its branches.
+This is the code for \G, which means "match at start of match position, taking
+into account the match offset".
+
+A branch is also implicitly anchored if it starts with .* and DOTALL is set,
+because that will try the rest of the pattern at all possible matching points,
+so there is no point trying again.... er ....
+
+.... except when the .* appears inside capturing parentheses, and there is a
+subsequent back reference to those parentheses. We haven't enough information
+to catch that case precisely.
+
+At first, the best we could do was to detect when .* was in capturing brackets
+and the highest back reference was greater than or equal to that level.
+However, by keeping a bitmap of the first 31 back references, we can catch some
+of the more common cases more precisely.
+
+... A second exception is when the .* appears inside an atomic group, because
+this prevents the number of characters it matches from being adjusted.
+
+Arguments:
+ code points to start of expression (the bracket)
+ bracket_map a bitmap of which brackets we are inside while testing; this
+ handles up to substring 31; after that we just have to take
+ the less precise approach
+ cd points to the compile data block
+ atomcount atomic group level
+
+Returns: TRUE or FALSE
+*/
+
+static BOOL
+is_anchored(register const pcre_uchar *code, unsigned int bracket_map,
+ compile_data *cd, int atomcount)
+{
+do {
+ const pcre_uchar *scode = first_significant_code(
+ code + PRIV(OP_lengths)[*code], FALSE);
+ register int op = *scode;
+
+ /* Non-capturing brackets */
+
+ if (op == OP_BRA || op == OP_BRAPOS ||
+ op == OP_SBRA || op == OP_SBRAPOS)
+ {
+ if (!is_anchored(scode, bracket_map, cd, atomcount)) return FALSE;
+ }
+
+ /* Capturing brackets */
+
+ else if (op == OP_CBRA || op == OP_CBRAPOS ||
+ op == OP_SCBRA || op == OP_SCBRAPOS)
+ {
+ int n = GET2(scode, 1+LINK_SIZE);
+ int new_map = bracket_map | ((n < 32)? (1 << n) : 1);
+ if (!is_anchored(scode, new_map, cd, atomcount)) return FALSE;
+ }
+
+ /* Positive forward assertions and conditions */
+
+ else if (op == OP_ASSERT || op == OP_COND)
+ {
+ if (!is_anchored(scode, bracket_map, cd, atomcount)) return FALSE;
+ }
+
+ /* Atomic groups */
+
+ else if (op == OP_ONCE || op == OP_ONCE_NC)
+ {
+ if (!is_anchored(scode, bracket_map, cd, atomcount + 1))
+ return FALSE;
+ }
+
+ /* .* is not anchored unless DOTALL is set (which generates OP_ALLANY) and
+ it isn't in brackets that are or may be referenced or inside an atomic
+ group. */
+
+ else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR ||
+ op == OP_TYPEPOSSTAR))
+ {
+ if (scode[1] != OP_ALLANY || (bracket_map & cd->backref_map) != 0 ||
+ atomcount > 0 || cd->had_pruneorskip)
+ return FALSE;
+ }
+
+ /* Check for explicit anchoring */
+
+ else if (op != OP_SOD && op != OP_SOM && op != OP_CIRC) return FALSE;
+
+ code += GET(code, 1);
+ }
+while (*code == OP_ALT); /* Loop for each alternative */
+return TRUE;
+}
+
+
+
+/*************************************************
+* Check for starting with ^ or .* *
+*************************************************/
+
+/* This is called to find out if every branch starts with ^ or .* so that
+"first char" processing can be done to speed things up in multiline
+matching and for non-DOTALL patterns that start with .* (which must start at
+the beginning or after \n). As in the case of is_anchored() (see above), we
+have to take account of back references to capturing brackets that contain .*
+because in that case we can't make the assumption. Also, the appearance of .*
+inside atomic brackets or in a pattern that contains *PRUNE or *SKIP does not
+count, because once again the assumption no longer holds.
+
+Arguments:
+ code points to start of expression (the bracket)
+ bracket_map a bitmap of which brackets we are inside while testing; this
+ handles up to substring 31; after that we just have to take
+ the less precise approach
+ cd points to the compile data
+ atomcount atomic group level
+
+Returns: TRUE or FALSE
+*/
+
+static BOOL
+is_startline(const pcre_uchar *code, unsigned int bracket_map,
+ compile_data *cd, int atomcount)
+{
+do {
+ const pcre_uchar *scode = first_significant_code(
+ code + PRIV(OP_lengths)[*code], FALSE);
+ register int op = *scode;
+
+ /* If we are at the start of a conditional assertion group, *both* the
+ conditional assertion *and* what follows the condition must satisfy the test
+ for start of line. Other kinds of condition fail. Note that there may be an
+ auto-callout at the start of a condition. */
+
+ if (op == OP_COND)
+ {
+ scode += 1 + LINK_SIZE;
+ if (*scode == OP_CALLOUT) scode += PRIV(OP_lengths)[OP_CALLOUT];
+ switch (*scode)
+ {
+ case OP_CREF:
+ case OP_DNCREF:
+ case OP_RREF:
+ case OP_DNRREF:
+ case OP_DEF:
+ return FALSE;
+
+ default: /* Assertion */
+ if (!is_startline(scode, bracket_map, cd, atomcount)) return FALSE;
+ do scode += GET(scode, 1); while (*scode == OP_ALT);
+ scode += 1 + LINK_SIZE;
+ break;
+ }
+ scode = first_significant_code(scode, FALSE);
+ op = *scode;
+ }
+
+ /* Non-capturing brackets */
+
+ if (op == OP_BRA || op == OP_BRAPOS ||
+ op == OP_SBRA || op == OP_SBRAPOS)
+ {
+ if (!is_startline(scode, bracket_map, cd, atomcount)) return FALSE;
+ }
+
+ /* Capturing brackets */
+
+ else if (op == OP_CBRA || op == OP_CBRAPOS ||
+ op == OP_SCBRA || op == OP_SCBRAPOS)
+ {
+ int n = GET2(scode, 1+LINK_SIZE);
+ int new_map = bracket_map | ((n < 32)? (1 << n) : 1);
+ if (!is_startline(scode, new_map, cd, atomcount)) return FALSE;
+ }
+
+ /* Positive forward assertions */
+
+ else if (op == OP_ASSERT)
+ {
+ if (!is_startline(scode, bracket_map, cd, atomcount)) return FALSE;
+ }
+
+ /* Atomic brackets */
+
+ else if (op == OP_ONCE || op == OP_ONCE_NC)
+ {
+ if (!is_startline(scode, bracket_map, cd, atomcount + 1)) return FALSE;
+ }
+
+ /* .* means "start at start or after \n" if it isn't in atomic brackets or
+ brackets that may be referenced, as long as the pattern does not contain
+ *PRUNE or *SKIP, because these break the feature. Consider, for example,
+ /.*?a(*PRUNE)b/ with the subject "aab", which matches "ab", i.e. not at the
+ start of a line. */
+
+ else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR)
+ {
+ if (scode[1] != OP_ANY || (bracket_map & cd->backref_map) != 0 ||
+ atomcount > 0 || cd->had_pruneorskip)
+ return FALSE;
+ }
+
+ /* Check for explicit circumflex; anything else gives a FALSE result. Note
+ in particular that this includes atomic brackets OP_ONCE and OP_ONCE_NC
+ because the number of characters matched by .* cannot be adjusted inside
+ them. */
+
+ else if (op != OP_CIRC && op != OP_CIRCM) return FALSE;
+
+ /* Move on to the next alternative */
+
+ code += GET(code, 1);
+ }
+while (*code == OP_ALT); /* Loop for each alternative */
+return TRUE;
+}
+
+
+
+/*************************************************
+* Check for asserted fixed first char *
+*************************************************/
+
+/* During compilation, the "first char" settings from forward assertions are
+discarded, because they can cause conflicts with actual literals that follow.
+However, if we end up without a first char setting for an unanchored pattern,
+it is worth scanning the regex to see if there is an initial asserted first
+char. If all branches start with the same asserted char, or with a
+non-conditional bracket all of whose alternatives start with the same asserted
+char (recurse ad lib), then we return that char, with the flags set to zero or
+REQ_CASELESS; otherwise return zero with REQ_NONE in the flags.
+
+Arguments:
+ code points to start of expression (the bracket)
+ flags points to the first char flags, or to REQ_NONE
+ inassert TRUE if in an assertion
+
+Returns: the fixed first char, or 0 with REQ_NONE in flags
+*/
+
+static pcre_uint32
+find_firstassertedchar(const pcre_uchar *code, pcre_int32 *flags,
+ BOOL inassert)
+{
+register pcre_uint32 c = 0;
+int cflags = REQ_NONE;
+
+*flags = REQ_NONE;
+do {
+ pcre_uint32 d;
+ int dflags;
+ int xl = (*code == OP_CBRA || *code == OP_SCBRA ||
+ *code == OP_CBRAPOS || *code == OP_SCBRAPOS)? IMM2_SIZE:0;
+ const pcre_uchar *scode = first_significant_code(code + 1+LINK_SIZE + xl,
+ TRUE);
+ register pcre_uchar op = *scode;
+
+ switch(op)
+ {
+ default:
+ return 0;
+
+ case OP_BRA:
+ case OP_BRAPOS:
+ case OP_CBRA:
+ case OP_SCBRA:
+ case OP_CBRAPOS:
+ case OP_SCBRAPOS:
+ case OP_ASSERT:
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ d = find_firstassertedchar(scode, &dflags, op == OP_ASSERT);
+ if (dflags < 0)
+ return 0;
+ if (cflags < 0) { c = d; cflags = dflags; } else if (c != d || cflags != dflags) return 0;
+ break;
+
+ case OP_EXACT:
+ scode += IMM2_SIZE;
+ /* Fall through */
+
+ case OP_CHAR:
+ case OP_PLUS:
+ case OP_MINPLUS:
+ case OP_POSPLUS:
+ if (!inassert) return 0;
+ if (cflags < 0) { c = scode[1]; cflags = 0; }
+ else if (c != scode[1]) return 0;
+ break;
+
+ case OP_EXACTI:
+ scode += IMM2_SIZE;
+ /* Fall through */
+
+ case OP_CHARI:
+ case OP_PLUSI:
+ case OP_MINPLUSI:
+ case OP_POSPLUSI:
+ if (!inassert) return 0;
+ if (cflags < 0) { c = scode[1]; cflags = REQ_CASELESS; }
+ else if (c != scode[1]) return 0;
+ break;
+ }
+
+ code += GET(code, 1);
+ }
+while (*code == OP_ALT);
+
+*flags = cflags;
+return c;
+}
+
+
+
+/*************************************************
+* Add an entry to the name/number table *
+*************************************************/
+
+/* This function is called between compiling passes to add an entry to the
+name/number table, maintaining alphabetical order. Checking for permitted
+and forbidden duplicates has already been done.
+
+Arguments:
+ cd the compile data block
+ name the name to add
+ length the length of the name
+ groupno the group number
+
+Returns: nothing
+*/
+
+static void
+add_name(compile_data *cd, const pcre_uchar *name, int length,
+ unsigned int groupno)
+{
+int i;
+pcre_uchar *slot = cd->name_table;
+
+for (i = 0; i < cd->names_found; i++)
+ {
+ int crc = memcmp(name, slot+IMM2_SIZE, IN_UCHARS(length));
+ if (crc == 0 && slot[IMM2_SIZE+length] != 0)
+ crc = -1; /* Current name is a substring */
+
+ /* Make space in the table and break the loop for an earlier name. For a
+ duplicate or later name, carry on. We do this for duplicates so that in the
+ simple case (when ?(| is not used) they are in order of their numbers. In all
+ cases they are in the order in which they appear in the pattern. */
+
+ if (crc < 0)
+ {
+ memmove(slot + cd->name_entry_size, slot,
+ IN_UCHARS((cd->names_found - i) * cd->name_entry_size));
+ break;
+ }
+
+ /* Continue the loop for a later or duplicate name */
+
+ slot += cd->name_entry_size;
+ }
+
+PUT2(slot, 0, groupno);
+memcpy(slot + IMM2_SIZE, name, IN_UCHARS(length));
+slot[IMM2_SIZE + length] = 0;
+cd->names_found++;
+}
+
+
+
+/*************************************************
+* Compile a Regular Expression *
+*************************************************/
+
+/* This function takes a string and returns a pointer to a block of store
+holding a compiled version of the expression. The original API for this
+function had no error code return variable; it is retained for backwards
+compatibility. The new function is given a new name.
+
+Arguments:
+ pattern the regular expression
+ options various option bits
+ errorcodeptr pointer to error code variable (pcre_compile2() only)
+ can be NULL if you don't want a code value
+ errorptr pointer to pointer to error text
+ erroroffset ptr offset in pattern where error was detected
+ tables pointer to character tables or NULL
+
+Returns: pointer to compiled data block, or NULL on error,
+ with errorptr and erroroffset set
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN pcre * PCRE_CALL_CONVENTION
+pcre_compile(const char *pattern, int options, const char **errorptr,
+ int *erroroffset, const unsigned char *tables)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN pcre16 * PCRE_CALL_CONVENTION
+pcre16_compile(PCRE_SPTR16 pattern, int options, const char **errorptr,
+ int *erroroffset, const unsigned char *tables)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN pcre32 * PCRE_CALL_CONVENTION
+pcre32_compile(PCRE_SPTR32 pattern, int options, const char **errorptr,
+ int *erroroffset, const unsigned char *tables)
+#endif
+{
+#if defined COMPILE_PCRE8
+return pcre_compile2(pattern, options, NULL, errorptr, erroroffset, tables);
+#elif defined COMPILE_PCRE16
+return pcre16_compile2(pattern, options, NULL, errorptr, erroroffset, tables);
+#elif defined COMPILE_PCRE32
+return pcre32_compile2(pattern, options, NULL, errorptr, erroroffset, tables);
+#endif
+}
+
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN pcre * PCRE_CALL_CONVENTION
+pcre_compile2(const char *pattern, int options, int *errorcodeptr,
+ const char **errorptr, int *erroroffset, const unsigned char *tables)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN pcre16 * PCRE_CALL_CONVENTION
+pcre16_compile2(PCRE_SPTR16 pattern, int options, int *errorcodeptr,
+ const char **errorptr, int *erroroffset, const unsigned char *tables)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN pcre32 * PCRE_CALL_CONVENTION
+pcre32_compile2(PCRE_SPTR32 pattern, int options, int *errorcodeptr,
+ const char **errorptr, int *erroroffset, const unsigned char *tables)
+#endif
+{
+REAL_PCRE *re;
+int length = 1; /* For final END opcode */
+pcre_int32 firstcharflags, reqcharflags;
+pcre_uint32 firstchar, reqchar;
+pcre_uint32 limit_match = PCRE_UINT32_MAX;
+pcre_uint32 limit_recursion = PCRE_UINT32_MAX;
+int newline;
+int errorcode = 0;
+int skipatstart = 0;
+BOOL utf;
+BOOL never_utf = FALSE;
+size_t size;
+pcre_uchar *code;
+const pcre_uchar *codestart;
+const pcre_uchar *ptr;
+compile_data compile_block;
+compile_data *cd = &compile_block;
+
+/* This space is used for "compiling" into during the first phase, when we are
+computing the amount of memory that is needed. Compiled items are thrown away
+as soon as possible, so that a fairly large buffer should be sufficient for
+this purpose. The same space is used in the second phase for remembering where
+to fill in forward references to subpatterns. That may overflow, in which case
+new memory is obtained from malloc(). */
+
+pcre_uchar cworkspace[COMPILE_WORK_SIZE];
+
+/* This vector is used for remembering name groups during the pre-compile. In a
+similar way to cworkspace, it can be expanded using malloc() if necessary. */
+
+named_group named_groups[NAMED_GROUP_LIST_SIZE];
+
+/* Set this early so that early errors get offset 0. */
+
+ptr = (const pcre_uchar *)pattern;
+
+/* We can't pass back an error message if errorptr is NULL; I guess the best we
+can do is just return NULL, but we can set a code value if there is a code
+pointer. */
+
+if (errorptr == NULL)
+ {
+ if (errorcodeptr != NULL) *errorcodeptr = 99;
+ return NULL;
+ }
+
+*errorptr = NULL;
+if (errorcodeptr != NULL) *errorcodeptr = ERR0;
+
+/* However, we can give a message for this error */
+
+if (erroroffset == NULL)
+ {
+ errorcode = ERR16;
+ goto PCRE_EARLY_ERROR_RETURN2;
+ }
+
+*erroroffset = 0;
+
+/* Set up pointers to the individual character tables */
+
+if (tables == NULL) tables = PRIV(default_tables);
+cd->lcc = tables + lcc_offset;
+cd->fcc = tables + fcc_offset;
+cd->cbits = tables + cbits_offset;
+cd->ctypes = tables + ctypes_offset;
+
+/* Check that all undefined public option bits are zero */
+
+if ((options & ~PUBLIC_COMPILE_OPTIONS) != 0)
+ {
+ errorcode = ERR17;
+ goto PCRE_EARLY_ERROR_RETURN;
+ }
+
+/* If PCRE_NEVER_UTF is set, remember it. */
+
+if ((options & PCRE_NEVER_UTF) != 0) never_utf = TRUE;
+
+/* Check for global one-time settings at the start of the pattern, and remember
+the offset for later. */
+
+cd->external_flags = 0; /* Initialize here for LIMIT_MATCH/RECURSION */
+
+while (ptr[skipatstart] == CHAR_LEFT_PARENTHESIS &&
+ ptr[skipatstart+1] == CHAR_ASTERISK)
+ {
+ int newnl = 0;
+ int newbsr = 0;
+
+/* For completeness and backward compatibility, (*UTFn) is supported in the
+relevant libraries, but (*UTF) is generic and always supported. Note that
+PCRE_UTF8 == PCRE_UTF16 == PCRE_UTF32. */
+
+#ifdef COMPILE_PCRE8
+ if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF8_RIGHTPAR, 5) == 0)
+ { skipatstart += 7; options |= PCRE_UTF8; continue; }
+#endif
+#ifdef COMPILE_PCRE16
+ if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF16_RIGHTPAR, 6) == 0)
+ { skipatstart += 8; options |= PCRE_UTF16; continue; }
+#endif
+#ifdef COMPILE_PCRE32
+ if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF32_RIGHTPAR, 6) == 0)
+ { skipatstart += 8; options |= PCRE_UTF32; continue; }
+#endif
+
+ else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF_RIGHTPAR, 4) == 0)
+ { skipatstart += 6; options |= PCRE_UTF8; continue; }
+ else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UCP_RIGHTPAR, 4) == 0)
+ { skipatstart += 6; options |= PCRE_UCP; continue; }
+ else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_NO_AUTO_POSSESS_RIGHTPAR, 16) == 0)
+ { skipatstart += 18; options |= PCRE_NO_AUTO_POSSESS; continue; }
+ else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_NO_START_OPT_RIGHTPAR, 13) == 0)
+ { skipatstart += 15; options |= PCRE_NO_START_OPTIMIZE; continue; }
+
+ else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_LIMIT_MATCH_EQ, 12) == 0)
+ {
+ pcre_uint32 c = 0;
+ int p = skipatstart + 14;
+ while (isdigit(ptr[p]))
+ {
+ if (c > PCRE_UINT32_MAX / 10 - 1) break; /* Integer overflow */
+ c = c*10 + ptr[p++] - CHAR_0;
+ }
+ if (ptr[p++] != CHAR_RIGHT_PARENTHESIS) break;
+ if (c < limit_match)
+ {
+ limit_match = c;
+ cd->external_flags |= PCRE_MLSET;
+ }
+ skipatstart = p;
+ continue;
+ }
+
+ else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_LIMIT_RECURSION_EQ, 16) == 0)
+ {
+ pcre_uint32 c = 0;
+ int p = skipatstart + 18;
+ while (isdigit(ptr[p]))
+ {
+ if (c > PCRE_UINT32_MAX / 10 - 1) break; /* Integer overflow check */
+ c = c*10 + ptr[p++] - CHAR_0;
+ }
+ if (ptr[p++] != CHAR_RIGHT_PARENTHESIS) break;
+ if (c < limit_recursion)
+ {
+ limit_recursion = c;
+ cd->external_flags |= PCRE_RLSET;
+ }
+ skipatstart = p;
+ continue;
+ }
+
+ if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_CR_RIGHTPAR, 3) == 0)
+ { skipatstart += 5; newnl = PCRE_NEWLINE_CR; }
+ else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_LF_RIGHTPAR, 3) == 0)
+ { skipatstart += 5; newnl = PCRE_NEWLINE_LF; }
+ else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_CRLF_RIGHTPAR, 5) == 0)
+ { skipatstart += 7; newnl = PCRE_NEWLINE_CR + PCRE_NEWLINE_LF; }
+ else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_ANY_RIGHTPAR, 4) == 0)
+ { skipatstart += 6; newnl = PCRE_NEWLINE_ANY; }
+ else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_ANYCRLF_RIGHTPAR, 8) == 0)
+ { skipatstart += 10; newnl = PCRE_NEWLINE_ANYCRLF; }
+
+ else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_BSR_ANYCRLF_RIGHTPAR, 12) == 0)
+ { skipatstart += 14; newbsr = PCRE_BSR_ANYCRLF; }
+ else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_BSR_UNICODE_RIGHTPAR, 12) == 0)
+ { skipatstart += 14; newbsr = PCRE_BSR_UNICODE; }
+
+ if (newnl != 0)
+ options = (options & ~PCRE_NEWLINE_BITS) | newnl;
+ else if (newbsr != 0)
+ options = (options & ~(PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) | newbsr;
+ else break;
+ }
+
+/* PCRE_UTF(16|32) have the same value as PCRE_UTF8. */
+utf = (options & PCRE_UTF8) != 0;
+if (utf && never_utf)
+ {
+ errorcode = ERR78;
+ goto PCRE_EARLY_ERROR_RETURN2;
+ }
+
+/* Can't support UTF unless PCRE has been compiled to include the code. The
+return of an error code from PRIV(valid_utf)() is a new feature, introduced in
+release 8.13. It is passed back from pcre_[dfa_]exec(), but at the moment is
+not used here. */
+
+#ifdef SUPPORT_UTF
+if (utf && (options & PCRE_NO_UTF8_CHECK) == 0 &&
+ (errorcode = PRIV(valid_utf)((PCRE_PUCHAR)pattern, -1, erroroffset)) != 0)
+ {
+#if defined COMPILE_PCRE8
+ errorcode = ERR44;
+#elif defined COMPILE_PCRE16
+ errorcode = ERR74;
+#elif defined COMPILE_PCRE32
+ errorcode = ERR77;
+#endif
+ goto PCRE_EARLY_ERROR_RETURN2;
+ }
+#else
+if (utf)
+ {
+ errorcode = ERR32;
+ goto PCRE_EARLY_ERROR_RETURN;
+ }
+#endif
+
+/* Can't support UCP unless PCRE has been compiled to include the code. */
+
+#ifndef SUPPORT_UCP
+if ((options & PCRE_UCP) != 0)
+ {
+ errorcode = ERR67;
+ goto PCRE_EARLY_ERROR_RETURN;
+ }
+#endif
+
+/* Check validity of \R options. */
+
+if ((options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) ==
+ (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE))
+ {
+ errorcode = ERR56;
+ goto PCRE_EARLY_ERROR_RETURN;
+ }
+
+/* Handle different types of newline. The three bits give seven cases. The
+current code allows for fixed one- or two-byte sequences, plus "any" and
+"anycrlf". */
+
+switch (options & PCRE_NEWLINE_BITS)
+ {
+ case 0: newline = NEWLINE; break; /* Build-time default */
+ case PCRE_NEWLINE_CR: newline = CHAR_CR; break;
+ case PCRE_NEWLINE_LF: newline = CHAR_NL; break;
+ case PCRE_NEWLINE_CR+
+ PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break;
+ case PCRE_NEWLINE_ANY: newline = -1; break;
+ case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
+ default: errorcode = ERR56; goto PCRE_EARLY_ERROR_RETURN;
+ }
+
+if (newline == -2)
+ {
+ cd->nltype = NLTYPE_ANYCRLF;
+ }
+else if (newline < 0)
+ {
+ cd->nltype = NLTYPE_ANY;
+ }
+else
+ {
+ cd->nltype = NLTYPE_FIXED;
+ if (newline > 255)
+ {
+ cd->nllen = 2;
+ cd->nl[0] = (newline >> 8) & 255;
+ cd->nl[1] = newline & 255;
+ }
+ else
+ {
+ cd->nllen = 1;
+ cd->nl[0] = newline;
+ }
+ }
+
+/* Maximum back reference and backref bitmap. The bitmap records up to 31 back
+references to help in deciding whether (.*) can be treated as anchored or not.
+*/
+
+cd->top_backref = 0;
+cd->backref_map = 0;
+
+/* Reflect pattern for debugging output */
+
+DPRINTF(("------------------------------------------------------------------\n"));
+#ifdef PCRE_DEBUG
+print_puchar(stdout, (PCRE_PUCHAR)pattern);
+#endif
+DPRINTF(("\n"));
+
+/* Pretend to compile the pattern while actually just accumulating the length
+of memory required. This behaviour is triggered by passing a non-NULL final
+argument to compile_regex(). We pass a block of workspace (cworkspace) for it
+to compile parts of the pattern into; the compiled code is discarded when it is
+no longer needed, so hopefully this workspace will never overflow, though there
+is a test for its doing so. */
+
+cd->bracount = cd->final_bracount = 0;
+cd->names_found = 0;
+cd->name_entry_size = 0;
+cd->name_table = NULL;
+cd->dupnames = FALSE;
+cd->namedrefcount = 0;
+cd->start_code = cworkspace;
+cd->hwm = cworkspace;
+cd->start_workspace = cworkspace;
+cd->workspace_size = COMPILE_WORK_SIZE;
+cd->named_groups = named_groups;
+cd->named_group_list_size = NAMED_GROUP_LIST_SIZE;
+cd->start_pattern = (const pcre_uchar *)pattern;
+cd->end_pattern = (const pcre_uchar *)(pattern + STRLEN_UC((const pcre_uchar *)pattern));
+cd->req_varyopt = 0;
+cd->parens_depth = 0;
+cd->assert_depth = 0;
+cd->max_lookbehind = 0;
+cd->external_options = options;
+cd->open_caps = NULL;
+
+/* Now do the pre-compile. On error, errorcode will be set non-zero, so we
+don't need to look at the result of the function here. The initial options have
+been put into the cd block so that they can be changed if an option setting is
+found within the regex right at the beginning. Bringing initial option settings
+outside can help speed up starting point checks. */
+
+ptr += skipatstart;
+code = cworkspace;
+*code = OP_BRA;
+
+(void)compile_regex(cd->external_options, &code, &ptr, &errorcode, FALSE,
+ FALSE, 0, 0, &firstchar, &firstcharflags, &reqchar, &reqcharflags, NULL,
+ cd, &length);
+if (errorcode != 0) goto PCRE_EARLY_ERROR_RETURN;
+
+DPRINTF(("end pre-compile: length=%d workspace=%d\n", length,
+ (int)(cd->hwm - cworkspace)));
+
+if (length > MAX_PATTERN_SIZE)
+ {
+ errorcode = ERR20;
+ goto PCRE_EARLY_ERROR_RETURN;
+ }
+
+/* If there are groups with duplicate names and there are also references by
+name, we must allow for the possibility of named references to duplicated
+groups. These require an extra data item each. */
+
+if (cd->dupnames && cd->namedrefcount > 0)
+ length += cd->namedrefcount * IMM2_SIZE * sizeof(pcre_uchar);
+
+/* Compute the size of the data block for storing the compiled pattern. Integer
+overflow should no longer be possible because nowadays we limit the maximum
+value of cd->names_found and cd->name_entry_size. */
+
+size = sizeof(REAL_PCRE) +
+ (length + cd->names_found * cd->name_entry_size) * sizeof(pcre_uchar);
+
+/* Get the memory. */
+
+re = (REAL_PCRE *)(PUBL(malloc))(size);
+if (re == NULL)
+ {
+ errorcode = ERR21;
+ goto PCRE_EARLY_ERROR_RETURN;
+ }
+
+/* Put in the magic number, and save the sizes, initial options, internal
+flags, and character table pointer. NULL is used for the default character
+tables. The nullpad field is at the end; it's there to help in the case when a
+regex compiled on a system with 4-byte pointers is run on another with 8-byte
+pointers. */
+
+re->magic_number = MAGIC_NUMBER;
+re->size = (int)size;
+re->options = cd->external_options;
+re->flags = cd->external_flags;
+re->limit_match = limit_match;
+re->limit_recursion = limit_recursion;
+re->first_char = 0;
+re->req_char = 0;
+re->name_table_offset = sizeof(REAL_PCRE) / sizeof(pcre_uchar);
+re->name_entry_size = cd->name_entry_size;
+re->name_count = cd->names_found;
+re->ref_count = 0;
+re->tables = (tables == PRIV(default_tables))? NULL : tables;
+re->nullpad = NULL;
+#ifdef COMPILE_PCRE32
+re->dummy = 0;
+#else
+re->dummy1 = re->dummy2 = re->dummy3 = 0;
+#endif
+
+/* The starting points of the name/number translation table and of the code are
+passed around in the compile data block. The start/end pattern and initial
+options are already set from the pre-compile phase, as is the name_entry_size
+field. Reset the bracket count and the names_found field. Also reset the hwm
+field; this time it's used for remembering forward references to subpatterns.
+*/
+
+cd->final_bracount = cd->bracount; /* Save for checking forward references */
+cd->parens_depth = 0;
+cd->assert_depth = 0;
+cd->bracount = 0;
+cd->max_lookbehind = 0;
+cd->name_table = (pcre_uchar *)re + re->name_table_offset;
+codestart = cd->name_table + re->name_entry_size * re->name_count;
+cd->start_code = codestart;
+cd->hwm = (pcre_uchar *)(cd->start_workspace);
+cd->req_varyopt = 0;
+cd->had_accept = FALSE;
+cd->had_pruneorskip = FALSE;
+cd->check_lookbehind = FALSE;
+cd->open_caps = NULL;
+
+/* If any named groups were found, create the name/number table from the list
+created in the first pass. */
+
+if (cd->names_found > 0)
+ {
+ int i = cd->names_found;
+ named_group *ng = cd->named_groups;
+ cd->names_found = 0;
+ for (; i > 0; i--, ng++)
+ add_name(cd, ng->name, ng->length, ng->number);
+ if (cd->named_group_list_size > NAMED_GROUP_LIST_SIZE)
+ (PUBL(free))((void *)cd->named_groups);
+ }
+
+/* Set up a starting, non-extracting bracket, then compile the expression. On
+error, errorcode will be set non-zero, so we don't need to look at the result
+of the function here. */
+
+ptr = (const pcre_uchar *)pattern + skipatstart;
+code = (pcre_uchar *)codestart;
+*code = OP_BRA;
+(void)compile_regex(re->options, &code, &ptr, &errorcode, FALSE, FALSE, 0, 0,
+ &firstchar, &firstcharflags, &reqchar, &reqcharflags, NULL, cd, NULL);
+re->top_bracket = cd->bracount;
+re->top_backref = cd->top_backref;
+re->max_lookbehind = cd->max_lookbehind;
+re->flags = cd->external_flags | PCRE_MODE;
+
+if (cd->had_accept)
+ {
+ reqchar = 0; /* Must disable after (*ACCEPT) */
+ reqcharflags = REQ_NONE;
+ }
+
+/* If not reached end of pattern on success, there's an excess bracket. */
+
+if (errorcode == 0 && *ptr != CHAR_NULL) errorcode = ERR22;
+
+/* Fill in the terminating state and check for disastrous overflow, but
+if debugging, leave the test till after things are printed out. */
+
+*code++ = OP_END;
+
+#ifndef PCRE_DEBUG
+if (code - codestart > length) errorcode = ERR23;
+#endif
+
+#ifdef SUPPORT_VALGRIND
+/* If the estimated length exceeds the really used length, mark the extra
+allocated memory as unaddressable, so that any out-of-bound reads can be
+detected. */
+VALGRIND_MAKE_MEM_NOACCESS(code, (length - (code - codestart)) * sizeof(pcre_uchar));
+#endif
+
+/* Fill in any forward references that are required. There may be repeated
+references; optimize for them, as searching a large regex takes time. */
+
+if (cd->hwm > cd->start_workspace)
+ {
+ int prev_recno = -1;
+ const pcre_uchar *groupptr = NULL;
+ while (errorcode == 0 && cd->hwm > cd->start_workspace)
+ {
+ int offset, recno;
+ cd->hwm -= LINK_SIZE;
+ offset = GET(cd->hwm, 0);
+ recno = GET(codestart, offset);
+ if (recno != prev_recno)
+ {
+ groupptr = PRIV(find_bracket)(codestart, utf, recno);
+ prev_recno = recno;
+ }
+ if (groupptr == NULL) errorcode = ERR53;
+ else PUT(((pcre_uchar *)codestart), offset, (int)(groupptr - codestart));
+ }
+ }
+
+/* If the workspace had to be expanded, free the new memory. Set the pointer to
+NULL to indicate that forward references have been filled in. */
+
+if (cd->workspace_size > COMPILE_WORK_SIZE)
+ (PUBL(free))((void *)cd->start_workspace);
+cd->start_workspace = NULL;
+
+/* Give an error if there's back reference to a non-existent capturing
+subpattern. */
+
+if (errorcode == 0 && re->top_backref > re->top_bracket) errorcode = ERR15;
+
+/* Unless disabled, check whether single character iterators can be
+auto-possessified. The function overwrites the appropriate opcode values. */
+
+if ((options & PCRE_NO_AUTO_POSSESS) == 0)
+ auto_possessify((pcre_uchar *)codestart, utf, cd);
+
+/* If there were any lookbehind assertions that contained OP_RECURSE
+(recursions or subroutine calls), a flag is set for them to be checked here,
+because they may contain forward references. Actual recursions cannot be fixed
+length, but subroutine calls can. It is done like this so that those without
+OP_RECURSE that are not fixed length get a diagnosic with a useful offset. The
+exceptional ones forgo this. We scan the pattern to check that they are fixed
+length, and set their lengths. */
+
+if (cd->check_lookbehind)
+ {
+ pcre_uchar *cc = (pcre_uchar *)codestart;
+
+ /* Loop, searching for OP_REVERSE items, and process those that do not have
+ their length set. (Actually, it will also re-process any that have a length
+ of zero, but that is a pathological case, and it does no harm.) When we find
+ one, we temporarily terminate the branch it is in while we scan it. */
+
+ for (cc = (pcre_uchar *)PRIV(find_bracket)(codestart, utf, -1);
+ cc != NULL;
+ cc = (pcre_uchar *)PRIV(find_bracket)(cc, utf, -1))
+ {
+ if (GET(cc, 1) == 0)
+ {
+ int fixed_length;
+ pcre_uchar *be = cc - 1 - LINK_SIZE + GET(cc, -LINK_SIZE);
+ int end_op = *be;
+ *be = OP_END;
+ fixed_length = find_fixedlength(cc, (re->options & PCRE_UTF8) != 0, TRUE,
+ cd);
+ *be = end_op;
+ DPRINTF(("fixed length = %d\n", fixed_length));
+ if (fixed_length < 0)
+ {
+ errorcode = (fixed_length == -2)? ERR36 :
+ (fixed_length == -4)? ERR70 : ERR25;
+ break;
+ }
+ if (fixed_length > cd->max_lookbehind) cd->max_lookbehind = fixed_length;
+ PUT(cc, 1, fixed_length);
+ }
+ cc += 1 + LINK_SIZE;
+ }
+ }
+
+/* Failed to compile, or error while post-processing */
+
+if (errorcode != 0)
+ {
+ (PUBL(free))(re);
+ PCRE_EARLY_ERROR_RETURN:
+ *erroroffset = (int)(ptr - (const pcre_uchar *)pattern);
+ PCRE_EARLY_ERROR_RETURN2:
+ *errorptr = find_error_text(errorcode);
+ if (errorcodeptr != NULL) *errorcodeptr = errorcode;
+ return NULL;
+ }
+
+/* If the anchored option was not passed, set the flag if we can determine that
+the pattern is anchored by virtue of ^ characters or \A or anything else, such
+as starting with non-atomic .* when DOTALL is set and there are no occurrences
+of *PRUNE or *SKIP.
+
+Otherwise, if we know what the first byte has to be, save it, because that
+speeds up unanchored matches no end. If not, see if we can set the
+PCRE_STARTLINE flag. This is helpful for multiline matches when all branches
+start with ^. and also when all branches start with non-atomic .* for
+non-DOTALL matches when *PRUNE and SKIP are not present. */
+
+if ((re->options & PCRE_ANCHORED) == 0)
+ {
+ if (is_anchored(codestart, 0, cd, 0)) re->options |= PCRE_ANCHORED;
+ else
+ {
+ if (firstcharflags < 0)
+ firstchar = find_firstassertedchar(codestart, &firstcharflags, FALSE);
+ if (firstcharflags >= 0) /* Remove caseless flag for non-caseable chars */
+ {
+#if defined COMPILE_PCRE8
+ re->first_char = firstchar & 0xff;
+#elif defined COMPILE_PCRE16
+ re->first_char = firstchar & 0xffff;
+#elif defined COMPILE_PCRE32
+ re->first_char = firstchar;
+#endif
+ if ((firstcharflags & REQ_CASELESS) != 0)
+ {
+#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
+ /* We ignore non-ASCII first chars in 8 bit mode. */
+ if (utf)
+ {
+ if (re->first_char < 128)
+ {
+ if (cd->fcc[re->first_char] != re->first_char)
+ re->flags |= PCRE_FCH_CASELESS;
+ }
+ else if (UCD_OTHERCASE(re->first_char) != re->first_char)
+ re->flags |= PCRE_FCH_CASELESS;
+ }
+ else
+#endif
+ if (MAX_255(re->first_char)
+ && cd->fcc[re->first_char] != re->first_char)
+ re->flags |= PCRE_FCH_CASELESS;
+ }
+
+ re->flags |= PCRE_FIRSTSET;
+ }
+
+ else if (is_startline(codestart, 0, cd, 0)) re->flags |= PCRE_STARTLINE;
+ }
+ }
+
+/* For an anchored pattern, we use the "required byte" only if it follows a
+variable length item in the regex. Remove the caseless flag for non-caseable
+bytes. */
+
+if (reqcharflags >= 0 &&
+ ((re->options & PCRE_ANCHORED) == 0 || (reqcharflags & REQ_VARY) != 0))
+ {
+#if defined COMPILE_PCRE8
+ re->req_char = reqchar & 0xff;
+#elif defined COMPILE_PCRE16
+ re->req_char = reqchar & 0xffff;
+#elif defined COMPILE_PCRE32
+ re->req_char = reqchar;
+#endif
+ if ((reqcharflags & REQ_CASELESS) != 0)
+ {
+#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
+ /* We ignore non-ASCII first chars in 8 bit mode. */
+ if (utf)
+ {
+ if (re->req_char < 128)
+ {
+ if (cd->fcc[re->req_char] != re->req_char)
+ re->flags |= PCRE_RCH_CASELESS;
+ }
+ else if (UCD_OTHERCASE(re->req_char) != re->req_char)
+ re->flags |= PCRE_RCH_CASELESS;
+ }
+ else
+#endif
+ if (MAX_255(re->req_char) && cd->fcc[re->req_char] != re->req_char)
+ re->flags |= PCRE_RCH_CASELESS;
+ }
+
+ re->flags |= PCRE_REQCHSET;
+ }
+
+/* Print out the compiled data if debugging is enabled. This is never the
+case when building a production library. */
+
+#ifdef PCRE_DEBUG
+printf("Length = %d top_bracket = %d top_backref = %d\n",
+ length, re->top_bracket, re->top_backref);
+
+printf("Options=%08x\n", re->options);
+
+if ((re->flags & PCRE_FIRSTSET) != 0)
+ {
+ pcre_uchar ch = re->first_char;
+ const char *caseless =
+ ((re->flags & PCRE_FCH_CASELESS) == 0)? "" : " (caseless)";
+ if (PRINTABLE(ch)) printf("First char = %c%s\n", ch, caseless);
+ else printf("First char = \\x%02x%s\n", ch, caseless);
+ }
+
+if ((re->flags & PCRE_REQCHSET) != 0)
+ {
+ pcre_uchar ch = re->req_char;
+ const char *caseless =
+ ((re->flags & PCRE_RCH_CASELESS) == 0)? "" : " (caseless)";
+ if (PRINTABLE(ch)) printf("Req char = %c%s\n", ch, caseless);
+ else printf("Req char = \\x%02x%s\n", ch, caseless);
+ }
+
+#if defined COMPILE_PCRE8
+pcre_printint((pcre *)re, stdout, TRUE);
+#elif defined COMPILE_PCRE16
+pcre16_printint((pcre *)re, stdout, TRUE);
+#elif defined COMPILE_PCRE32
+pcre32_printint((pcre *)re, stdout, TRUE);
+#endif
+
+/* This check is done here in the debugging case so that the code that
+was compiled can be seen. */
+
+if (code - codestart > length)
+ {
+ (PUBL(free))(re);
+ *errorptr = find_error_text(ERR23);
+ *erroroffset = ptr - (pcre_uchar *)pattern;
+ if (errorcodeptr != NULL) *errorcodeptr = ERR23;
+ return NULL;
+ }
+#endif /* PCRE_DEBUG */
+
+/* Check for a pattern than can match an empty string, so that this information
+can be provided to applications. */
+
+do
+ {
+ if (could_be_empty_branch(codestart, code, utf, cd, NULL))
+ {
+ re->flags |= PCRE_MATCH_EMPTY;
+ break;
+ }
+ codestart += GET(codestart, 1);
+ }
+while (*codestart == OP_ALT);
+
+#if defined COMPILE_PCRE8
+return (pcre *)re;
+#elif defined COMPILE_PCRE16
+return (pcre16 *)re;
+#elif defined COMPILE_PCRE32
+return (pcre32 *)re;
+#endif
+}
+
+/* End of pcre_compile.c */
+
diff --git a/plugins/Pcre16/src/pcre_config.c b/plugins/Pcre16/src/pcre_config.c
new file mode 100644
index 0000000000..1cbdd9c960
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_config.c
@@ -0,0 +1,190 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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 external function pcre_config(). */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Keep the original link size. */
+static int real_link_size = LINK_SIZE;
+
+#include "pcre_internal.h"
+
+
+/*************************************************
+* Return info about what features are configured *
+*************************************************/
+
+/* This function has an extensible interface so that additional items can be
+added compatibly.
+
+Arguments:
+ what what information is required
+ where where to put the information
+
+Returns: 0 if data returned, negative on error
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_config(int what, void *where)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_config(int what, void *where)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre32_config(int what, void *where)
+#endif
+{
+switch (what)
+ {
+ case PCRE_CONFIG_UTF8:
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ *((int *)where) = 0;
+ return PCRE_ERROR_BADOPTION;
+#else
+#if defined SUPPORT_UTF
+ *((int *)where) = 1;
+#else
+ *((int *)where) = 0;
+#endif
+ break;
+#endif
+
+ case PCRE_CONFIG_UTF16:
+#if defined COMPILE_PCRE8 || defined COMPILE_PCRE32
+ *((int *)where) = 0;
+ return PCRE_ERROR_BADOPTION;
+#else
+#if defined SUPPORT_UTF
+ *((int *)where) = 1;
+#else
+ *((int *)where) = 0;
+#endif
+ break;
+#endif
+
+ case PCRE_CONFIG_UTF32:
+#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
+ *((int *)where) = 0;
+ return PCRE_ERROR_BADOPTION;
+#else
+#if defined SUPPORT_UTF
+ *((int *)where) = 1;
+#else
+ *((int *)where) = 0;
+#endif
+ break;
+#endif
+
+ case PCRE_CONFIG_UNICODE_PROPERTIES:
+#ifdef SUPPORT_UCP
+ *((int *)where) = 1;
+#else
+ *((int *)where) = 0;
+#endif
+ break;
+
+ case PCRE_CONFIG_JIT:
+#ifdef SUPPORT_JIT
+ *((int *)where) = 1;
+#else
+ *((int *)where) = 0;
+#endif
+ break;
+
+ case PCRE_CONFIG_JITTARGET:
+#ifdef SUPPORT_JIT
+ *((const char **)where) = PRIV(jit_get_target)();
+#else
+ *((const char **)where) = NULL;
+#endif
+ break;
+
+ case PCRE_CONFIG_NEWLINE:
+ *((int *)where) = NEWLINE;
+ break;
+
+ case PCRE_CONFIG_BSR:
+#ifdef BSR_ANYCRLF
+ *((int *)where) = 1;
+#else
+ *((int *)where) = 0;
+#endif
+ break;
+
+ case PCRE_CONFIG_LINK_SIZE:
+ *((int *)where) = real_link_size;
+ break;
+
+ case PCRE_CONFIG_POSIX_MALLOC_THRESHOLD:
+ *((int *)where) = POSIX_MALLOC_THRESHOLD;
+ break;
+
+ case PCRE_CONFIG_PARENS_LIMIT:
+ *((unsigned long int *)where) = PARENS_NEST_LIMIT;
+ break;
+
+ case PCRE_CONFIG_MATCH_LIMIT:
+ *((unsigned long int *)where) = MATCH_LIMIT;
+ break;
+
+ case PCRE_CONFIG_MATCH_LIMIT_RECURSION:
+ *((unsigned long int *)where) = MATCH_LIMIT_RECURSION;
+ break;
+
+ case PCRE_CONFIG_STACKRECURSE:
+#ifdef NO_RECURSE
+ *((int *)where) = 0;
+#else
+ *((int *)where) = 1;
+#endif
+ break;
+
+ default: return PCRE_ERROR_BADOPTION;
+ }
+
+return 0;
+}
+
+/* End of pcre_config.c */
diff --git a/plugins/Pcre16/src/pcre_dfa_exec.c b/plugins/Pcre16/src/pcre_dfa_exec.c
new file mode 100644
index 0000000000..fb0c7e805d
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_dfa_exec.c
@@ -0,0 +1,3673 @@
+/*************************************************
+* 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 (but see
+below for why this module is different).
+
+ Written by Philip Hazel
+ Copyright (c) 1997-2014 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 external function pcre_dfa_exec(), which is an
+alternative matching function that uses a sort of DFA algorithm (not a true
+FSM). This is NOT Perl-compatible, but it has advantages in certain
+applications. */
+
+
+/* NOTE ABOUT PERFORMANCE: A user of this function sent some code that improved
+the performance of his patterns greatly. I could not use it as it stood, as it
+was not thread safe, and made assumptions about pattern sizes. Also, it caused
+test 7 to loop, and test 9 to crash with a segfault.
+
+The issue is the check for duplicate states, which is done by a simple linear
+search up the state list. (Grep for "duplicate" below to find the code.) For
+many patterns, there will never be many states active at one time, so a simple
+linear search is fine. In patterns that have many active states, it might be a
+bottleneck. The suggested code used an indexing scheme to remember which states
+had previously been used for each character, and avoided the linear search when
+it knew there was no chance of a duplicate. This was implemented when adding
+states to the state lists.
+
+I wrote some thread-safe, not-limited code to try something similar at the time
+of checking for duplicates (instead of when adding states), using index vectors
+on the stack. It did give a 13% improvement with one specially constructed
+pattern for certain subject strings, but on other strings and on many of the
+simpler patterns in the test suite it did worse. The major problem, I think,
+was the extra time to initialize the index. This had to be done for each call
+of internal_dfa_exec(). (The supplied patch used a static vector, initialized
+only once - I suspect this was the cause of the problems with the tests.)
+
+Overall, I concluded that the gains in some cases did not outweigh the losses
+in others, so I abandoned this code. */
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define NLBLOCK md /* Block containing newline information */
+#define PSSTART start_subject /* Field containing processed string start */
+#define PSEND end_subject /* Field containing processed string end */
+
+#include "pcre_internal.h"
+
+
+/* For use to indent debugging output */
+
+#define SP " "
+
+
+/*************************************************
+* Code parameters and static tables *
+*************************************************/
+
+/* These are offsets that are used to turn the OP_TYPESTAR and friends opcodes
+into others, under special conditions. A gap of 20 between the blocks should be
+enough. The resulting opcodes don't have to be less than 256 because they are
+never stored, so we push them well clear of the normal opcodes. */
+
+#define OP_PROP_EXTRA 300
+#define OP_EXTUNI_EXTRA 320
+#define OP_ANYNL_EXTRA 340
+#define OP_HSPACE_EXTRA 360
+#define OP_VSPACE_EXTRA 380
+
+
+/* This table identifies those opcodes that are followed immediately by a
+character that is to be tested in some way. This makes it possible to
+centralize the loading of these characters. In the case of Type * etc, the
+"character" is the opcode for \D, \d, \S, \s, \W, or \w, which will always be a
+small value. Non-zero values in the table are the offsets from the opcode where
+the character is to be found. ***NOTE*** If the start of this table is
+modified, the three tables that follow must also be modified. */
+
+static const pcre_uint8 coptable[] = {
+ 0, /* End */
+ 0, 0, 0, 0, 0, /* \A, \G, \K, \B, \b */
+ 0, 0, 0, 0, 0, 0, /* \D, \d, \S, \s, \W, \w */
+ 0, 0, 0, /* Any, AllAny, Anybyte */
+ 0, 0, /* \P, \p */
+ 0, 0, 0, 0, 0, /* \R, \H, \h, \V, \v */
+ 0, /* \X */
+ 0, 0, 0, 0, 0, 0, /* \Z, \z, $, $M, ^, ^M */
+ 1, /* Char */
+ 1, /* Chari */
+ 1, /* not */
+ 1, /* noti */
+ /* Positive single-char repeats */
+ 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */
+ 1+IMM2_SIZE, 1+IMM2_SIZE, /* upto, minupto */
+ 1+IMM2_SIZE, /* exact */
+ 1, 1, 1, 1+IMM2_SIZE, /* *+, ++, ?+, upto+ */
+ 1, 1, 1, 1, 1, 1, /* *I, *?I, +I, +?I, ?I, ??I */
+ 1+IMM2_SIZE, 1+IMM2_SIZE, /* upto I, minupto I */
+ 1+IMM2_SIZE, /* exact I */
+ 1, 1, 1, 1+IMM2_SIZE, /* *+I, ++I, ?+I, upto+I */
+ /* Negative single-char repeats - only for chars < 256 */
+ 1, 1, 1, 1, 1, 1, /* NOT *, *?, +, +?, ?, ?? */
+ 1+IMM2_SIZE, 1+IMM2_SIZE, /* NOT upto, minupto */
+ 1+IMM2_SIZE, /* NOT exact */
+ 1, 1, 1, 1+IMM2_SIZE, /* NOT *+, ++, ?+, upto+ */
+ 1, 1, 1, 1, 1, 1, /* NOT *I, *?I, +I, +?I, ?I, ??I */
+ 1+IMM2_SIZE, 1+IMM2_SIZE, /* NOT upto I, minupto I */
+ 1+IMM2_SIZE, /* NOT exact I */
+ 1, 1, 1, 1+IMM2_SIZE, /* NOT *+I, ++I, ?+I, upto+I */
+ /* Positive type repeats */
+ 1, 1, 1, 1, 1, 1, /* Type *, *?, +, +?, ?, ?? */
+ 1+IMM2_SIZE, 1+IMM2_SIZE, /* Type upto, minupto */
+ 1+IMM2_SIZE, /* Type exact */
+ 1, 1, 1, 1+IMM2_SIZE, /* Type *+, ++, ?+, upto+ */
+ /* Character class & ref repeats */
+ 0, 0, 0, 0, 0, 0, /* *, *?, +, +?, ?, ?? */
+ 0, 0, /* CRRANGE, CRMINRANGE */
+ 0, 0, 0, 0, /* Possessive *+, ++, ?+, CRPOSRANGE */
+ 0, /* CLASS */
+ 0, /* NCLASS */
+ 0, /* XCLASS - variable length */
+ 0, /* REF */
+ 0, /* REFI */
+ 0, /* DNREF */
+ 0, /* DNREFI */
+ 0, /* RECURSE */
+ 0, /* CALLOUT */
+ 0, /* Alt */
+ 0, /* Ket */
+ 0, /* KetRmax */
+ 0, /* KetRmin */
+ 0, /* KetRpos */
+ 0, /* Reverse */
+ 0, /* Assert */
+ 0, /* Assert not */
+ 0, /* Assert behind */
+ 0, /* Assert behind not */
+ 0, 0, /* ONCE, ONCE_NC */
+ 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */
+ 0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */
+ 0, 0, /* CREF, DNCREF */
+ 0, 0, /* RREF, DNRREF */
+ 0, /* DEF */
+ 0, 0, 0, /* BRAZERO, BRAMINZERO, BRAPOSZERO */
+ 0, 0, 0, /* MARK, PRUNE, PRUNE_ARG */
+ 0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */
+ 0, 0, 0, 0, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */
+ 0, 0 /* CLOSE, SKIPZERO */
+};
+
+/* This table identifies those opcodes that inspect a character. It is used to
+remember the fact that a character could have been inspected when the end of
+the subject is reached. ***NOTE*** If the start of this table is modified, the
+two tables that follow must also be modified. */
+
+static const pcre_uint8 poptable[] = {
+ 0, /* End */
+ 0, 0, 0, 1, 1, /* \A, \G, \K, \B, \b */
+ 1, 1, 1, 1, 1, 1, /* \D, \d, \S, \s, \W, \w */
+ 1, 1, 1, /* Any, AllAny, Anybyte */
+ 1, 1, /* \P, \p */
+ 1, 1, 1, 1, 1, /* \R, \H, \h, \V, \v */
+ 1, /* \X */
+ 0, 0, 0, 0, 0, 0, /* \Z, \z, $, $M, ^, ^M */
+ 1, /* Char */
+ 1, /* Chari */
+ 1, /* not */
+ 1, /* noti */
+ /* Positive single-char repeats */
+ 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */
+ 1, 1, 1, /* upto, minupto, exact */
+ 1, 1, 1, 1, /* *+, ++, ?+, upto+ */
+ 1, 1, 1, 1, 1, 1, /* *I, *?I, +I, +?I, ?I, ??I */
+ 1, 1, 1, /* upto I, minupto I, exact I */
+ 1, 1, 1, 1, /* *+I, ++I, ?+I, upto+I */
+ /* Negative single-char repeats - only for chars < 256 */
+ 1, 1, 1, 1, 1, 1, /* NOT *, *?, +, +?, ?, ?? */
+ 1, 1, 1, /* NOT upto, minupto, exact */
+ 1, 1, 1, 1, /* NOT *+, ++, ?+, upto+ */
+ 1, 1, 1, 1, 1, 1, /* NOT *I, *?I, +I, +?I, ?I, ??I */
+ 1, 1, 1, /* NOT upto I, minupto I, exact I */
+ 1, 1, 1, 1, /* NOT *+I, ++I, ?+I, upto+I */
+ /* Positive type repeats */
+ 1, 1, 1, 1, 1, 1, /* Type *, *?, +, +?, ?, ?? */
+ 1, 1, 1, /* Type upto, minupto, exact */
+ 1, 1, 1, 1, /* Type *+, ++, ?+, upto+ */
+ /* Character class & ref repeats */
+ 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */
+ 1, 1, /* CRRANGE, CRMINRANGE */
+ 1, 1, 1, 1, /* Possessive *+, ++, ?+, CRPOSRANGE */
+ 1, /* CLASS */
+ 1, /* NCLASS */
+ 1, /* XCLASS - variable length */
+ 0, /* REF */
+ 0, /* REFI */
+ 0, /* DNREF */
+ 0, /* DNREFI */
+ 0, /* RECURSE */
+ 0, /* CALLOUT */
+ 0, /* Alt */
+ 0, /* Ket */
+ 0, /* KetRmax */
+ 0, /* KetRmin */
+ 0, /* KetRpos */
+ 0, /* Reverse */
+ 0, /* Assert */
+ 0, /* Assert not */
+ 0, /* Assert behind */
+ 0, /* Assert behind not */
+ 0, 0, /* ONCE, ONCE_NC */
+ 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */
+ 0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */
+ 0, 0, /* CREF, DNCREF */
+ 0, 0, /* RREF, DNRREF */
+ 0, /* DEF */
+ 0, 0, 0, /* BRAZERO, BRAMINZERO, BRAPOSZERO */
+ 0, 0, 0, /* MARK, PRUNE, PRUNE_ARG */
+ 0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */
+ 0, 0, 0, 0, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */
+ 0, 0 /* CLOSE, SKIPZERO */
+};
+
+/* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W,
+and \w */
+
+static const pcre_uint8 toptable1[] = {
+ 0, 0, 0, 0, 0, 0,
+ ctype_digit, ctype_digit,
+ ctype_space, ctype_space,
+ ctype_word, ctype_word,
+ 0, 0 /* OP_ANY, OP_ALLANY */
+};
+
+static const pcre_uint8 toptable2[] = {
+ 0, 0, 0, 0, 0, 0,
+ ctype_digit, 0,
+ ctype_space, 0,
+ ctype_word, 0,
+ 1, 1 /* OP_ANY, OP_ALLANY */
+};
+
+
+/* Structure for holding data about a particular state, which is in effect the
+current data for an active path through the match tree. It must consist
+entirely of ints because the working vector we are passed, and which we put
+these structures in, is a vector of ints. */
+
+typedef struct stateblock {
+ int offset; /* Offset to opcode */
+ int count; /* Count for repeats */
+ int data; /* Some use extra data */
+} stateblock;
+
+#define INTS_PER_STATEBLOCK (int)(sizeof(stateblock)/sizeof(int))
+
+
+#ifdef PCRE_DEBUG
+/*************************************************
+* Print character string *
+*************************************************/
+
+/* Character string printing function for debugging.
+
+Arguments:
+ p points to string
+ length number of bytes
+ f where to print
+
+Returns: nothing
+*/
+
+static void
+pchars(const pcre_uchar *p, int length, FILE *f)
+{
+pcre_uint32 c;
+while (length-- > 0)
+ {
+ if (isprint(c = *(p++)))
+ fprintf(f, "%c", c);
+ else
+ fprintf(f, "\\x{%02x}", c);
+ }
+}
+#endif
+
+
+
+/*************************************************
+* Execute a Regular Expression - DFA engine *
+*************************************************/
+
+/* This internal function applies a compiled pattern to a subject string,
+starting at a given point, using a DFA engine. This function is called from the
+external one, possibly multiple times if the pattern is not anchored. The
+function calls itself recursively for some kinds of subpattern.
+
+Arguments:
+ md the match_data block with fixed information
+ this_start_code the opening bracket of this subexpression's code
+ current_subject where we currently are in the subject string
+ start_offset start offset in the subject string
+ offsets vector to contain the matching string offsets
+ offsetcount size of same
+ workspace vector of workspace
+ wscount size of same
+ rlevel function call recursion level
+
+Returns: > 0 => number of match offset pairs placed in offsets
+ = 0 => offsets overflowed; longest matches are present
+ -1 => failed to match
+ < -1 => some kind of unexpected problem
+
+The following macros are used for adding states to the two state vectors (one
+for the current character, one for the following character). */
+
+#define ADD_ACTIVE(x,y) \
+ if (active_count++ < wscount) \
+ { \
+ next_active_state->offset = (x); \
+ next_active_state->count = (y); \
+ next_active_state++; \
+ DPRINTF(("%.*sADD_ACTIVE(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \
+ } \
+ else return PCRE_ERROR_DFA_WSSIZE
+
+#define ADD_ACTIVE_DATA(x,y,z) \
+ if (active_count++ < wscount) \
+ { \
+ next_active_state->offset = (x); \
+ next_active_state->count = (y); \
+ next_active_state->data = (z); \
+ next_active_state++; \
+ DPRINTF(("%.*sADD_ACTIVE_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \
+ } \
+ else return PCRE_ERROR_DFA_WSSIZE
+
+#define ADD_NEW(x,y) \
+ if (new_count++ < wscount) \
+ { \
+ next_new_state->offset = (x); \
+ next_new_state->count = (y); \
+ next_new_state++; \
+ DPRINTF(("%.*sADD_NEW(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \
+ } \
+ else return PCRE_ERROR_DFA_WSSIZE
+
+#define ADD_NEW_DATA(x,y,z) \
+ if (new_count++ < wscount) \
+ { \
+ next_new_state->offset = (x); \
+ next_new_state->count = (y); \
+ next_new_state->data = (z); \
+ next_new_state++; \
+ DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d) line %d\n", rlevel*2-2, SP, \
+ (x), (y), (z), __LINE__)); \
+ } \
+ else return PCRE_ERROR_DFA_WSSIZE
+
+/* And now, here is the code */
+
+static int
+internal_dfa_exec(
+ dfa_match_data *md,
+ const pcre_uchar *this_start_code,
+ const pcre_uchar *current_subject,
+ int start_offset,
+ int *offsets,
+ int offsetcount,
+ int *workspace,
+ int wscount,
+ int rlevel)
+{
+stateblock *active_states, *new_states, *temp_states;
+stateblock *next_active_state, *next_new_state;
+
+const pcre_uint8 *ctypes, *lcc, *fcc;
+const pcre_uchar *ptr;
+const pcre_uchar *end_code, *first_op;
+
+dfa_recursion_info new_recursive;
+
+int active_count, new_count, match_count;
+
+/* Some fields in the md block are frequently referenced, so we load them into
+independent variables in the hope that this will perform better. */
+
+const pcre_uchar *start_subject = md->start_subject;
+const pcre_uchar *end_subject = md->end_subject;
+const pcre_uchar *start_code = md->start_code;
+
+#ifdef SUPPORT_UTF
+BOOL utf = (md->poptions & PCRE_UTF8) != 0;
+#else
+BOOL utf = FALSE;
+#endif
+
+BOOL reset_could_continue = FALSE;
+
+rlevel++;
+offsetcount &= (-2);
+
+wscount -= 2;
+wscount = (wscount - (wscount % (INTS_PER_STATEBLOCK * 2))) /
+ (2 * INTS_PER_STATEBLOCK);
+
+DPRINTF(("\n%.*s---------------------\n"
+ "%.*sCall to internal_dfa_exec f=%d\n",
+ rlevel*2-2, SP, rlevel*2-2, SP, rlevel));
+
+ctypes = md->tables + ctypes_offset;
+lcc = md->tables + lcc_offset;
+fcc = md->tables + fcc_offset;
+
+match_count = PCRE_ERROR_NOMATCH; /* A negative number */
+
+active_states = (stateblock *)(workspace + 2);
+next_new_state = new_states = active_states + wscount;
+new_count = 0;
+
+first_op = this_start_code + 1 + LINK_SIZE +
+ ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA ||
+ *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS)
+ ? IMM2_SIZE:0);
+
+/* The first thing in any (sub) pattern is a bracket of some sort. Push all
+the alternative states onto the list, and find out where the end is. This
+makes is possible to use this function recursively, when we want to stop at a
+matching internal ket rather than at the end.
+
+If the first opcode in the first alternative is OP_REVERSE, we are dealing with
+a backward assertion. In that case, we have to find out the maximum amount to
+move back, and set up each alternative appropriately. */
+
+if (*first_op == OP_REVERSE)
+ {
+ int max_back = 0;
+ int gone_back;
+
+ end_code = this_start_code;
+ do
+ {
+ int back = GET(end_code, 2+LINK_SIZE);
+ if (back > max_back) max_back = back;
+ end_code += GET(end_code, 1);
+ }
+ while (*end_code == OP_ALT);
+
+ /* If we can't go back the amount required for the longest lookbehind
+ pattern, go back as far as we can; some alternatives may still be viable. */
+
+#ifdef SUPPORT_UTF
+ /* In character mode we have to step back character by character */
+
+ if (utf)
+ {
+ for (gone_back = 0; gone_back < max_back; gone_back++)
+ {
+ if (current_subject <= start_subject) break;
+ current_subject--;
+ ACROSSCHAR(current_subject > start_subject, *current_subject, current_subject--);
+ }
+ }
+ else
+#endif
+
+ /* In byte-mode we can do this quickly. */
+
+ {
+ gone_back = (current_subject - max_back < start_subject)?
+ (int)(current_subject - start_subject) : max_back;
+ current_subject -= gone_back;
+ }
+
+ /* Save the earliest consulted character */
+
+ if (current_subject < md->start_used_ptr)
+ md->start_used_ptr = current_subject;
+
+ /* Now we can process the individual branches. */
+
+ end_code = this_start_code;
+ do
+ {
+ int back = GET(end_code, 2+LINK_SIZE);
+ if (back <= gone_back)
+ {
+ int bstate = (int)(end_code - start_code + 2 + 2*LINK_SIZE);
+ ADD_NEW_DATA(-bstate, 0, gone_back - back);
+ }
+ end_code += GET(end_code, 1);
+ }
+ while (*end_code == OP_ALT);
+ }
+
+/* This is the code for a "normal" subpattern (not a backward assertion). The
+start of a whole pattern is always one of these. If we are at the top level,
+we may be asked to restart matching from the same point that we reached for a
+previous partial match. We still have to scan through the top-level branches to
+find the end state. */
+
+else
+ {
+ end_code = this_start_code;
+
+ /* Restarting */
+
+ if (rlevel == 1 && (md->moptions & PCRE_DFA_RESTART) != 0)
+ {
+ do { end_code += GET(end_code, 1); } while (*end_code == OP_ALT);
+ new_count = workspace[1];
+ if (!workspace[0])
+ memcpy(new_states, active_states, new_count * sizeof(stateblock));
+ }
+
+ /* Not restarting */
+
+ else
+ {
+ int length = 1 + LINK_SIZE +
+ ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA ||
+ *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS)
+ ? IMM2_SIZE:0);
+ do
+ {
+ ADD_NEW((int)(end_code - start_code + length), 0);
+ end_code += GET(end_code, 1);
+ length = 1 + LINK_SIZE;
+ }
+ while (*end_code == OP_ALT);
+ }
+ }
+
+workspace[0] = 0; /* Bit indicating which vector is current */
+
+DPRINTF(("%.*sEnd state = %d\n", rlevel*2-2, SP, (int)(end_code - start_code)));
+
+/* Loop for scanning the subject */
+
+ptr = current_subject;
+for (;;)
+ {
+ int i, j;
+ int clen, dlen;
+ pcre_uint32 c, d;
+ int forced_fail = 0;
+ BOOL partial_newline = FALSE;
+ BOOL could_continue = reset_could_continue;
+ reset_could_continue = FALSE;
+
+ /* Make the new state list into the active state list and empty the
+ new state list. */
+
+ temp_states = active_states;
+ active_states = new_states;
+ new_states = temp_states;
+ active_count = new_count;
+ new_count = 0;
+
+ workspace[0] ^= 1; /* Remember for the restarting feature */
+ workspace[1] = active_count;
+
+#ifdef PCRE_DEBUG
+ printf("%.*sNext character: rest of subject = \"", rlevel*2-2, SP);
+ pchars(ptr, STRLEN_UC(ptr), stdout);
+ printf("\"\n");
+
+ printf("%.*sActive states: ", rlevel*2-2, SP);
+ for (i = 0; i < active_count; i++)
+ printf("%d/%d ", active_states[i].offset, active_states[i].count);
+ printf("\n");
+#endif
+
+ /* Set the pointers for adding new states */
+
+ next_active_state = active_states + active_count;
+ next_new_state = new_states;
+
+ /* Load the current character from the subject outside the loop, as many
+ different states may want to look at it, and we assume that at least one
+ will. */
+
+ if (ptr < end_subject)
+ {
+ clen = 1; /* Number of data items in the character */
+#ifdef SUPPORT_UTF
+ GETCHARLENTEST(c, ptr, clen);
+#else
+ c = *ptr;
+#endif /* SUPPORT_UTF */
+ }
+ else
+ {
+ clen = 0; /* This indicates the end of the subject */
+ c = NOTACHAR; /* This value should never actually be used */
+ }
+
+ /* Scan up the active states and act on each one. The result of an action
+ may be to add more states to the currently active list (e.g. on hitting a
+ parenthesis) or it may be to put states on the new list, for considering
+ when we move the character pointer on. */
+
+ for (i = 0; i < active_count; i++)
+ {
+ stateblock *current_state = active_states + i;
+ BOOL caseless = FALSE;
+ const pcre_uchar *code;
+ int state_offset = current_state->offset;
+ int codevalue, rrc;
+ int count;
+
+#ifdef PCRE_DEBUG
+ printf ("%.*sProcessing state %d c=", rlevel*2-2, SP, state_offset);
+ if (clen == 0) printf("EOL\n");
+ else if (c > 32 && c < 127) printf("'%c'\n", c);
+ else printf("0x%02x\n", c);
+#endif
+
+ /* A negative offset is a special case meaning "hold off going to this
+ (negated) state until the number of characters in the data field have
+ been skipped". If the could_continue flag was passed over from a previous
+ state, arrange for it to passed on. */
+
+ if (state_offset < 0)
+ {
+ if (current_state->data > 0)
+ {
+ DPRINTF(("%.*sSkipping this character\n", rlevel*2-2, SP));
+ ADD_NEW_DATA(state_offset, current_state->count,
+ current_state->data - 1);
+ if (could_continue) reset_could_continue = TRUE;
+ continue;
+ }
+ else
+ {
+ current_state->offset = state_offset = -state_offset;
+ }
+ }
+
+ /* Check for a duplicate state with the same count, and skip if found.
+ See the note at the head of this module about the possibility of improving
+ performance here. */
+
+ for (j = 0; j < i; j++)
+ {
+ if (active_states[j].offset == state_offset &&
+ active_states[j].count == current_state->count)
+ {
+ DPRINTF(("%.*sDuplicate state: skipped\n", rlevel*2-2, SP));
+ goto NEXT_ACTIVE_STATE;
+ }
+ }
+
+ /* The state offset is the offset to the opcode */
+
+ code = start_code + state_offset;
+ codevalue = *code;
+
+ /* If this opcode inspects a character, but we are at the end of the
+ subject, remember the fact for use when testing for a partial match. */
+
+ if (clen == 0 && poptable[codevalue] != 0)
+ could_continue = TRUE;
+
+ /* If this opcode is followed by an inline character, load it. It is
+ tempting to test for the presence of a subject character here, but that
+ is wrong, because sometimes zero repetitions of the subject are
+ permitted.
+
+ We also use this mechanism for opcodes such as OP_TYPEPLUS that take an
+ argument that is not a data character - but is always one byte long because
+ the values are small. We have to take special action to deal with \P, \p,
+ \H, \h, \V, \v and \X in this case. To keep the other cases fast, convert
+ these ones to new opcodes. */
+
+ if (coptable[codevalue] > 0)
+ {
+ dlen = 1;
+#ifdef SUPPORT_UTF
+ if (utf) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else
+#endif /* SUPPORT_UTF */
+ d = code[coptable[codevalue]];
+ if (codevalue >= OP_TYPESTAR)
+ {
+ switch(d)
+ {
+ case OP_ANYBYTE: return PCRE_ERROR_DFA_UITEM;
+ case OP_NOTPROP:
+ case OP_PROP: codevalue += OP_PROP_EXTRA; break;
+ case OP_ANYNL: codevalue += OP_ANYNL_EXTRA; break;
+ case OP_EXTUNI: codevalue += OP_EXTUNI_EXTRA; break;
+ case OP_NOT_HSPACE:
+ case OP_HSPACE: codevalue += OP_HSPACE_EXTRA; break;
+ case OP_NOT_VSPACE:
+ case OP_VSPACE: codevalue += OP_VSPACE_EXTRA; break;
+ default: break;
+ }
+ }
+ }
+ else
+ {
+ dlen = 0; /* Not strictly necessary, but compilers moan */
+ d = NOTACHAR; /* if these variables are not set. */
+ }
+
+
+ /* Now process the individual opcodes */
+
+ switch (codevalue)
+ {
+/* ========================================================================== */
+ /* These cases are never obeyed. This is a fudge that causes a compile-
+ time error if the vectors coptable or poptable, which are indexed by
+ opcode, are not the correct length. It seems to be the only way to do
+ such a check at compile time, as the sizeof() operator does not work
+ in the C preprocessor. */
+
+ case OP_TABLE_LENGTH:
+ case OP_TABLE_LENGTH +
+ ((sizeof(coptable) == OP_TABLE_LENGTH) &&
+ (sizeof(poptable) == OP_TABLE_LENGTH)):
+ break;
+
+/* ========================================================================== */
+ /* Reached a closing bracket. If not at the end of the pattern, carry
+ on with the next opcode. For repeating opcodes, also add the repeat
+ state. Note that KETRPOS will always be encountered at the end of the
+ subpattern, because the possessive subpattern repeats are always handled
+ using recursive calls. Thus, it never adds any new states.
+
+ At the end of the (sub)pattern, unless we have an empty string and
+ PCRE_NOTEMPTY is set, or PCRE_NOTEMPTY_ATSTART is set and we are at the
+ start of the subject, save the match data, shifting up all previous
+ matches so we always have the longest first. */
+
+ case OP_KET:
+ case OP_KETRMIN:
+ case OP_KETRMAX:
+ case OP_KETRPOS:
+ if (code != end_code)
+ {
+ ADD_ACTIVE(state_offset + 1 + LINK_SIZE, 0);
+ if (codevalue != OP_KET)
+ {
+ ADD_ACTIVE(state_offset - GET(code, 1), 0);
+ }
+ }
+ else
+ {
+ if (ptr > current_subject ||
+ ((md->moptions & PCRE_NOTEMPTY) == 0 &&
+ ((md->moptions & PCRE_NOTEMPTY_ATSTART) == 0 ||
+ current_subject > start_subject + md->start_offset)))
+ {
+ if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;
+ else if (match_count > 0 && ++match_count * 2 > offsetcount)
+ match_count = 0;
+ count = ((match_count == 0)? offsetcount : match_count * 2) - 2;
+ if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int));
+ if (offsetcount >= 2)
+ {
+ offsets[0] = (int)(current_subject - start_subject);
+ offsets[1] = (int)(ptr - start_subject);
+ DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP,
+ offsets[1] - offsets[0], (char *)current_subject));
+ }
+ if ((md->moptions & PCRE_DFA_SHORTEST) != 0)
+ {
+ DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n"
+ "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel,
+ match_count, rlevel*2-2, SP));
+ return match_count;
+ }
+ }
+ }
+ break;
+
+/* ========================================================================== */
+ /* These opcodes add to the current list of states without looking
+ at the current character. */
+
+ /*-----------------------------------------------------------------*/
+ case OP_ALT:
+ do { code += GET(code, 1); } while (*code == OP_ALT);
+ ADD_ACTIVE((int)(code - start_code), 0);
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_BRA:
+ case OP_SBRA:
+ do
+ {
+ ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0);
+ code += GET(code, 1);
+ }
+ while (*code == OP_ALT);
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_CBRA:
+ case OP_SCBRA:
+ ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE + IMM2_SIZE), 0);
+ code += GET(code, 1);
+ while (*code == OP_ALT)
+ {
+ ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0);
+ code += GET(code, 1);
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_BRAZERO:
+ case OP_BRAMINZERO:
+ ADD_ACTIVE(state_offset + 1, 0);
+ code += 1 + GET(code, 2);
+ while (*code == OP_ALT) code += GET(code, 1);
+ ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0);
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_SKIPZERO:
+ code += 1 + GET(code, 2);
+ while (*code == OP_ALT) code += GET(code, 1);
+ ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0);
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_CIRC:
+ if (ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0)
+ { ADD_ACTIVE(state_offset + 1, 0); }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_CIRCM:
+ if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) ||
+ (ptr != end_subject && WAS_NEWLINE(ptr)))
+ { ADD_ACTIVE(state_offset + 1, 0); }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_EOD:
+ if (ptr >= end_subject)
+ {
+ if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
+ could_continue = TRUE;
+ else { ADD_ACTIVE(state_offset + 1, 0); }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_SOD:
+ if (ptr == start_subject) { ADD_ACTIVE(state_offset + 1, 0); }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_SOM:
+ if (ptr == start_subject + start_offset) { ADD_ACTIVE(state_offset + 1, 0); }
+ break;
+
+
+/* ========================================================================== */
+ /* These opcodes inspect the next subject character, and sometimes
+ the previous one as well, but do not have an argument. The variable
+ clen contains the length of the current character and is zero if we are
+ at the end of the subject. */
+
+ /*-----------------------------------------------------------------*/
+ case OP_ANY:
+ if (clen > 0 && !IS_NEWLINE(ptr))
+ {
+ if (ptr + 1 >= md->end_subject &&
+ (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ c == NLBLOCK->nl[0])
+ {
+ could_continue = partial_newline = TRUE;
+ }
+ else
+ {
+ ADD_NEW(state_offset + 1, 0);
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_ALLANY:
+ if (clen > 0)
+ { ADD_NEW(state_offset + 1, 0); }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_EODN:
+ if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0)
+ could_continue = TRUE;
+ else if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - md->nllen))
+ { ADD_ACTIVE(state_offset + 1, 0); }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_DOLL:
+ if ((md->moptions & PCRE_NOTEOL) == 0)
+ {
+ if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0)
+ could_continue = TRUE;
+ else if (clen == 0 ||
+ ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) &&
+ (ptr == end_subject - md->nllen)
+ ))
+ { ADD_ACTIVE(state_offset + 1, 0); }
+ else if (ptr + 1 >= md->end_subject &&
+ (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ c == NLBLOCK->nl[0])
+ {
+ if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
+ {
+ reset_could_continue = TRUE;
+ ADD_NEW_DATA(-(state_offset + 1), 0, 1);
+ }
+ else could_continue = partial_newline = TRUE;
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_DOLLM:
+ if ((md->moptions & PCRE_NOTEOL) == 0)
+ {
+ if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0)
+ could_continue = TRUE;
+ else if (clen == 0 ||
+ ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr)))
+ { ADD_ACTIVE(state_offset + 1, 0); }
+ else if (ptr + 1 >= md->end_subject &&
+ (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ c == NLBLOCK->nl[0])
+ {
+ if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
+ {
+ reset_could_continue = TRUE;
+ ADD_NEW_DATA(-(state_offset + 1), 0, 1);
+ }
+ else could_continue = partial_newline = TRUE;
+ }
+ }
+ else if (IS_NEWLINE(ptr))
+ { ADD_ACTIVE(state_offset + 1, 0); }
+ break;
+
+ /*-----------------------------------------------------------------*/
+
+ case OP_DIGIT:
+ case OP_WHITESPACE:
+ case OP_WORDCHAR:
+ if (clen > 0 && c < 256 &&
+ ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0)
+ { ADD_NEW(state_offset + 1, 0); }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_NOT_DIGIT:
+ case OP_NOT_WHITESPACE:
+ case OP_NOT_WORDCHAR:
+ if (clen > 0 && (c >= 256 ||
+ ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0))
+ { ADD_NEW(state_offset + 1, 0); }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_WORD_BOUNDARY:
+ case OP_NOT_WORD_BOUNDARY:
+ {
+ int left_word, right_word;
+
+ if (ptr > start_subject)
+ {
+ const pcre_uchar *temp = ptr - 1;
+ if (temp < md->start_used_ptr) md->start_used_ptr = temp;
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (utf) { BACKCHAR(temp); }
+#endif
+ GETCHARTEST(d, temp);
+#ifdef SUPPORT_UCP
+ if ((md->poptions & PCRE_UCP) != 0)
+ {
+ if (d == '_') left_word = TRUE; else
+ {
+ int cat = UCD_CATEGORY(d);
+ left_word = (cat == ucp_L || cat == ucp_N);
+ }
+ }
+ else
+#endif
+ left_word = d < 256 && (ctypes[d] & ctype_word) != 0;
+ }
+ else left_word = FALSE;
+
+ if (clen > 0)
+ {
+#ifdef SUPPORT_UCP
+ if ((md->poptions & PCRE_UCP) != 0)
+ {
+ if (c == '_') right_word = TRUE; else
+ {
+ int cat = UCD_CATEGORY(c);
+ right_word = (cat == ucp_L || cat == ucp_N);
+ }
+ }
+ else
+#endif
+ right_word = c < 256 && (ctypes[c] & ctype_word) != 0;
+ }
+ else right_word = FALSE;
+
+ if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY))
+ { ADD_ACTIVE(state_offset + 1, 0); }
+ }
+ break;
+
+
+ /*-----------------------------------------------------------------*/
+ /* Check the next character by Unicode property. We will get here only
+ if the support is in the binary; otherwise a compile-time error occurs.
+ */
+
+#ifdef SUPPORT_UCP
+ case OP_PROP:
+ case OP_NOTPROP:
+ if (clen > 0)
+ {
+ BOOL OK;
+ const pcre_uint32 *cp;
+ const ucd_record * prop = GET_UCD(c);
+ switch(code[1])
+ {
+ case PT_ANY:
+ OK = TRUE;
+ break;
+
+ case PT_LAMP:
+ OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
+ prop->chartype == ucp_Lt;
+ break;
+
+ case PT_GC:
+ OK = PRIV(ucp_gentype)[prop->chartype] == code[2];
+ break;
+
+ case PT_PC:
+ OK = prop->chartype == code[2];
+ break;
+
+ case PT_SC:
+ OK = prop->script == code[2];
+ break;
+
+ /* These are specials for combination cases. */
+
+ case PT_ALNUM:
+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N;
+ break;
+
+ /* Perl space used to exclude VT, but from Perl 5.18 it is included,
+ which means that Perl space and POSIX space are now identical. PCRE
+ was changed at release 8.34. */
+
+ case PT_SPACE: /* Perl space */
+ case PT_PXSPACE: /* POSIX space */
+ switch(c)
+ {
+ HSPACE_CASES:
+ VSPACE_CASES:
+ OK = TRUE;
+ break;
+
+ default:
+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z;
+ break;
+ }
+ break;
+
+ case PT_WORD:
+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
+ c == CHAR_UNDERSCORE;
+ break;
+
+ case PT_CLIST:
+ cp = PRIV(ucd_caseless_sets) + code[2];
+ for (;;)
+ {
+ if (c < *cp) { OK = FALSE; break; }
+ if (c == *cp++) { OK = TRUE; break; }
+ }
+ break;
+
+ case PT_UCNC:
+ OK = c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
+ c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
+ c >= 0xe000;
+ break;
+
+ /* Should never occur, but keep compilers from grumbling. */
+
+ default:
+ OK = codevalue != OP_PROP;
+ break;
+ }
+
+ if (OK == (codevalue == OP_PROP)) { ADD_NEW(state_offset + 3, 0); }
+ }
+ break;
+#endif
+
+
+
+/* ========================================================================== */
+ /* These opcodes likewise inspect the subject character, but have an
+ argument that is not a data character. It is one of these opcodes:
+ OP_ANY, OP_ALLANY, OP_DIGIT, OP_NOT_DIGIT, OP_WHITESPACE, OP_NOT_SPACE,
+ OP_WORDCHAR, OP_NOT_WORDCHAR. The value is loaded into d. */
+
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEPOSPLUS:
+ count = current_state->count; /* Already matched */
+ if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
+ if (clen > 0)
+ {
+ if (d == OP_ANY && ptr + 1 >= md->end_subject &&
+ (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ c == NLBLOCK->nl[0])
+ {
+ could_continue = partial_newline = TRUE;
+ }
+ else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
+ (c < 256 &&
+ (d != OP_ANY || !IS_NEWLINE(ptr)) &&
+ ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
+ {
+ if (count > 0 && codevalue == OP_TYPEPOSPLUS)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ count++;
+ ADD_NEW(state_offset, count);
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ case OP_TYPEPOSQUERY:
+ ADD_ACTIVE(state_offset + 2, 0);
+ if (clen > 0)
+ {
+ if (d == OP_ANY && ptr + 1 >= md->end_subject &&
+ (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ c == NLBLOCK->nl[0])
+ {
+ could_continue = partial_newline = TRUE;
+ }
+ else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
+ (c < 256 &&
+ (d != OP_ANY || !IS_NEWLINE(ptr)) &&
+ ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
+ {
+ if (codevalue == OP_TYPEPOSQUERY)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ ADD_NEW(state_offset + 2, 0);
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPOSSTAR:
+ ADD_ACTIVE(state_offset + 2, 0);
+ if (clen > 0)
+ {
+ if (d == OP_ANY && ptr + 1 >= md->end_subject &&
+ (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ c == NLBLOCK->nl[0])
+ {
+ could_continue = partial_newline = TRUE;
+ }
+ else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
+ (c < 256 &&
+ (d != OP_ANY || !IS_NEWLINE(ptr)) &&
+ ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
+ {
+ if (codevalue == OP_TYPEPOSSTAR)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ ADD_NEW(state_offset, 0);
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_TYPEEXACT:
+ count = current_state->count; /* Number already matched */
+ if (clen > 0)
+ {
+ if (d == OP_ANY && ptr + 1 >= md->end_subject &&
+ (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ c == NLBLOCK->nl[0])
+ {
+ could_continue = partial_newline = TRUE;
+ }
+ else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
+ (c < 256 &&
+ (d != OP_ANY || !IS_NEWLINE(ptr)) &&
+ ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
+ {
+ if (++count >= (int)GET2(code, 1))
+ { ADD_NEW(state_offset + 1 + IMM2_SIZE + 1, 0); }
+ else
+ { ADD_NEW(state_offset, count); }
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ case OP_TYPEPOSUPTO:
+ ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0);
+ count = current_state->count; /* Number already matched */
+ if (clen > 0)
+ {
+ if (d == OP_ANY && ptr + 1 >= md->end_subject &&
+ (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ c == NLBLOCK->nl[0])
+ {
+ could_continue = partial_newline = TRUE;
+ }
+ else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
+ (c < 256 &&
+ (d != OP_ANY || !IS_NEWLINE(ptr)) &&
+ ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
+ {
+ if (codevalue == OP_TYPEPOSUPTO)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ if (++count >= (int)GET2(code, 1))
+ { ADD_NEW(state_offset + 2 + IMM2_SIZE, 0); }
+ else
+ { ADD_NEW(state_offset, count); }
+ }
+ }
+ break;
+
+/* ========================================================================== */
+ /* These are virtual opcodes that are used when something like
+ OP_TYPEPLUS has OP_PROP, OP_NOTPROP, OP_ANYNL, or OP_EXTUNI as its
+ argument. It keeps the code above fast for the other cases. The argument
+ is in the d variable. */
+
+#ifdef SUPPORT_UCP
+ case OP_PROP_EXTRA + OP_TYPEPLUS:
+ case OP_PROP_EXTRA + OP_TYPEMINPLUS:
+ case OP_PROP_EXTRA + OP_TYPEPOSPLUS:
+ count = current_state->count; /* Already matched */
+ if (count > 0) { ADD_ACTIVE(state_offset + 4, 0); }
+ if (clen > 0)
+ {
+ BOOL OK;
+ const pcre_uint32 *cp;
+ const ucd_record * prop = GET_UCD(c);
+ switch(code[2])
+ {
+ case PT_ANY:
+ OK = TRUE;
+ break;
+
+ case PT_LAMP:
+ OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
+ prop->chartype == ucp_Lt;
+ break;
+
+ case PT_GC:
+ OK = PRIV(ucp_gentype)[prop->chartype] == code[3];
+ break;
+
+ case PT_PC:
+ OK = prop->chartype == code[3];
+ break;
+
+ case PT_SC:
+ OK = prop->script == code[3];
+ break;
+
+ /* These are specials for combination cases. */
+
+ case PT_ALNUM:
+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N;
+ break;
+
+ /* Perl space used to exclude VT, but from Perl 5.18 it is included,
+ which means that Perl space and POSIX space are now identical. PCRE
+ was changed at release 8.34. */
+
+ case PT_SPACE: /* Perl space */
+ case PT_PXSPACE: /* POSIX space */
+ switch(c)
+ {
+ HSPACE_CASES:
+ VSPACE_CASES:
+ OK = TRUE;
+ break;
+
+ default:
+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z;
+ break;
+ }
+ break;
+
+ case PT_WORD:
+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
+ c == CHAR_UNDERSCORE;
+ break;
+
+ case PT_CLIST:
+ cp = PRIV(ucd_caseless_sets) + code[3];
+ for (;;)
+ {
+ if (c < *cp) { OK = FALSE; break; }
+ if (c == *cp++) { OK = TRUE; break; }
+ }
+ break;
+
+ case PT_UCNC:
+ OK = c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
+ c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
+ c >= 0xe000;
+ break;
+
+ /* Should never occur, but keep compilers from grumbling. */
+
+ default:
+ OK = codevalue != OP_PROP;
+ break;
+ }
+
+ if (OK == (d == OP_PROP))
+ {
+ if (count > 0 && codevalue == OP_PROP_EXTRA + OP_TYPEPOSPLUS)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ count++;
+ ADD_NEW(state_offset, count);
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_EXTUNI_EXTRA + OP_TYPEPLUS:
+ case OP_EXTUNI_EXTRA + OP_TYPEMINPLUS:
+ case OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS:
+ count = current_state->count; /* Already matched */
+ if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
+ if (clen > 0)
+ {
+ int lgb, rgb;
+ const pcre_uchar *nptr = ptr + clen;
+ int ncount = 0;
+ if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ lgb = UCD_GRAPHBREAK(c);
+ while (nptr < end_subject)
+ {
+ dlen = 1;
+ if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
+ rgb = UCD_GRAPHBREAK(d);
+ if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
+ ncount++;
+ lgb = rgb;
+ nptr += dlen;
+ }
+ count++;
+ ADD_NEW_DATA(-state_offset, count, ncount);
+ }
+ break;
+#endif
+
+ /*-----------------------------------------------------------------*/
+ case OP_ANYNL_EXTRA + OP_TYPEPLUS:
+ case OP_ANYNL_EXTRA + OP_TYPEMINPLUS:
+ case OP_ANYNL_EXTRA + OP_TYPEPOSPLUS:
+ count = current_state->count; /* Already matched */
+ if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
+ if (clen > 0)
+ {
+ int ncount = 0;
+ switch (c)
+ {
+ case CHAR_VT:
+ case CHAR_FF:
+ case CHAR_NEL:
+#ifndef EBCDIC
+ case 0x2028:
+ case 0x2029:
+#endif /* Not EBCDIC */
+ if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
+ goto ANYNL01;
+
+ case CHAR_CR:
+ if (ptr + 1 < end_subject && UCHAR21TEST(ptr + 1) == CHAR_LF) ncount = 1;
+ /* Fall through */
+
+ ANYNL01:
+ case CHAR_LF:
+ if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ count++;
+ ADD_NEW_DATA(-state_offset, count, ncount);
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_VSPACE_EXTRA + OP_TYPEPLUS:
+ case OP_VSPACE_EXTRA + OP_TYPEMINPLUS:
+ case OP_VSPACE_EXTRA + OP_TYPEPOSPLUS:
+ count = current_state->count; /* Already matched */
+ if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
+ if (clen > 0)
+ {
+ BOOL OK;
+ switch (c)
+ {
+ VSPACE_CASES:
+ OK = TRUE;
+ break;
+
+ default:
+ OK = FALSE;
+ break;
+ }
+
+ if (OK == (d == OP_VSPACE))
+ {
+ if (count > 0 && codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSPLUS)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ count++;
+ ADD_NEW_DATA(-state_offset, count, 0);
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_HSPACE_EXTRA + OP_TYPEPLUS:
+ case OP_HSPACE_EXTRA + OP_TYPEMINPLUS:
+ case OP_HSPACE_EXTRA + OP_TYPEPOSPLUS:
+ count = current_state->count; /* Already matched */
+ if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
+ if (clen > 0)
+ {
+ BOOL OK;
+ switch (c)
+ {
+ HSPACE_CASES:
+ OK = TRUE;
+ break;
+
+ default:
+ OK = FALSE;
+ break;
+ }
+
+ if (OK == (d == OP_HSPACE))
+ {
+ if (count > 0 && codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSPLUS)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ count++;
+ ADD_NEW_DATA(-state_offset, count, 0);
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+#ifdef SUPPORT_UCP
+ case OP_PROP_EXTRA + OP_TYPEQUERY:
+ case OP_PROP_EXTRA + OP_TYPEMINQUERY:
+ case OP_PROP_EXTRA + OP_TYPEPOSQUERY:
+ count = 4;
+ goto QS1;
+
+ case OP_PROP_EXTRA + OP_TYPESTAR:
+ case OP_PROP_EXTRA + OP_TYPEMINSTAR:
+ case OP_PROP_EXTRA + OP_TYPEPOSSTAR:
+ count = 0;
+
+ QS1:
+
+ ADD_ACTIVE(state_offset + 4, 0);
+ if (clen > 0)
+ {
+ BOOL OK;
+ const pcre_uint32 *cp;
+ const ucd_record * prop = GET_UCD(c);
+ switch(code[2])
+ {
+ case PT_ANY:
+ OK = TRUE;
+ break;
+
+ case PT_LAMP:
+ OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
+ prop->chartype == ucp_Lt;
+ break;
+
+ case PT_GC:
+ OK = PRIV(ucp_gentype)[prop->chartype] == code[3];
+ break;
+
+ case PT_PC:
+ OK = prop->chartype == code[3];
+ break;
+
+ case PT_SC:
+ OK = prop->script == code[3];
+ break;
+
+ /* These are specials for combination cases. */
+
+ case PT_ALNUM:
+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N;
+ break;
+
+ /* Perl space used to exclude VT, but from Perl 5.18 it is included,
+ which means that Perl space and POSIX space are now identical. PCRE
+ was changed at release 8.34. */
+
+ case PT_SPACE: /* Perl space */
+ case PT_PXSPACE: /* POSIX space */
+ switch(c)
+ {
+ HSPACE_CASES:
+ VSPACE_CASES:
+ OK = TRUE;
+ break;
+
+ default:
+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z;
+ break;
+ }
+ break;
+
+ case PT_WORD:
+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
+ c == CHAR_UNDERSCORE;
+ break;
+
+ case PT_CLIST:
+ cp = PRIV(ucd_caseless_sets) + code[3];
+ for (;;)
+ {
+ if (c < *cp) { OK = FALSE; break; }
+ if (c == *cp++) { OK = TRUE; break; }
+ }
+ break;
+
+ case PT_UCNC:
+ OK = c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
+ c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
+ c >= 0xe000;
+ break;
+
+ /* Should never occur, but keep compilers from grumbling. */
+
+ default:
+ OK = codevalue != OP_PROP;
+ break;
+ }
+
+ if (OK == (d == OP_PROP))
+ {
+ if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSSTAR ||
+ codevalue == OP_PROP_EXTRA + OP_TYPEPOSQUERY)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ ADD_NEW(state_offset + count, 0);
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_EXTUNI_EXTRA + OP_TYPEQUERY:
+ case OP_EXTUNI_EXTRA + OP_TYPEMINQUERY:
+ case OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY:
+ count = 2;
+ goto QS2;
+
+ case OP_EXTUNI_EXTRA + OP_TYPESTAR:
+ case OP_EXTUNI_EXTRA + OP_TYPEMINSTAR:
+ case OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR:
+ count = 0;
+
+ QS2:
+
+ ADD_ACTIVE(state_offset + 2, 0);
+ if (clen > 0)
+ {
+ int lgb, rgb;
+ const pcre_uchar *nptr = ptr + clen;
+ int ncount = 0;
+ if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR ||
+ codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ lgb = UCD_GRAPHBREAK(c);
+ while (nptr < end_subject)
+ {
+ dlen = 1;
+ if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
+ rgb = UCD_GRAPHBREAK(d);
+ if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
+ ncount++;
+ lgb = rgb;
+ nptr += dlen;
+ }
+ ADD_NEW_DATA(-(state_offset + count), 0, ncount);
+ }
+ break;
+#endif
+
+ /*-----------------------------------------------------------------*/
+ case OP_ANYNL_EXTRA + OP_TYPEQUERY:
+ case OP_ANYNL_EXTRA + OP_TYPEMINQUERY:
+ case OP_ANYNL_EXTRA + OP_TYPEPOSQUERY:
+ count = 2;
+ goto QS3;
+
+ case OP_ANYNL_EXTRA + OP_TYPESTAR:
+ case OP_ANYNL_EXTRA + OP_TYPEMINSTAR:
+ case OP_ANYNL_EXTRA + OP_TYPEPOSSTAR:
+ count = 0;
+
+ QS3:
+ ADD_ACTIVE(state_offset + 2, 0);
+ if (clen > 0)
+ {
+ int ncount = 0;
+ switch (c)
+ {
+ case CHAR_VT:
+ case CHAR_FF:
+ case CHAR_NEL:
+#ifndef EBCDIC
+ case 0x2028:
+ case 0x2029:
+#endif /* Not EBCDIC */
+ if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
+ goto ANYNL02;
+
+ case CHAR_CR:
+ if (ptr + 1 < end_subject && UCHAR21TEST(ptr + 1) == CHAR_LF) ncount = 1;
+ /* Fall through */
+
+ ANYNL02:
+ case CHAR_LF:
+ if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR ||
+ codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ ADD_NEW_DATA(-(state_offset + (int)count), 0, ncount);
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_VSPACE_EXTRA + OP_TYPEQUERY:
+ case OP_VSPACE_EXTRA + OP_TYPEMINQUERY:
+ case OP_VSPACE_EXTRA + OP_TYPEPOSQUERY:
+ count = 2;
+ goto QS4;
+
+ case OP_VSPACE_EXTRA + OP_TYPESTAR:
+ case OP_VSPACE_EXTRA + OP_TYPEMINSTAR:
+ case OP_VSPACE_EXTRA + OP_TYPEPOSSTAR:
+ count = 0;
+
+ QS4:
+ ADD_ACTIVE(state_offset + 2, 0);
+ if (clen > 0)
+ {
+ BOOL OK;
+ switch (c)
+ {
+ VSPACE_CASES:
+ OK = TRUE;
+ break;
+
+ default:
+ OK = FALSE;
+ break;
+ }
+ if (OK == (d == OP_VSPACE))
+ {
+ if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSSTAR ||
+ codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSQUERY)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ ADD_NEW_DATA(-(state_offset + (int)count), 0, 0);
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_HSPACE_EXTRA + OP_TYPEQUERY:
+ case OP_HSPACE_EXTRA + OP_TYPEMINQUERY:
+ case OP_HSPACE_EXTRA + OP_TYPEPOSQUERY:
+ count = 2;
+ goto QS5;
+
+ case OP_HSPACE_EXTRA + OP_TYPESTAR:
+ case OP_HSPACE_EXTRA + OP_TYPEMINSTAR:
+ case OP_HSPACE_EXTRA + OP_TYPEPOSSTAR:
+ count = 0;
+
+ QS5:
+ ADD_ACTIVE(state_offset + 2, 0);
+ if (clen > 0)
+ {
+ BOOL OK;
+ switch (c)
+ {
+ HSPACE_CASES:
+ OK = TRUE;
+ break;
+
+ default:
+ OK = FALSE;
+ break;
+ }
+
+ if (OK == (d == OP_HSPACE))
+ {
+ if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSSTAR ||
+ codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSQUERY)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ ADD_NEW_DATA(-(state_offset + (int)count), 0, 0);
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+#ifdef SUPPORT_UCP
+ case OP_PROP_EXTRA + OP_TYPEEXACT:
+ case OP_PROP_EXTRA + OP_TYPEUPTO:
+ case OP_PROP_EXTRA + OP_TYPEMINUPTO:
+ case OP_PROP_EXTRA + OP_TYPEPOSUPTO:
+ if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT)
+ { ADD_ACTIVE(state_offset + 1 + IMM2_SIZE + 3, 0); }
+ count = current_state->count; /* Number already matched */
+ if (clen > 0)
+ {
+ BOOL OK;
+ const pcre_uint32 *cp;
+ const ucd_record * prop = GET_UCD(c);
+ switch(code[1 + IMM2_SIZE + 1])
+ {
+ case PT_ANY:
+ OK = TRUE;
+ break;
+
+ case PT_LAMP:
+ OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
+ prop->chartype == ucp_Lt;
+ break;
+
+ case PT_GC:
+ OK = PRIV(ucp_gentype)[prop->chartype] == code[1 + IMM2_SIZE + 2];
+ break;
+
+ case PT_PC:
+ OK = prop->chartype == code[1 + IMM2_SIZE + 2];
+ break;
+
+ case PT_SC:
+ OK = prop->script == code[1 + IMM2_SIZE + 2];
+ break;
+
+ /* These are specials for combination cases. */
+
+ case PT_ALNUM:
+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N;
+ break;
+
+ /* Perl space used to exclude VT, but from Perl 5.18 it is included,
+ which means that Perl space and POSIX space are now identical. PCRE
+ was changed at release 8.34. */
+
+ case PT_SPACE: /* Perl space */
+ case PT_PXSPACE: /* POSIX space */
+ switch(c)
+ {
+ HSPACE_CASES:
+ VSPACE_CASES:
+ OK = TRUE;
+ break;
+
+ default:
+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z;
+ break;
+ }
+ break;
+
+ case PT_WORD:
+ OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
+ c == CHAR_UNDERSCORE;
+ break;
+
+ case PT_CLIST:
+ cp = PRIV(ucd_caseless_sets) + code[1 + IMM2_SIZE + 2];
+ for (;;)
+ {
+ if (c < *cp) { OK = FALSE; break; }
+ if (c == *cp++) { OK = TRUE; break; }
+ }
+ break;
+
+ case PT_UCNC:
+ OK = c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
+ c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
+ c >= 0xe000;
+ break;
+
+ /* Should never occur, but keep compilers from grumbling. */
+
+ default:
+ OK = codevalue != OP_PROP;
+ break;
+ }
+
+ if (OK == (d == OP_PROP))
+ {
+ if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSUPTO)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ if (++count >= (int)GET2(code, 1))
+ { ADD_NEW(state_offset + 1 + IMM2_SIZE + 3, 0); }
+ else
+ { ADD_NEW(state_offset, count); }
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_EXTUNI_EXTRA + OP_TYPEEXACT:
+ case OP_EXTUNI_EXTRA + OP_TYPEUPTO:
+ case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO:
+ case OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO:
+ if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT)
+ { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
+ count = current_state->count; /* Number already matched */
+ if (clen > 0)
+ {
+ int lgb, rgb;
+ const pcre_uchar *nptr = ptr + clen;
+ int ncount = 0;
+ if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ lgb = UCD_GRAPHBREAK(c);
+ while (nptr < end_subject)
+ {
+ dlen = 1;
+ if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
+ rgb = UCD_GRAPHBREAK(d);
+ if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
+ ncount++;
+ lgb = rgb;
+ nptr += dlen;
+ }
+ if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0)
+ reset_could_continue = TRUE;
+ if (++count >= (int)GET2(code, 1))
+ { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); }
+ else
+ { ADD_NEW_DATA(-state_offset, count, ncount); }
+ }
+ break;
+#endif
+
+ /*-----------------------------------------------------------------*/
+ case OP_ANYNL_EXTRA + OP_TYPEEXACT:
+ case OP_ANYNL_EXTRA + OP_TYPEUPTO:
+ case OP_ANYNL_EXTRA + OP_TYPEMINUPTO:
+ case OP_ANYNL_EXTRA + OP_TYPEPOSUPTO:
+ if (codevalue != OP_ANYNL_EXTRA + OP_TYPEEXACT)
+ { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
+ count = current_state->count; /* Number already matched */
+ if (clen > 0)
+ {
+ int ncount = 0;
+ switch (c)
+ {
+ case CHAR_VT:
+ case CHAR_FF:
+ case CHAR_NEL:
+#ifndef EBCDIC
+ case 0x2028:
+ case 0x2029:
+#endif /* Not EBCDIC */
+ if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
+ goto ANYNL03;
+
+ case CHAR_CR:
+ if (ptr + 1 < end_subject && UCHAR21TEST(ptr + 1) == CHAR_LF) ncount = 1;
+ /* Fall through */
+
+ ANYNL03:
+ case CHAR_LF:
+ if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ if (++count >= (int)GET2(code, 1))
+ { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); }
+ else
+ { ADD_NEW_DATA(-state_offset, count, ncount); }
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_VSPACE_EXTRA + OP_TYPEEXACT:
+ case OP_VSPACE_EXTRA + OP_TYPEUPTO:
+ case OP_VSPACE_EXTRA + OP_TYPEMINUPTO:
+ case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO:
+ if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT)
+ { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
+ count = current_state->count; /* Number already matched */
+ if (clen > 0)
+ {
+ BOOL OK;
+ switch (c)
+ {
+ VSPACE_CASES:
+ OK = TRUE;
+ break;
+
+ default:
+ OK = FALSE;
+ }
+
+ if (OK == (d == OP_VSPACE))
+ {
+ if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSUPTO)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ if (++count >= (int)GET2(code, 1))
+ { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); }
+ else
+ { ADD_NEW_DATA(-state_offset, count, 0); }
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_HSPACE_EXTRA + OP_TYPEEXACT:
+ case OP_HSPACE_EXTRA + OP_TYPEUPTO:
+ case OP_HSPACE_EXTRA + OP_TYPEMINUPTO:
+ case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO:
+ if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT)
+ { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); }
+ count = current_state->count; /* Number already matched */
+ if (clen > 0)
+ {
+ BOOL OK;
+ switch (c)
+ {
+ HSPACE_CASES:
+ OK = TRUE;
+ break;
+
+ default:
+ OK = FALSE;
+ break;
+ }
+
+ if (OK == (d == OP_HSPACE))
+ {
+ if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSUPTO)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ if (++count >= (int)GET2(code, 1))
+ { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); }
+ else
+ { ADD_NEW_DATA(-state_offset, count, 0); }
+ }
+ }
+ break;
+
+/* ========================================================================== */
+ /* These opcodes are followed by a character that is usually compared
+ to the current subject character; it is loaded into d. We still get
+ here even if there is no subject character, because in some cases zero
+ repetitions are permitted. */
+
+ /*-----------------------------------------------------------------*/
+ case OP_CHAR:
+ if (clen > 0 && c == d) { ADD_NEW(state_offset + dlen + 1, 0); }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_CHARI:
+ if (clen == 0) break;
+
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else
+ {
+ unsigned int othercase;
+ if (c < 128)
+ othercase = fcc[c];
+ else
+ /* If we have Unicode property support, we can use it to test the
+ other case of the character. */
+#ifdef SUPPORT_UCP
+ othercase = UCD_OTHERCASE(c);
+#else
+ othercase = NOTACHAR;
+#endif
+
+ if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); }
+ }
+ }
+ else
+#endif /* SUPPORT_UTF */
+ /* Not UTF mode */
+ {
+ if (TABLE_GET(c, lcc, c) == TABLE_GET(d, lcc, d))
+ { ADD_NEW(state_offset + 2, 0); }
+ }
+ break;
+
+
+#ifdef SUPPORT_UCP
+ /*-----------------------------------------------------------------*/
+ /* This is a tricky one because it can match more than one character.
+ Find out how many characters to skip, and then set up a negative state
+ to wait for them to pass before continuing. */
+
+ case OP_EXTUNI:
+ if (clen > 0)
+ {
+ int lgb, rgb;
+ const pcre_uchar *nptr = ptr + clen;
+ int ncount = 0;
+ lgb = UCD_GRAPHBREAK(c);
+ while (nptr < end_subject)
+ {
+ dlen = 1;
+ if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
+ rgb = UCD_GRAPHBREAK(d);
+ if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
+ ncount++;
+ lgb = rgb;
+ nptr += dlen;
+ }
+ if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0)
+ reset_could_continue = TRUE;
+ ADD_NEW_DATA(-(state_offset + 1), 0, ncount);
+ }
+ break;
+#endif
+
+ /*-----------------------------------------------------------------*/
+ /* This is a tricky like EXTUNI because it too can match more than one
+ character (when CR is followed by LF). In this case, set up a negative
+ state to wait for one character to pass before continuing. */
+
+ case OP_ANYNL:
+ if (clen > 0) switch(c)
+ {
+ case CHAR_VT:
+ case CHAR_FF:
+ case CHAR_NEL:
+#ifndef EBCDIC
+ case 0x2028:
+ case 0x2029:
+#endif /* Not EBCDIC */
+ if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
+
+ case CHAR_LF:
+ ADD_NEW(state_offset + 1, 0);
+ break;
+
+ case CHAR_CR:
+ if (ptr + 1 >= end_subject)
+ {
+ ADD_NEW(state_offset + 1, 0);
+ if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
+ reset_could_continue = TRUE;
+ }
+ else if (UCHAR21TEST(ptr + 1) == CHAR_LF)
+ {
+ ADD_NEW_DATA(-(state_offset + 1), 0, 1);
+ }
+ else
+ {
+ ADD_NEW(state_offset + 1, 0);
+ }
+ break;
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_NOT_VSPACE:
+ if (clen > 0) switch(c)
+ {
+ VSPACE_CASES:
+ break;
+
+ default:
+ ADD_NEW(state_offset + 1, 0);
+ break;
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_VSPACE:
+ if (clen > 0) switch(c)
+ {
+ VSPACE_CASES:
+ ADD_NEW(state_offset + 1, 0);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_NOT_HSPACE:
+ if (clen > 0) switch(c)
+ {
+ HSPACE_CASES:
+ break;
+
+ default:
+ ADD_NEW(state_offset + 1, 0);
+ break;
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_HSPACE:
+ if (clen > 0) switch(c)
+ {
+ HSPACE_CASES:
+ ADD_NEW(state_offset + 1, 0);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ /* Match a negated single character casefully. */
+
+ case OP_NOT:
+ if (clen > 0 && c != d) { ADD_NEW(state_offset + dlen + 1, 0); }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ /* Match a negated single character caselessly. */
+
+ case OP_NOTI:
+ if (clen > 0)
+ {
+ unsigned int otherd;
+#ifdef SUPPORT_UTF
+ if (utf && d >= 128)
+ {
+#ifdef SUPPORT_UCP
+ otherd = UCD_OTHERCASE(d);
+#endif /* SUPPORT_UCP */
+ }
+ else
+#endif /* SUPPORT_UTF */
+ otherd = TABLE_GET(d, fcc, d);
+ if (c != d && c != otherd)
+ { ADD_NEW(state_offset + dlen + 1, 0); }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_PLUSI:
+ case OP_MINPLUSI:
+ case OP_POSPLUSI:
+ case OP_NOTPLUSI:
+ case OP_NOTMINPLUSI:
+ case OP_NOTPOSPLUSI:
+ caseless = TRUE;
+ codevalue -= OP_STARI - OP_STAR;
+
+ /* Fall through */
+ case OP_PLUS:
+ case OP_MINPLUS:
+ case OP_POSPLUS:
+ case OP_NOTPLUS:
+ case OP_NOTMINPLUS:
+ case OP_NOTPOSPLUS:
+ count = current_state->count; /* Already matched */
+ if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); }
+ if (clen > 0)
+ {
+ pcre_uint32 otherd = NOTACHAR;
+ if (caseless)
+ {
+#ifdef SUPPORT_UTF
+ if (utf && d >= 128)
+ {
+#ifdef SUPPORT_UCP
+ otherd = UCD_OTHERCASE(d);
+#endif /* SUPPORT_UCP */
+ }
+ else
+#endif /* SUPPORT_UTF */
+ otherd = TABLE_GET(d, fcc, d);
+ }
+ if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
+ {
+ if (count > 0 &&
+ (codevalue == OP_POSPLUS || codevalue == OP_NOTPOSPLUS))
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ count++;
+ ADD_NEW(state_offset, count);
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_QUERYI:
+ case OP_MINQUERYI:
+ case OP_POSQUERYI:
+ case OP_NOTQUERYI:
+ case OP_NOTMINQUERYI:
+ case OP_NOTPOSQUERYI:
+ caseless = TRUE;
+ codevalue -= OP_STARI - OP_STAR;
+ /* Fall through */
+ case OP_QUERY:
+ case OP_MINQUERY:
+ case OP_POSQUERY:
+ case OP_NOTQUERY:
+ case OP_NOTMINQUERY:
+ case OP_NOTPOSQUERY:
+ ADD_ACTIVE(state_offset + dlen + 1, 0);
+ if (clen > 0)
+ {
+ pcre_uint32 otherd = NOTACHAR;
+ if (caseless)
+ {
+#ifdef SUPPORT_UTF
+ if (utf && d >= 128)
+ {
+#ifdef SUPPORT_UCP
+ otherd = UCD_OTHERCASE(d);
+#endif /* SUPPORT_UCP */
+ }
+ else
+#endif /* SUPPORT_UTF */
+ otherd = TABLE_GET(d, fcc, d);
+ }
+ if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
+ {
+ if (codevalue == OP_POSQUERY || codevalue == OP_NOTPOSQUERY)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ ADD_NEW(state_offset + dlen + 1, 0);
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_STARI:
+ case OP_MINSTARI:
+ case OP_POSSTARI:
+ case OP_NOTSTARI:
+ case OP_NOTMINSTARI:
+ case OP_NOTPOSSTARI:
+ caseless = TRUE;
+ codevalue -= OP_STARI - OP_STAR;
+ /* Fall through */
+ case OP_STAR:
+ case OP_MINSTAR:
+ case OP_POSSTAR:
+ case OP_NOTSTAR:
+ case OP_NOTMINSTAR:
+ case OP_NOTPOSSTAR:
+ ADD_ACTIVE(state_offset + dlen + 1, 0);
+ if (clen > 0)
+ {
+ pcre_uint32 otherd = NOTACHAR;
+ if (caseless)
+ {
+#ifdef SUPPORT_UTF
+ if (utf && d >= 128)
+ {
+#ifdef SUPPORT_UCP
+ otherd = UCD_OTHERCASE(d);
+#endif /* SUPPORT_UCP */
+ }
+ else
+#endif /* SUPPORT_UTF */
+ otherd = TABLE_GET(d, fcc, d);
+ }
+ if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
+ {
+ if (codevalue == OP_POSSTAR || codevalue == OP_NOTPOSSTAR)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ ADD_NEW(state_offset, 0);
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_EXACTI:
+ case OP_NOTEXACTI:
+ caseless = TRUE;
+ codevalue -= OP_STARI - OP_STAR;
+ /* Fall through */
+ case OP_EXACT:
+ case OP_NOTEXACT:
+ count = current_state->count; /* Number already matched */
+ if (clen > 0)
+ {
+ pcre_uint32 otherd = NOTACHAR;
+ if (caseless)
+ {
+#ifdef SUPPORT_UTF
+ if (utf && d >= 128)
+ {
+#ifdef SUPPORT_UCP
+ otherd = UCD_OTHERCASE(d);
+#endif /* SUPPORT_UCP */
+ }
+ else
+#endif /* SUPPORT_UTF */
+ otherd = TABLE_GET(d, fcc, d);
+ }
+ if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
+ {
+ if (++count >= (int)GET2(code, 1))
+ { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); }
+ else
+ { ADD_NEW(state_offset, count); }
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_UPTOI:
+ case OP_MINUPTOI:
+ case OP_POSUPTOI:
+ case OP_NOTUPTOI:
+ case OP_NOTMINUPTOI:
+ case OP_NOTPOSUPTOI:
+ caseless = TRUE;
+ codevalue -= OP_STARI - OP_STAR;
+ /* Fall through */
+ case OP_UPTO:
+ case OP_MINUPTO:
+ case OP_POSUPTO:
+ case OP_NOTUPTO:
+ case OP_NOTMINUPTO:
+ case OP_NOTPOSUPTO:
+ ADD_ACTIVE(state_offset + dlen + 1 + IMM2_SIZE, 0);
+ count = current_state->count; /* Number already matched */
+ if (clen > 0)
+ {
+ pcre_uint32 otherd = NOTACHAR;
+ if (caseless)
+ {
+#ifdef SUPPORT_UTF
+ if (utf && d >= 128)
+ {
+#ifdef SUPPORT_UCP
+ otherd = UCD_OTHERCASE(d);
+#endif /* SUPPORT_UCP */
+ }
+ else
+#endif /* SUPPORT_UTF */
+ otherd = TABLE_GET(d, fcc, d);
+ }
+ if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
+ {
+ if (codevalue == OP_POSUPTO || codevalue == OP_NOTPOSUPTO)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ if (++count >= (int)GET2(code, 1))
+ { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); }
+ else
+ { ADD_NEW(state_offset, count); }
+ }
+ }
+ break;
+
+
+/* ========================================================================== */
+ /* These are the class-handling opcodes */
+
+ case OP_CLASS:
+ case OP_NCLASS:
+ case OP_XCLASS:
+ {
+ BOOL isinclass = FALSE;
+ int next_state_offset;
+ const pcre_uchar *ecode;
+
+ /* For a simple class, there is always just a 32-byte table, and we
+ can set isinclass from it. */
+
+ if (codevalue != OP_XCLASS)
+ {
+ ecode = code + 1 + (32 / sizeof(pcre_uchar));
+ if (clen > 0)
+ {
+ isinclass = (c > 255)? (codevalue == OP_NCLASS) :
+ ((((pcre_uint8 *)(code + 1))[c/8] & (1 << (c&7))) != 0);
+ }
+ }
+
+ /* An extended class may have a table or a list of single characters,
+ ranges, or both, and it may be positive or negative. There's a
+ function that sorts all this out. */
+
+ else
+ {
+ ecode = code + GET(code, 1);
+ if (clen > 0) isinclass = PRIV(xclass)(c, code + 1 + LINK_SIZE, utf);
+ }
+
+ /* At this point, isinclass is set for all kinds of class, and ecode
+ points to the byte after the end of the class. If there is a
+ quantifier, this is where it will be. */
+
+ next_state_offset = (int)(ecode - start_code);
+
+ switch (*ecode)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRPOSSTAR:
+ ADD_ACTIVE(next_state_offset + 1, 0);
+ if (isinclass)
+ {
+ if (*ecode == OP_CRPOSSTAR)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ ADD_NEW(state_offset, 0);
+ }
+ break;
+
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ case OP_CRPOSPLUS:
+ count = current_state->count; /* Already matched */
+ if (count > 0) { ADD_ACTIVE(next_state_offset + 1, 0); }
+ if (isinclass)
+ {
+ if (count > 0 && *ecode == OP_CRPOSPLUS)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ count++;
+ ADD_NEW(state_offset, count);
+ }
+ break;
+
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ case OP_CRPOSQUERY:
+ ADD_ACTIVE(next_state_offset + 1, 0);
+ if (isinclass)
+ {
+ if (*ecode == OP_CRPOSQUERY)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ ADD_NEW(next_state_offset + 1, 0);
+ }
+ break;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ case OP_CRPOSRANGE:
+ count = current_state->count; /* Already matched */
+ if (count >= (int)GET2(ecode, 1))
+ { ADD_ACTIVE(next_state_offset + 1 + 2 * IMM2_SIZE, 0); }
+ if (isinclass)
+ {
+ int max = (int)GET2(ecode, 1 + IMM2_SIZE);
+ if (*ecode == OP_CRPOSRANGE)
+ {
+ active_count--; /* Remove non-match possibility */
+ next_active_state--;
+ }
+ if (++count >= max && max != 0) /* Max 0 => no limit */
+ { ADD_NEW(next_state_offset + 1 + 2 * IMM2_SIZE, 0); }
+ else
+ { ADD_NEW(state_offset, count); }
+ }
+ break;
+
+ default:
+ if (isinclass) { ADD_NEW(next_state_offset, 0); }
+ break;
+ }
+ }
+ break;
+
+/* ========================================================================== */
+ /* These are the opcodes for fancy brackets of various kinds. We have
+ to use recursion in order to handle them. The "always failing" assertion
+ (?!) is optimised to OP_FAIL when compiling, so we have to support that,
+ though the other "backtracking verbs" are not supported. */
+
+ case OP_FAIL:
+ forced_fail++; /* Count FAILs for multiple states */
+ break;
+
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ {
+ int rc;
+ int local_offsets[2];
+ int local_workspace[1000];
+ const pcre_uchar *endasscode = code + GET(code, 1);
+
+ while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);
+
+ rc = internal_dfa_exec(
+ md, /* static match data */
+ code, /* this subexpression's code */
+ ptr, /* where we currently are */
+ (int)(ptr - start_subject), /* start offset */
+ local_offsets, /* offset vector */
+ sizeof(local_offsets)/sizeof(int), /* size of same */
+ local_workspace, /* workspace vector */
+ sizeof(local_workspace)/sizeof(int), /* size of same */
+ rlevel); /* function recursion level */
+
+ if (rc == PCRE_ERROR_DFA_UITEM) return rc;
+ if ((rc >= 0) == (codevalue == OP_ASSERT || codevalue == OP_ASSERTBACK))
+ { ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_COND:
+ case OP_SCOND:
+ {
+ int local_offsets[1000];
+ int local_workspace[1000];
+ int codelink = GET(code, 1);
+ int condcode;
+
+ /* Because of the way auto-callout works during compile, a callout item
+ is inserted between OP_COND and an assertion condition. This does not
+ happen for the other conditions. */
+
+ if (code[LINK_SIZE+1] == OP_CALLOUT)
+ {
+ rrc = 0;
+ if (PUBL(callout) != NULL)
+ {
+ PUBL(callout_block) cb;
+ cb.version = 1; /* Version 1 of the callout block */
+ cb.callout_number = code[LINK_SIZE+2];
+ cb.offset_vector = offsets;
+#if defined COMPILE_PCRE8
+ cb.subject = (PCRE_SPTR)start_subject;
+#elif defined COMPILE_PCRE16
+ cb.subject = (PCRE_SPTR16)start_subject;
+#elif defined COMPILE_PCRE32
+ cb.subject = (PCRE_SPTR32)start_subject;
+#endif
+ cb.subject_length = (int)(end_subject - start_subject);
+ cb.start_match = (int)(current_subject - start_subject);
+ cb.current_position = (int)(ptr - start_subject);
+ cb.pattern_position = GET(code, LINK_SIZE + 3);
+ cb.next_item_length = GET(code, 3 + 2*LINK_SIZE);
+ cb.capture_top = 1;
+ cb.capture_last = -1;
+ cb.callout_data = md->callout_data;
+ cb.mark = NULL; /* No (*MARK) support */
+ if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc; /* Abandon */
+ }
+ if (rrc > 0) break; /* Fail this thread */
+ code += PRIV(OP_lengths)[OP_CALLOUT]; /* Skip callout data */
+ }
+
+ condcode = code[LINK_SIZE+1];
+
+ /* Back reference conditions and duplicate named recursion conditions
+ are not supported */
+
+ if (condcode == OP_CREF || condcode == OP_DNCREF ||
+ condcode == OP_DNRREF)
+ return PCRE_ERROR_DFA_UCOND;
+
+ /* The DEFINE condition is always false */
+
+ if (condcode == OP_DEF)
+ { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 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
+ recursed groups. */
+
+ else if (condcode == OP_RREF)
+ {
+ int value = GET2(code, LINK_SIZE + 2);
+ if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;
+ if (md->recursive != NULL)
+ { ADD_ACTIVE(state_offset + LINK_SIZE + 2 + IMM2_SIZE, 0); }
+ else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
+ }
+
+ /* Otherwise, the condition is an assertion */
+
+ else
+ {
+ int rc;
+ const pcre_uchar *asscode = code + LINK_SIZE + 1;
+ const pcre_uchar *endasscode = asscode + GET(asscode, 1);
+
+ while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);
+
+ rc = internal_dfa_exec(
+ md, /* fixed match data */
+ asscode, /* this subexpression's code */
+ ptr, /* where we currently are */
+ (int)(ptr - start_subject), /* start offset */
+ local_offsets, /* offset vector */
+ sizeof(local_offsets)/sizeof(int), /* size of same */
+ local_workspace, /* workspace vector */
+ sizeof(local_workspace)/sizeof(int), /* size of same */
+ rlevel); /* function recursion level */
+
+ if (rc == PCRE_ERROR_DFA_UITEM) return rc;
+ if ((rc >= 0) ==
+ (condcode == OP_ASSERT || condcode == OP_ASSERTBACK))
+ { ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); }
+ else
+ { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_RECURSE:
+ {
+ dfa_recursion_info *ri;
+ int local_offsets[1000];
+ int local_workspace[1000];
+ const pcre_uchar *callpat = start_code + GET(code, 1);
+ int recno = (callpat == md->start_code)? 0 :
+ GET2(callpat, 1 + LINK_SIZE);
+ int rc;
+
+ DPRINTF(("%.*sStarting regex recursion\n", rlevel*2-2, SP));
+
+ /* Check for repeating a recursion without advancing the subject
+ pointer. This should catch convoluted mutual recursions. (Some simple
+ cases are caught at compile time.) */
+
+ for (ri = md->recursive; ri != NULL; ri = ri->prevrec)
+ if (recno == ri->group_num && ptr == ri->subject_position)
+ return PCRE_ERROR_RECURSELOOP;
+
+ /* Remember this recursion and where we started it so as to
+ catch infinite loops. */
+
+ new_recursive.group_num = recno;
+ new_recursive.subject_position = ptr;
+ new_recursive.prevrec = md->recursive;
+ md->recursive = &new_recursive;
+
+ rc = internal_dfa_exec(
+ md, /* fixed match data */
+ callpat, /* this subexpression's code */
+ ptr, /* where we currently are */
+ (int)(ptr - start_subject), /* start offset */
+ local_offsets, /* offset vector */
+ sizeof(local_offsets)/sizeof(int), /* size of same */
+ local_workspace, /* workspace vector */
+ sizeof(local_workspace)/sizeof(int), /* size of same */
+ rlevel); /* function recursion level */
+
+ md->recursive = new_recursive.prevrec; /* Done this recursion */
+
+ DPRINTF(("%.*sReturn from regex recursion: rc=%d\n", rlevel*2-2, SP,
+ rc));
+
+ /* Ran out of internal offsets */
+
+ if (rc == 0) return PCRE_ERROR_DFA_RECURSE;
+
+ /* For each successful matched substring, set up the next state with a
+ count of characters to skip before trying it. Note that the count is in
+ characters, not bytes. */
+
+ if (rc > 0)
+ {
+ for (rc = rc*2 - 2; rc >= 0; rc -= 2)
+ {
+ int charcount = local_offsets[rc+1] - local_offsets[rc];
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (utf)
+ {
+ const pcre_uchar *p = start_subject + local_offsets[rc];
+ const pcre_uchar *pp = start_subject + local_offsets[rc+1];
+ while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
+ }
+#endif
+ if (charcount > 0)
+ {
+ ADD_NEW_DATA(-(state_offset + LINK_SIZE + 1), 0, (charcount - 1));
+ }
+ else
+ {
+ ADD_ACTIVE(state_offset + LINK_SIZE + 1, 0);
+ }
+ }
+ }
+ else if (rc != PCRE_ERROR_NOMATCH) return rc;
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_BRAPOS:
+ case OP_SBRAPOS:
+ case OP_CBRAPOS:
+ case OP_SCBRAPOS:
+ case OP_BRAPOSZERO:
+ {
+ int charcount, matched_count;
+ const pcre_uchar *local_ptr = ptr;
+ BOOL allow_zero;
+
+ if (codevalue == OP_BRAPOSZERO)
+ {
+ allow_zero = TRUE;
+ codevalue = *(++code); /* Codevalue will be one of above BRAs */
+ }
+ else allow_zero = FALSE;
+
+ /* Loop to match the subpattern as many times as possible as if it were
+ a complete pattern. */
+
+ for (matched_count = 0;; matched_count++)
+ {
+ int local_offsets[2];
+ int local_workspace[1000];
+
+ int rc = internal_dfa_exec(
+ md, /* fixed match data */
+ code, /* this subexpression's code */
+ local_ptr, /* where we currently are */
+ (int)(ptr - start_subject), /* start offset */
+ local_offsets, /* offset vector */
+ sizeof(local_offsets)/sizeof(int), /* size of same */
+ local_workspace, /* workspace vector */
+ sizeof(local_workspace)/sizeof(int), /* size of same */
+ rlevel); /* function recursion level */
+
+ /* Failed to match */
+
+ if (rc < 0)
+ {
+ if (rc != PCRE_ERROR_NOMATCH) return rc;
+ break;
+ }
+
+ /* Matched: break the loop if zero characters matched. */
+
+ charcount = local_offsets[1] - local_offsets[0];
+ if (charcount == 0) break;
+ local_ptr += charcount; /* Advance temporary position ptr */
+ }
+
+ /* At this point we have matched the subpattern matched_count
+ times, and local_ptr is pointing to the character after the end of the
+ last match. */
+
+ if (matched_count > 0 || allow_zero)
+ {
+ const pcre_uchar *end_subpattern = code;
+ int next_state_offset;
+
+ do { end_subpattern += GET(end_subpattern, 1); }
+ while (*end_subpattern == OP_ALT);
+ next_state_offset =
+ (int)(end_subpattern - start_code + LINK_SIZE + 1);
+
+ /* Optimization: if there are no more active states, and there
+ are no new states yet set up, then skip over the subject string
+ right here, to save looping. Otherwise, set up the new state to swing
+ into action when the end of the matched substring is reached. */
+
+ if (i + 1 >= active_count && new_count == 0)
+ {
+ ptr = local_ptr;
+ clen = 0;
+ ADD_NEW(next_state_offset, 0);
+ }
+ else
+ {
+ const pcre_uchar *p = ptr;
+ const pcre_uchar *pp = local_ptr;
+ charcount = (int)(pp - p);
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (utf) while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
+#endif
+ ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1));
+ }
+ }
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ {
+ int local_offsets[2];
+ int local_workspace[1000];
+
+ int rc = internal_dfa_exec(
+ md, /* fixed match data */
+ code, /* this subexpression's code */
+ ptr, /* where we currently are */
+ (int)(ptr - start_subject), /* start offset */
+ local_offsets, /* offset vector */
+ sizeof(local_offsets)/sizeof(int), /* size of same */
+ local_workspace, /* workspace vector */
+ sizeof(local_workspace)/sizeof(int), /* size of same */
+ rlevel); /* function recursion level */
+
+ if (rc >= 0)
+ {
+ const pcre_uchar *end_subpattern = code;
+ int charcount = local_offsets[1] - local_offsets[0];
+ int next_state_offset, repeat_state_offset;
+
+ do { end_subpattern += GET(end_subpattern, 1); }
+ while (*end_subpattern == OP_ALT);
+ next_state_offset =
+ (int)(end_subpattern - start_code + LINK_SIZE + 1);
+
+ /* If the end of this subpattern is KETRMAX or KETRMIN, we must
+ arrange for the repeat state also to be added to the relevant list.
+ Calculate the offset, or set -1 for no repeat. */
+
+ repeat_state_offset = (*end_subpattern == OP_KETRMAX ||
+ *end_subpattern == OP_KETRMIN)?
+ (int)(end_subpattern - start_code - GET(end_subpattern, 1)) : -1;
+
+ /* If we have matched an empty string, add the next state at the
+ current character pointer. This is important so that the duplicate
+ checking kicks in, which is what breaks infinite loops that match an
+ empty string. */
+
+ if (charcount == 0)
+ {
+ ADD_ACTIVE(next_state_offset, 0);
+ }
+
+ /* Optimization: if there are no more active states, and there
+ are no new states yet set up, then skip over the subject string
+ right here, to save looping. Otherwise, set up the new state to swing
+ into action when the end of the matched substring is reached. */
+
+ else if (i + 1 >= active_count && new_count == 0)
+ {
+ ptr += charcount;
+ clen = 0;
+ ADD_NEW(next_state_offset, 0);
+
+ /* If we are adding a repeat state at the new character position,
+ we must fudge things so that it is the only current state.
+ Otherwise, it might be a duplicate of one we processed before, and
+ that would cause it to be skipped. */
+
+ if (repeat_state_offset >= 0)
+ {
+ next_active_state = active_states;
+ active_count = 0;
+ i = -1;
+ ADD_ACTIVE(repeat_state_offset, 0);
+ }
+ }
+ else
+ {
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (utf)
+ {
+ const pcre_uchar *p = start_subject + local_offsets[0];
+ const pcre_uchar *pp = start_subject + local_offsets[1];
+ while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
+ }
+#endif
+ ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1));
+ if (repeat_state_offset >= 0)
+ { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); }
+ }
+ }
+ else if (rc != PCRE_ERROR_NOMATCH) return rc;
+ }
+ break;
+
+
+/* ========================================================================== */
+ /* Handle callouts */
+
+ case OP_CALLOUT:
+ rrc = 0;
+ if (PUBL(callout) != NULL)
+ {
+ PUBL(callout_block) cb;
+ cb.version = 1; /* Version 1 of the callout block */
+ cb.callout_number = code[1];
+ cb.offset_vector = offsets;
+#if defined COMPILE_PCRE8
+ cb.subject = (PCRE_SPTR)start_subject;
+#elif defined COMPILE_PCRE16
+ cb.subject = (PCRE_SPTR16)start_subject;
+#elif defined COMPILE_PCRE32
+ cb.subject = (PCRE_SPTR32)start_subject;
+#endif
+ cb.subject_length = (int)(end_subject - start_subject);
+ cb.start_match = (int)(current_subject - start_subject);
+ cb.current_position = (int)(ptr - start_subject);
+ cb.pattern_position = GET(code, 2);
+ cb.next_item_length = GET(code, 2 + LINK_SIZE);
+ cb.capture_top = 1;
+ cb.capture_last = -1;
+ cb.callout_data = md->callout_data;
+ cb.mark = NULL; /* No (*MARK) support */
+ if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc; /* Abandon */
+ }
+ if (rrc == 0)
+ { ADD_ACTIVE(state_offset + PRIV(OP_lengths)[OP_CALLOUT], 0); }
+ break;
+
+
+/* ========================================================================== */
+ default: /* Unsupported opcode */
+ return PCRE_ERROR_DFA_UITEM;
+ }
+
+ NEXT_ACTIVE_STATE: continue;
+
+ } /* End of loop scanning active states */
+
+ /* 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.
+
+ The "forced_ fail" variable counts the number of (*F) encountered for the
+ character. If it is equal to the original active_count (saved in
+ workspace[1]) it means that (*F) was found on every active state. In this
+ case we don't want to give a partial match.
+
+ The "could_continue" variable is true if a state could have continued but
+ for the fact that the end of the subject was reached. */
+
+ if (new_count <= 0)
+ {
+ if (rlevel == 1 && /* Top level, and */
+ could_continue && /* Some could go on, and */
+ forced_fail != workspace[1] && /* Not all forced fail & */
+ ( /* either... */
+ (md->moptions & PCRE_PARTIAL_HARD) != 0 /* Hard partial */
+ || /* or... */
+ ((md->moptions & PCRE_PARTIAL_SOFT) != 0 && /* Soft partial and */
+ match_count < 0) /* no matches */
+ ) && /* And... */
+ (
+ partial_newline || /* Either partial NL */
+ ( /* or ... */
+ ptr >= end_subject && /* End of subject and */
+ ptr > md->start_used_ptr) /* Inspected non-empty string */
+ )
+ )
+ match_count = PCRE_ERROR_PARTIAL;
+ DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n"
+ "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel, match_count,
+ rlevel*2-2, SP));
+ break; /* In effect, "return", but see the comment below */
+ }
+
+ /* One or more states are active for the next character. */
+
+ ptr += clen; /* Advance to next subject character */
+ } /* Loop to move along the subject string */
+
+/* Control gets here from "break" a few lines above. We do it this way because
+if we use "return" above, we have compiler trouble. Some compilers warn if
+there's nothing here because they think the function doesn't return a value. On
+the other hand, if we put a dummy statement here, some more clever compilers
+complain that it can't be reached. Sigh. */
+
+return match_count;
+}
+
+
+
+
+/*************************************************
+* Execute a Regular Expression - DFA engine *
+*************************************************/
+
+/* This external function applies a compiled re to a subject string using a DFA
+engine. This function calls the internal function multiple times if the pattern
+is not anchored.
+
+Arguments:
+ argument_re points to the compiled expression
+ extra_data points to extra data or is NULL
+ subject points to the subject string
+ length length of subject string (may contain binary zeros)
+ start_offset where to start in the subject string
+ options option bits
+ offsets vector of match offsets
+ offsetcount size of same
+ workspace workspace vector
+ wscount size of same
+
+Returns: > 0 => number of match offset pairs placed in offsets
+ = 0 => offsets overflowed; longest matches are present
+ -1 => failed to match
+ < -1 => some kind of unexpected problem
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data,
+ const char *subject, int length, int start_offset, int options, int *offsets,
+ int offsetcount, int *workspace, int wscount)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_dfa_exec(const pcre16 *argument_re, const pcre16_extra *extra_data,
+ PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets,
+ int offsetcount, int *workspace, int wscount)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre32_dfa_exec(const pcre32 *argument_re, const pcre32_extra *extra_data,
+ PCRE_SPTR32 subject, int length, int start_offset, int options, int *offsets,
+ int offsetcount, int *workspace, int wscount)
+#endif
+{
+REAL_PCRE *re = (REAL_PCRE *)argument_re;
+dfa_match_data match_block;
+dfa_match_data *md = &match_block;
+BOOL utf, anchored, startline, firstline;
+const pcre_uchar *current_subject, *end_subject;
+const pcre_study_data *study = NULL;
+
+const pcre_uchar *req_char_ptr;
+const pcre_uint8 *start_bits = NULL;
+BOOL has_first_char = FALSE;
+BOOL has_req_char = FALSE;
+pcre_uchar first_char = 0;
+pcre_uchar first_char2 = 0;
+pcre_uchar req_char = 0;
+pcre_uchar req_char2 = 0;
+int newline;
+
+/* Plausibility checks */
+
+if ((options & ~PUBLIC_DFA_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
+if (re == NULL || subject == NULL || workspace == NULL ||
+ (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;
+if (offsetcount < 0) return PCRE_ERROR_BADCOUNT;
+if (wscount < 20) return PCRE_ERROR_DFA_WSSIZE;
+if (length < 0) return PCRE_ERROR_BADLENGTH;
+if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET;
+
+/* Check that the first field in the block is the magic number. If it is not,
+return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to
+REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which
+means that the pattern is likely compiled with different endianness. */
+
+if (re->magic_number != MAGIC_NUMBER)
+ return re->magic_number == REVERSED_MAGIC_NUMBER?
+ PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC;
+if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
+
+/* If restarting after a partial match, do some sanity checks on the contents
+of the workspace. */
+
+if ((options & PCRE_DFA_RESTART) != 0)
+ {
+ if ((workspace[0] & (-2)) != 0 || workspace[1] < 1 ||
+ workspace[1] > (wscount - 2)/INTS_PER_STATEBLOCK)
+ return PCRE_ERROR_DFA_BADRESTART;
+ }
+
+/* Set up study, callout, and table data */
+
+md->tables = re->tables;
+md->callout_data = NULL;
+
+if (extra_data != NULL)
+ {
+ unsigned int flags = extra_data->flags;
+ if ((flags & PCRE_EXTRA_STUDY_DATA) != 0)
+ study = (const pcre_study_data *)extra_data->study_data;
+ if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) return PCRE_ERROR_DFA_UMLIMIT;
+ if ((flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION) != 0)
+ return PCRE_ERROR_DFA_UMLIMIT;
+ if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0)
+ md->callout_data = extra_data->callout_data;
+ if ((flags & PCRE_EXTRA_TABLES) != 0)
+ md->tables = extra_data->tables;
+ }
+
+/* Set some local values */
+
+current_subject = (const pcre_uchar *)subject + start_offset;
+end_subject = (const pcre_uchar *)subject + length;
+req_char_ptr = current_subject - 1;
+
+#ifdef SUPPORT_UTF
+/* PCRE_UTF(16|32) have the same value as PCRE_UTF8. */
+utf = (re->options & PCRE_UTF8) != 0;
+#else
+utf = FALSE;
+#endif
+
+anchored = (options & (PCRE_ANCHORED|PCRE_DFA_RESTART)) != 0 ||
+ (re->options & PCRE_ANCHORED) != 0;
+
+/* The remaining fixed data for passing around. */
+
+md->start_code = (const pcre_uchar *)argument_re +
+ re->name_table_offset + re->name_count * re->name_entry_size;
+md->start_subject = (const pcre_uchar *)subject;
+md->end_subject = end_subject;
+md->start_offset = start_offset;
+md->moptions = options;
+md->poptions = re->options;
+
+/* If the BSR option is not set at match time, copy what was set
+at compile time. */
+
+if ((md->moptions & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) == 0)
+ {
+ if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0)
+ md->moptions |= re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE);
+#ifdef BSR_ANYCRLF
+ else md->moptions |= PCRE_BSR_ANYCRLF;
+#endif
+ }
+
+/* Handle different types of newline. The three bits give eight cases. If
+nothing is set at run time, whatever was used at compile time applies. */
+
+switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : (pcre_uint32)options) &
+ PCRE_NEWLINE_BITS)
+ {
+ case 0: newline = NEWLINE; break; /* Compile-time default */
+ case PCRE_NEWLINE_CR: newline = CHAR_CR; break;
+ case PCRE_NEWLINE_LF: newline = CHAR_NL; break;
+ case PCRE_NEWLINE_CR+
+ PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break;
+ case PCRE_NEWLINE_ANY: newline = -1; break;
+ case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
+ default: return PCRE_ERROR_BADNEWLINE;
+ }
+
+if (newline == -2)
+ {
+ md->nltype = NLTYPE_ANYCRLF;
+ }
+else if (newline < 0)
+ {
+ md->nltype = NLTYPE_ANY;
+ }
+else
+ {
+ md->nltype = NLTYPE_FIXED;
+ if (newline > 255)
+ {
+ md->nllen = 2;
+ md->nl[0] = (newline >> 8) & 255;
+ md->nl[1] = newline & 255;
+ }
+ else
+ {
+ md->nllen = 1;
+ md->nl[0] = newline;
+ }
+ }
+
+/* Check a UTF-8 string if required. Unfortunately there's no way of passing
+back the character offset. */
+
+#ifdef SUPPORT_UTF
+if (utf && (options & PCRE_NO_UTF8_CHECK) == 0)
+ {
+ int erroroffset;
+ int errorcode = PRIV(valid_utf)((pcre_uchar *)subject, length, &erroroffset);
+ if (errorcode != 0)
+ {
+ if (offsetcount >= 2)
+ {
+ offsets[0] = erroroffset;
+ offsets[1] = errorcode;
+ }
+#if defined COMPILE_PCRE8
+ return (errorcode <= PCRE_UTF8_ERR5 && (options & PCRE_PARTIAL_HARD) != 0) ?
+ PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8;
+#elif defined COMPILE_PCRE16
+ return (errorcode <= PCRE_UTF16_ERR1 && (options & PCRE_PARTIAL_HARD) != 0) ?
+ PCRE_ERROR_SHORTUTF16 : PCRE_ERROR_BADUTF16;
+#elif defined COMPILE_PCRE32
+ return PCRE_ERROR_BADUTF32;
+#endif
+ }
+#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
+ if (start_offset > 0 && start_offset < length &&
+ NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset]))
+ return PCRE_ERROR_BADUTF8_OFFSET;
+#endif
+ }
+#endif
+
+/* If the exec call supplied NULL for tables, use the inbuilt ones. This
+is a feature that makes it possible to save compiled regex and re-use them
+in other programs later. */
+
+if (md->tables == NULL) md->tables = PRIV(default_tables);
+
+/* The "must be at the start of a line" flags are used in a loop when finding
+where to start. */
+
+startline = (re->flags & PCRE_STARTLINE) != 0;
+firstline = (re->options & PCRE_FIRSTLINE) != 0;
+
+/* Set up the first character to match, if available. The first_byte value is
+never set for an anchored regular expression, but the anchoring may be forced
+at run time, so we have to test for anchoring. The first char may be unset for
+an unanchored pattern, of course. If there's no first char and the pattern was
+studied, there may be a bitmap of possible first characters. */
+
+if (!anchored)
+ {
+ if ((re->flags & PCRE_FIRSTSET) != 0)
+ {
+ has_first_char = TRUE;
+ first_char = first_char2 = (pcre_uchar)(re->first_char);
+ if ((re->flags & PCRE_FCH_CASELESS) != 0)
+ {
+ first_char2 = TABLE_GET(first_char, md->tables + fcc_offset, first_char);
+#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
+ if (utf && first_char > 127)
+ first_char2 = UCD_OTHERCASE(first_char);
+#endif
+ }
+ }
+ else
+ {
+ if (!startline && study != NULL &&
+ (study->flags & PCRE_STUDY_MAPPED) != 0)
+ start_bits = study->start_bits;
+ }
+ }
+
+/* For anchored or unanchored matches, there may be a "last known required
+character" set. */
+
+if ((re->flags & PCRE_REQCHSET) != 0)
+ {
+ has_req_char = TRUE;
+ req_char = req_char2 = (pcre_uchar)(re->req_char);
+ if ((re->flags & PCRE_RCH_CASELESS) != 0)
+ {
+ req_char2 = TABLE_GET(req_char, md->tables + fcc_offset, req_char);
+#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
+ if (utf && req_char > 127)
+ req_char2 = UCD_OTHERCASE(req_char);
+#endif
+ }
+ }
+
+/* Call the main matching function, looping for a non-anchored regex after a
+failed match. If not restarting, perform certain optimizations at the start of
+a match. */
+
+for (;;)
+ {
+ int rc;
+
+ if ((options & PCRE_DFA_RESTART) == 0)
+ {
+ const pcre_uchar *save_end_subject = end_subject;
+
+ /* If firstline is TRUE, the start of the match is constrained to the first
+ line of a multiline string. Implement this by temporarily adjusting
+ end_subject so that we stop scanning at a newline. If the match fails at
+ the newline, later code breaks this loop. */
+
+ if (firstline)
+ {
+ PCRE_PUCHAR t = current_subject;
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ while (t < md->end_subject && !IS_NEWLINE(t))
+ {
+ t++;
+ ACROSSCHAR(t < end_subject, *t, t++);
+ }
+ }
+ else
+#endif
+ while (t < md->end_subject && !IS_NEWLINE(t)) t++;
+ end_subject = t;
+ }
+
+ /* There are some optimizations that avoid running the match if a known
+ starting point is not found. However, there is an option that disables
+ these, for testing and for ensuring that all callouts do actually occur.
+ The option can be set in the regex by (*NO_START_OPT) or passed in
+ match-time options. */
+
+ if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)
+ {
+ /* Advance to a known first pcre_uchar (i.e. data item) */
+
+ if (has_first_char)
+ {
+ if (first_char != first_char2)
+ {
+ pcre_uchar csc;
+ while (current_subject < end_subject &&
+ (csc = UCHAR21TEST(current_subject)) != first_char && csc != first_char2)
+ current_subject++;
+ }
+ else
+ while (current_subject < end_subject &&
+ UCHAR21TEST(current_subject) != first_char)
+ current_subject++;
+ }
+
+ /* Or to just after a linebreak for a multiline match if possible */
+
+ else if (startline)
+ {
+ if (current_subject > md->start_subject + start_offset)
+ {
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ while (current_subject < end_subject &&
+ !WAS_NEWLINE(current_subject))
+ {
+ current_subject++;
+ ACROSSCHAR(current_subject < end_subject, *current_subject,
+ current_subject++);
+ }
+ }
+ else
+#endif
+ while (current_subject < end_subject && !WAS_NEWLINE(current_subject))
+ current_subject++;
+
+ /* If we have just passed a CR and the newline option is ANY or
+ ANYCRLF, and we are now at a LF, advance the match position by one
+ more character. */
+
+ if (UCHAR21TEST(current_subject - 1) == CHAR_CR &&
+ (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
+ current_subject < end_subject &&
+ UCHAR21TEST(current_subject) == CHAR_NL)
+ current_subject++;
+ }
+ }
+
+ /* Advance to a non-unique first pcre_uchar after study */
+
+ else if (start_bits != NULL)
+ {
+ while (current_subject < end_subject)
+ {
+ register pcre_uint32 c = UCHAR21TEST(current_subject);
+#ifndef COMPILE_PCRE8
+ if (c > 255) c = 255;
+#endif
+ if ((start_bits[c/8] & (1 << (c&7))) != 0) break;
+ current_subject++;
+ }
+ }
+ }
+
+ /* Restore fudged end_subject */
+
+ end_subject = save_end_subject;
+
+ /* The following two optimizations are disabled for partial matching or if
+ disabling is explicitly requested (and of course, by the test above, this
+ code is not obeyed when restarting after a partial match). */
+
+ if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0 &&
+ (options & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) == 0)
+ {
+ /* If the pattern was studied, a minimum subject length may be set. This
+ 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
+ in pcre_uchar units to avoid spending too much time in this optimization.
+ */
+
+ if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 &&
+ (pcre_uint32)(end_subject - current_subject) < study->minlength)
+ return PCRE_ERROR_NOMATCH;
+
+ /* If req_char is set, we know that that pcre_uchar must appear in the
+ subject for the match to succeed. If the first pcre_uchar is set,
+ req_char must be later in the subject; otherwise the test starts at the
+ match point. This optimization can save a huge amount of work 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.
+
+ 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 /^C/ on a 32-megabyte
+ string... so we don't do this when the string is sufficiently long. */
+
+ if (has_req_char && end_subject - current_subject < REQ_BYTE_MAX)
+ {
+ register PCRE_PUCHAR p = current_subject + (has_first_char? 1:0);
+
+ /* We don't need to repeat the search if we haven't yet reached the
+ place we found it at last time. */
+
+ if (p > req_char_ptr)
+ {
+ if (req_char != req_char2)
+ {
+ while (p < end_subject)
+ {
+ register pcre_uint32 pp = UCHAR21INCTEST(p);
+ if (pp == req_char || pp == req_char2) { p--; break; }
+ }
+ }
+ else
+ {
+ while (p < end_subject)
+ {
+ if (UCHAR21INCTEST(p) == req_char) { p--; break; }
+ }
+ }
+
+ /* If we can't find the required pcre_uchar, break the matching loop,
+ which will cause a return or PCRE_ERROR_NOMATCH. */
+
+ if (p >= end_subject) break;
+
+ /* If we have found the required pcre_uchar, save the point where we
+ found it, so that we don't search again next time round the loop if
+ the start hasn't passed this point yet. */
+
+ req_char_ptr = p;
+ }
+ }
+ }
+ } /* End of optimizations that are done when not restarting */
+
+ /* OK, now we can do the business */
+
+ md->start_used_ptr = current_subject;
+ md->recursive = NULL;
+
+ rc = internal_dfa_exec(
+ md, /* fixed match data */
+ md->start_code, /* this subexpression's code */
+ current_subject, /* where we currently are */
+ start_offset, /* start offset in subject */
+ offsets, /* offset vector */
+ offsetcount, /* size of same */
+ workspace, /* workspace vector */
+ wscount, /* size of same */
+ 0); /* function recurse level */
+
+ /* Anything other than "no match" means we are done, always; otherwise, carry
+ on only if not anchored. */
+
+ if (rc != PCRE_ERROR_NOMATCH || anchored)
+ {
+ if (rc == PCRE_ERROR_PARTIAL && offsetcount >= 2)
+ {
+ offsets[0] = (int)(md->start_used_ptr - (PCRE_PUCHAR)subject);
+ offsets[1] = (int)(end_subject - (PCRE_PUCHAR)subject);
+ if (offsetcount > 2)
+ offsets[2] = (int)(current_subject - (PCRE_PUCHAR)subject);
+ }
+ return rc;
+ }
+
+ /* Advance to the next subject character unless we are at the end of a line
+ and firstline is set. */
+
+ if (firstline && IS_NEWLINE(current_subject)) break;
+ current_subject++;
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ ACROSSCHAR(current_subject < end_subject, *current_subject,
+ current_subject++);
+ }
+#endif
+ if (current_subject > end_subject) break;
+
+ /* If we have just passed a CR and we are now at a LF, and the pattern does
+ not contain any explicit matches for \r or \n, and the newline option is CRLF
+ or ANY or ANYCRLF, advance the match position by one more character. */
+
+ if (UCHAR21TEST(current_subject - 1) == CHAR_CR &&
+ current_subject < end_subject &&
+ UCHAR21TEST(current_subject) == CHAR_NL &&
+ (re->flags & PCRE_HASCRORLF) == 0 &&
+ (md->nltype == NLTYPE_ANY ||
+ md->nltype == NLTYPE_ANYCRLF ||
+ md->nllen == 2))
+ current_subject++;
+
+ } /* "Bumpalong" loop */
+
+return PCRE_ERROR_NOMATCH;
+}
+
+/* End of pcre_dfa_exec.c */
diff --git a/plugins/Pcre16/src/pcre_exec.c b/plugins/Pcre16/src/pcre_exec.c
new file mode 100644
index 0000000000..5dec99234a
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_exec.c
@@ -0,0 +1,7178 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2014 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 pcre_exec(), the externally visible function that does
+pattern matching using an NFA algorithm, trying to mimic Perl as closely as
+possible. There are also some static supporting functions. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define NLBLOCK md /* Block containing newline information */
+#define PSSTART start_subject /* Field containing processed string start */
+#define PSEND end_subject /* Field containing processed string end */
+
+#include "pcre_internal.h"
+
+/* Undefine some potentially clashing cpp symbols */
+
+#undef min
+#undef max
+
+/* The md->capture_last field uses the lower 16 bits for the last captured
+substring (which can never be greater than 65535) and a bit in the top half
+to mean "capture vector overflowed". This odd way of doing things was
+implemented when it was realized that preserving and restoring the overflow bit
+whenever the last capture number was saved/restored made for a neater
+interface, and doing it this way saved on (a) another variable, which would
+have increased the stack frame size (a big NO-NO in PCRE) and (b) another
+separate set of save/restore instructions. The following defines are used in
+implementing this. */
+
+#define CAPLMASK 0x0000ffff /* The bits used for last_capture */
+#define OVFLMASK 0xffff0000 /* The bits used for the overflow flag */
+#define OVFLBIT 0x00010000 /* The bit that is set for overflow */
+
+/* Values for setting in md->match_function_type to indicate two special types
+of call to match(). We do it this way to save on using another stack variable,
+as stack usage is to be discouraged. */
+
+#define MATCH_CONDASSERT 1 /* Called to check a condition assertion */
+#define MATCH_CBEGROUP 2 /* Could-be-empty unlimited repeat group */
+
+/* Non-error returns from the match() function. Error returns are externally
+defined PCRE_ERROR_xxx codes, which are all negative. */
+
+#define MATCH_MATCH 1
+#define MATCH_NOMATCH 0
+
+/* Special internal returns from the match() function. Make them sufficiently
+negative to avoid the external error codes. */
+
+#define MATCH_ACCEPT (-999)
+#define MATCH_KETRPOS (-998)
+#define MATCH_ONCE (-997)
+/* The next 5 must be kept together and in sequence so that a test that checks
+for any one of them can use a range. */
+#define MATCH_COMMIT (-996)
+#define MATCH_PRUNE (-995)
+#define MATCH_SKIP (-994)
+#define MATCH_SKIP_ARG (-993)
+#define MATCH_THEN (-992)
+#define MATCH_BACKTRACK_MAX MATCH_THEN
+#define MATCH_BACKTRACK_MIN MATCH_COMMIT
+
+/* Maximum number of ints of offset to save on the stack for recursive calls.
+If the offset vector is bigger, malloc is used. This should be a multiple of 3,
+because the offset vector is always a multiple of 3 long. */
+
+#define REC_STACK_SAVE_MAX 30
+
+/* Min and max values for the common repeats; for the maxima, 0 => infinity */
+
+static const char rep_min[] = { 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, };
+static const char rep_max[] = { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, };
+
+#ifdef PCRE_DEBUG
+/*************************************************
+* Debugging function to print chars *
+*************************************************/
+
+/* Print a sequence of chars in printable format, stopping at the end of the
+subject if the requested.
+
+Arguments:
+ p points to characters
+ length number to print
+ is_subject TRUE if printing from within md->start_subject
+ md pointer to matching data block, if is_subject is TRUE
+
+Returns: nothing
+*/
+
+static void
+pchars(const pcre_uchar *p, int length, BOOL is_subject, match_data *md)
+{
+pcre_uint32 c;
+BOOL utf = md->utf;
+if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
+while (length-- > 0)
+ if (isprint(c = UCHAR21INCTEST(p))) printf("%c", (char)c); else printf("\\x{%02x}", c);
+}
+#endif
+
+
+
+/*************************************************
+* Match a back-reference *
+*************************************************/
+
+/* Normally, if a back reference hasn't been set, the length that is passed is
+negative, so the match always fails. However, in JavaScript compatibility mode,
+the length passed is zero. Note that in caseless UTF-8 mode, the number of
+subject bytes matched may be different to the number of reference bytes.
+
+Arguments:
+ offset index into the offset vector
+ eptr pointer into the subject
+ length length of reference to be matched (number of bytes)
+ md points to match data block
+ caseless TRUE if caseless
+
+Returns: >= 0 the number of subject bytes matched
+ -1 no match
+ -2 partial match; always given if at end subject
+*/
+
+static int
+match_ref(int offset, register PCRE_PUCHAR eptr, int length, match_data *md,
+ BOOL caseless)
+{
+PCRE_PUCHAR eptr_start = eptr;
+register PCRE_PUCHAR p = md->start_subject + md->offset_vector[offset];
+#if defined SUPPORT_UTF && defined SUPPORT_UCP
+BOOL utf = md->utf;
+#endif
+
+#ifdef PCRE_DEBUG
+if (eptr >= md->end_subject)
+ printf("matching subject <null>");
+else
+ {
+ printf("matching subject ");
+ pchars(eptr, length, TRUE, md);
+ }
+printf(" against backref ");
+pchars(p, length, FALSE, md);
+printf("\n");
+#endif
+
+/* Always fail if reference not set (and not JavaScript compatible - in that
+case the length is passed as zero). */
+
+if (length < 0) return -1;
+
+/* Separate the caseless case for speed. In UTF-8 mode we can only do this
+properly if Unicode properties are supported. Otherwise, we can check only
+ASCII characters. */
+
+if (caseless)
+ {
+#if defined SUPPORT_UTF && defined SUPPORT_UCP
+ if (utf)
+ {
+ /* Match characters up to the end of the reference. NOTE: the number of
+ data units matched may differ, because in UTF-8 there are some characters
+ whose upper and lower case versions code have different numbers of bytes.
+ For example, U+023A (2 bytes in UTF-8) is the upper case version of U+2C65
+ (3 bytes in UTF-8); a sequence of 3 of the former uses 6 bytes, as does a
+ sequence of two of the latter. It is important, therefore, to check the
+ length along the reference, not along the subject (earlier code did this
+ wrong). */
+
+ PCRE_PUCHAR endptr = p + length;
+ while (p < endptr)
+ {
+ pcre_uint32 c, d;
+ const ucd_record *ur;
+ if (eptr >= md->end_subject) return -2; /* Partial match */
+ GETCHARINC(c, eptr);
+ GETCHARINC(d, p);
+ ur = GET_UCD(d);
+ if (c != d && c != d + ur->other_case)
+ {
+ const pcre_uint32 *pp = PRIV(ucd_caseless_sets) + ur->caseset;
+ for (;;)
+ {
+ if (c < *pp) return -1;
+ if (c == *pp++) break;
+ }
+ }
+ }
+ }
+ else
+#endif
+
+ /* The same code works when not in UTF-8 mode and in UTF-8 mode when there
+ is no UCP support. */
+ {
+ while (length-- > 0)
+ {
+ pcre_uint32 cc, cp;
+ if (eptr >= md->end_subject) return -2; /* Partial match */
+ cc = UCHAR21TEST(eptr);
+ cp = UCHAR21TEST(p);
+ if (TABLE_GET(cp, md->lcc, cp) != TABLE_GET(cc, md->lcc, cc)) return -1;
+ p++;
+ eptr++;
+ }
+ }
+ }
+
+/* In the caseful case, we can just compare the bytes, whether or not we
+are in UTF-8 mode. */
+
+else
+ {
+ while (length-- > 0)
+ {
+ if (eptr >= md->end_subject) return -2; /* Partial match */
+ if (UCHAR21INCTEST(p) != UCHAR21INCTEST(eptr)) return -1;
+ }
+ }
+
+return (int)(eptr - eptr_start);
+}
+
+
+
+/***************************************************************************
+****************************************************************************
+ RECURSION IN THE match() FUNCTION
+
+The match() function is highly recursive, though not every recursive call
+increases the recursive depth. Nevertheless, some regular expressions can cause
+it to recurse to a great depth. I was writing for Unix, so I just let it call
+itself recursively. This uses the stack for saving everything that has to be
+saved for a recursive call. On Unix, the stack can be large, and this works
+fine.
+
+It turns out that on some non-Unix-like systems there are problems with
+programs that use a lot of stack. (This despite the fact that every last chip
+has oodles of memory these days, and techniques for extending the stack have
+been known for decades.) So....
+
+There is a fudge, triggered by defining NO_RECURSE, which avoids recursive
+calls by keeping local variables that need to be preserved in blocks of memory
+obtained from malloc() instead instead of on the stack. Macros are used to
+achieve this so that the actual code doesn't look very different to what it
+always used to.
+
+The original heap-recursive code used longjmp(). However, it seems that this
+can be very slow on some operating systems. Following a suggestion from Stan
+Switzer, the use of longjmp() has been abolished, at the cost of having to
+provide a unique number for each call to RMATCH. There is no way of generating
+a sequence of numbers at compile time in C. I have given them names, to make
+them stand out more clearly.
+
+Crude tests on x86 Linux show a small speedup of around 5-8%. However, on
+FreeBSD, avoiding longjmp() more than halves the time taken to run the standard
+tests. Furthermore, not using longjmp() means that local dynamic variables
+don't have indeterminate values; this has meant that the frame size can be
+reduced because the result can be "passed back" by straight setting of the
+variable instead of being passed in the frame.
+****************************************************************************
+***************************************************************************/
+
+/* Numbers for RMATCH calls. When this list is changed, the code at HEAP_RETURN
+below must be updated in sync. */
+
+enum { RM1=1, RM2, RM3, RM4, RM5, RM6, RM7, RM8, RM9, RM10,
+ RM11, RM12, RM13, RM14, RM15, RM16, RM17, RM18, RM19, RM20,
+ RM21, RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30,
+ RM31, RM32, RM33, RM34, RM35, RM36, RM37, RM38, RM39, RM40,
+ RM41, RM42, RM43, RM44, RM45, RM46, RM47, RM48, RM49, RM50,
+ RM51, RM52, RM53, RM54, RM55, RM56, RM57, RM58, RM59, RM60,
+ RM61, RM62, RM63, RM64, RM65, RM66, RM67 };
+
+/* These versions of the macros use the stack, as normal. There are debugging
+versions and production versions. Note that the "rw" argument of RMATCH isn't
+actually used in this definition. */
+
+#ifndef NO_RECURSE
+#define REGISTER register
+
+#ifdef PCRE_DEBUG
+#define RMATCH(ra,rb,rc,rd,re,rw) \
+ { \
+ printf("match() called in line %d\n", __LINE__); \
+ rrc = match(ra,rb,mstart,rc,rd,re,rdepth+1); \
+ printf("to line %d\n", __LINE__); \
+ }
+#define RRETURN(ra) \
+ { \
+ printf("match() returned %d from line %d\n", ra, __LINE__); \
+ return ra; \
+ }
+#else
+#define RMATCH(ra,rb,rc,rd,re,rw) \
+ rrc = match(ra,rb,mstart,rc,rd,re,rdepth+1)
+#define RRETURN(ra) return ra
+#endif
+
+#else
+
+
+/* These versions of the macros manage a private stack on the heap. Note that
+the "rd" argument of RMATCH isn't actually used in this definition. It's the md
+argument of match(), which never changes. */
+
+#define REGISTER
+
+#define RMATCH(ra,rb,rc,rd,re,rw)\
+ {\
+ heapframe *newframe = frame->Xnextframe;\
+ if (newframe == NULL)\
+ {\
+ newframe = (heapframe *)(PUBL(stack_malloc))(sizeof(heapframe));\
+ if (newframe == NULL) RRETURN(PCRE_ERROR_NOMEMORY);\
+ newframe->Xnextframe = NULL;\
+ frame->Xnextframe = newframe;\
+ }\
+ frame->Xwhere = rw;\
+ newframe->Xeptr = ra;\
+ newframe->Xecode = rb;\
+ newframe->Xmstart = mstart;\
+ newframe->Xoffset_top = rc;\
+ newframe->Xeptrb = re;\
+ newframe->Xrdepth = frame->Xrdepth + 1;\
+ newframe->Xprevframe = frame;\
+ frame = newframe;\
+ DPRINTF(("restarting from line %d\n", __LINE__));\
+ goto HEAP_RECURSE;\
+ L_##rw:\
+ DPRINTF(("jumped back to line %d\n", __LINE__));\
+ }
+
+#define RRETURN(ra)\
+ {\
+ heapframe *oldframe = frame;\
+ frame = oldframe->Xprevframe;\
+ if (frame != NULL)\
+ {\
+ rrc = ra;\
+ goto HEAP_RETURN;\
+ }\
+ return ra;\
+ }
+
+
+/* Structure for remembering the local variables in a private frame */
+
+typedef struct heapframe {
+ struct heapframe *Xprevframe;
+ struct heapframe *Xnextframe;
+
+ /* Function arguments that may change */
+
+ PCRE_PUCHAR Xeptr;
+ const pcre_uchar *Xecode;
+ PCRE_PUCHAR Xmstart;
+ int Xoffset_top;
+ eptrblock *Xeptrb;
+ unsigned int Xrdepth;
+
+ /* Function local variables */
+
+ PCRE_PUCHAR Xcallpat;
+#ifdef SUPPORT_UTF
+ PCRE_PUCHAR Xcharptr;
+#endif
+ PCRE_PUCHAR Xdata;
+ PCRE_PUCHAR Xnext;
+ PCRE_PUCHAR Xpp;
+ PCRE_PUCHAR Xprev;
+ PCRE_PUCHAR Xsaved_eptr;
+
+ recursion_info Xnew_recursive;
+
+ BOOL Xcur_is_word;
+ BOOL Xcondition;
+ BOOL Xprev_is_word;
+
+#ifdef SUPPORT_UCP
+ int Xprop_type;
+ unsigned int Xprop_value;
+ int Xprop_fail_result;
+ int Xoclength;
+ pcre_uchar Xocchars[6];
+#endif
+
+ int Xcodelink;
+ int Xctype;
+ unsigned int Xfc;
+ int Xfi;
+ int Xlength;
+ int Xmax;
+ int Xmin;
+ unsigned int Xnumber;
+ int Xoffset;
+ unsigned int Xop;
+ pcre_int32 Xsave_capture_last;
+ int Xsave_offset1, Xsave_offset2, Xsave_offset3;
+ int Xstacksave[REC_STACK_SAVE_MAX];
+
+ eptrblock Xnewptrb;
+
+ /* Where to jump back to */
+
+ int Xwhere;
+
+} heapframe;
+
+#endif
+
+
+/***************************************************************************
+***************************************************************************/
+
+
+
+/*************************************************
+* Match from current position *
+*************************************************/
+
+/* This function is called recursively in many circumstances. Whenever it
+returns a negative (error) response, the outer incarnation must also return the
+same response. */
+
+/* These macros pack up tests that are used for partial matching, and which
+appear 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 start of the subject (i.e.
+something has been matched). 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. */
+
+#define CHECK_PARTIAL()\
+ if (md->partial != 0 && eptr >= md->end_subject && \
+ eptr > md->start_used_ptr) \
+ { \
+ md->hitend = TRUE; \
+ if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); \
+ }
+
+#define SCHECK_PARTIAL()\
+ if (md->partial != 0 && eptr > md->start_used_ptr) \
+ { \
+ md->hitend = TRUE; \
+ if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); \
+ }
+
+
+/* Performance note: It might be tempting to extract commonly used fields from
+the md structure (e.g. utf, end_subject) into individual variables to improve
+performance. Tests using gcc on a SPARC disproved this; in the first case, it
+made performance worse.
+
+Arguments:
+ eptr pointer to current character in subject
+ ecode pointer to current position in compiled code
+ mstart pointer to the current match start position (can be modified
+ by encountering \K)
+ offset_top current top pointer
+ md pointer to "static" info for the match
+ eptrb pointer to chain of blocks containing eptr at start of
+ brackets - for testing for empty matches
+ rdepth the recursion depth
+
+Returns: MATCH_MATCH if matched ) these values are >= 0
+ MATCH_NOMATCH if failed to match )
+ a negative MATCH_xxx value for PRUNE, SKIP, etc
+ a negative PCRE_ERROR_xxx value if aborted by an error condition
+ (e.g. stopped by repeated call or recursion limit)
+*/
+
+static int
+match(REGISTER PCRE_PUCHAR eptr, REGISTER const pcre_uchar *ecode,
+ PCRE_PUCHAR mstart, int offset_top, match_data *md, eptrblock *eptrb,
+ unsigned int rdepth)
+{
+/* These variables do not need to be preserved over recursion in this function,
+so they can be ordinary variables in all cases. Mark some of them with
+"register" because they are used a lot in loops. */
+
+register int rrc; /* Returns from recursive calls */
+register int i; /* Used for loops not involving calls to RMATCH() */
+register pcre_uint32 c; /* Character values not kept over RMATCH() calls */
+register BOOL utf; /* Local copy of UTF flag for speed */
+
+BOOL minimize, possessive; /* Quantifier options */
+BOOL caseless;
+int condcode;
+
+/* When recursion is not being used, all "local" variables that have to be
+preserved over calls to RMATCH() are part of a "frame". We set up the top-level
+frame on the stack here; subsequent instantiations are obtained from the heap
+whenever RMATCH() does a "recursion". See the macro definitions above. Putting
+the top-level on the stack rather than malloc-ing them all gives a performance
+boost in many cases where there is not much "recursion". */
+
+#ifdef NO_RECURSE
+heapframe *frame = (heapframe *)md->match_frames_base;
+
+/* Copy in the original argument variables */
+
+frame->Xeptr = eptr;
+frame->Xecode = ecode;
+frame->Xmstart = mstart;
+frame->Xoffset_top = offset_top;
+frame->Xeptrb = eptrb;
+frame->Xrdepth = rdepth;
+
+/* This is where control jumps back to to effect "recursion" */
+
+HEAP_RECURSE:
+
+/* Macros make the argument variables come from the current frame */
+
+#define eptr frame->Xeptr
+#define ecode frame->Xecode
+#define mstart frame->Xmstart
+#define offset_top frame->Xoffset_top
+#define eptrb frame->Xeptrb
+#define rdepth frame->Xrdepth
+
+/* Ditto for the local variables */
+
+#ifdef SUPPORT_UTF
+#define charptr frame->Xcharptr
+#endif
+#define callpat frame->Xcallpat
+#define codelink frame->Xcodelink
+#define data frame->Xdata
+#define next frame->Xnext
+#define pp frame->Xpp
+#define prev frame->Xprev
+#define saved_eptr frame->Xsaved_eptr
+
+#define new_recursive frame->Xnew_recursive
+
+#define cur_is_word frame->Xcur_is_word
+#define condition frame->Xcondition
+#define prev_is_word frame->Xprev_is_word
+
+#ifdef SUPPORT_UCP
+#define prop_type frame->Xprop_type
+#define prop_value frame->Xprop_value
+#define prop_fail_result frame->Xprop_fail_result
+#define oclength frame->Xoclength
+#define occhars frame->Xocchars
+#endif
+
+#define ctype frame->Xctype
+#define fc frame->Xfc
+#define fi frame->Xfi
+#define length frame->Xlength
+#define max frame->Xmax
+#define min frame->Xmin
+#define number frame->Xnumber
+#define offset frame->Xoffset
+#define op frame->Xop
+#define save_capture_last frame->Xsave_capture_last
+#define save_offset1 frame->Xsave_offset1
+#define save_offset2 frame->Xsave_offset2
+#define save_offset3 frame->Xsave_offset3
+#define stacksave frame->Xstacksave
+
+#define newptrb frame->Xnewptrb
+
+/* When recursion is being used, local variables are allocated on the stack and
+get preserved during recursion in the normal way. In this environment, fi and
+i, and fc and c, can be the same variables. */
+
+#else /* NO_RECURSE not defined */
+#define fi i
+#define fc c
+
+/* Many of the following variables are used only in small blocks of the code.
+My normal style of coding would have declared them within each of those blocks.
+However, in order to accommodate the version of this code that uses an external
+"stack" implemented on the heap, it is easier to declare them all here, so the
+declarations can be cut out in a block. The only declarations within blocks
+below are for variables that do not have to be preserved over a recursive call
+to RMATCH(). */
+
+#ifdef SUPPORT_UTF
+const pcre_uchar *charptr;
+#endif
+const pcre_uchar *callpat;
+const pcre_uchar *data;
+const pcre_uchar *next;
+PCRE_PUCHAR pp;
+const pcre_uchar *prev;
+PCRE_PUCHAR saved_eptr;
+
+recursion_info new_recursive;
+
+BOOL cur_is_word;
+BOOL condition;
+BOOL prev_is_word;
+
+#ifdef SUPPORT_UCP
+int prop_type;
+unsigned int prop_value;
+int prop_fail_result;
+int oclength;
+pcre_uchar occhars[6];
+#endif
+
+int codelink;
+int ctype;
+int length;
+int max;
+int min;
+unsigned int number;
+int offset;
+unsigned int op;
+pcre_int32 save_capture_last;
+int save_offset1, save_offset2, save_offset3;
+int stacksave[REC_STACK_SAVE_MAX];
+
+eptrblock newptrb;
+
+/* There is a special fudge for calling match() in a way that causes it to
+measure the size of its basic stack frame when the stack is being used for
+recursion. The second argument (ecode) being NULL triggers this behaviour. It
+cannot normally ever be NULL. The return is the negated value of the frame
+size. */
+
+if (ecode == NULL)
+ {
+ if (rdepth == 0)
+ return match((PCRE_PUCHAR)&rdepth, NULL, NULL, 0, NULL, NULL, 1);
+ else
+ {
+ int len = (char *)&rdepth - (char *)eptr;
+ return (len > 0)? -len : len;
+ }
+ }
+#endif /* NO_RECURSE */
+
+/* To save space on the stack and in the heap frame, I have doubled up on some
+of the local variables that are used only in localised parts of the code, but
+still need to be preserved over recursive calls of match(). These macros define
+the alternative names that are used. */
+
+#define allow_zero cur_is_word
+#define cbegroup condition
+#define code_offset codelink
+#define condassert condition
+#define matched_once prev_is_word
+#define foc number
+#define save_mark data
+
+/* These statements are here to stop the compiler complaining about unitialized
+variables. */
+
+#ifdef SUPPORT_UCP
+prop_value = 0;
+prop_fail_result = 0;
+#endif
+
+
+/* This label is used for tail recursion, which is used in a few cases even
+when NO_RECURSE is not defined, in order to reduce the amount of stack that is
+used. Thanks to Ian Taylor for noticing this possibility and sending the
+original patch. */
+
+TAIL_RECURSE:
+
+/* OK, now we can get on with the real code of the function. Recursive calls
+are specified by the macro RMATCH and RRETURN is used to return. When
+NO_RECURSE is *not* defined, these just turn into a recursive call to match()
+and a "return", respectively (possibly with some debugging if PCRE_DEBUG is
+defined). However, RMATCH isn't like a function call because it's quite a
+complicated macro. It has to be used in one particular way. This shouldn't,
+however, impact performance when true recursion is being used. */
+
+#ifdef SUPPORT_UTF
+utf = md->utf; /* Local copy of the flag */
+#else
+utf = FALSE;
+#endif
+
+/* First check that we haven't called match() too many times, or that we
+haven't exceeded the recursive call limit. */
+
+if (md->match_call_count++ >= md->match_limit) RRETURN(PCRE_ERROR_MATCHLIMIT);
+if (rdepth >= md->match_limit_recursion) RRETURN(PCRE_ERROR_RECURSIONLIMIT);
+
+/* At the start of a group with an unlimited repeat that may match an empty
+string, the variable md->match_function_type is set to MATCH_CBEGROUP. It is
+done this way to save having to use another function argument, which would take
+up space on the stack. See also MATCH_CONDASSERT below.
+
+When MATCH_CBEGROUP is set, add the current subject pointer to the chain of
+such remembered pointers, to be checked when we hit the closing ket, in order
+to break infinite loops that match no characters. When match() is called in
+other circumstances, don't add to the chain. The MATCH_CBEGROUP feature must
+NOT be used with tail recursion, because the memory block that is used is on
+the stack, so a new one may be required for each match(). */
+
+if (md->match_function_type == MATCH_CBEGROUP)
+ {
+ newptrb.epb_saved_eptr = eptr;
+ newptrb.epb_prev = eptrb;
+ eptrb = &newptrb;
+ md->match_function_type = 0;
+ }
+
+/* Now start processing the opcodes. */
+
+for (;;)
+ {
+ minimize = possessive = FALSE;
+ op = *ecode;
+
+ switch(op)
+ {
+ case OP_MARK:
+ md->nomatch_mark = ecode + 2;
+ md->mark = NULL; /* In case previously set by assertion */
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md,
+ eptrb, RM55);
+ if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&
+ md->mark == NULL) md->mark = ecode + 2;
+
+ /* A return of MATCH_SKIP_ARG means that matching failed at SKIP with an
+ argument, and we must check whether that argument matches this MARK's
+ argument. It is passed back in md->start_match_ptr (an overloading of that
+ variable). If it does match, we reset that variable to the current subject
+ position and return MATCH_SKIP. Otherwise, pass back the return code
+ unaltered. */
+
+ else if (rrc == MATCH_SKIP_ARG &&
+ STRCMP_UC_UC_TEST(ecode + 2, md->start_match_ptr) == 0)
+ {
+ md->start_match_ptr = eptr;
+ RRETURN(MATCH_SKIP);
+ }
+ RRETURN(rrc);
+
+ case OP_FAIL:
+ RRETURN(MATCH_NOMATCH);
+
+ case OP_COMMIT:
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+ eptrb, RM52);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ RRETURN(MATCH_COMMIT);
+
+ case OP_PRUNE:
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+ eptrb, RM51);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ RRETURN(MATCH_PRUNE);
+
+ case OP_PRUNE_ARG:
+ md->nomatch_mark = ecode + 2;
+ md->mark = NULL; /* In case previously set by assertion */
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md,
+ eptrb, RM56);
+ if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&
+ md->mark == NULL) md->mark = ecode + 2;
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ RRETURN(MATCH_PRUNE);
+
+ case OP_SKIP:
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+ eptrb, RM53);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ md->start_match_ptr = eptr; /* Pass back current position */
+ RRETURN(MATCH_SKIP);
+
+ /* Note that, for Perl compatibility, SKIP with an argument does NOT set
+ nomatch_mark. When a pattern match ends with a SKIP_ARG for which there was
+ not a matching mark, we have to re-run the match, ignoring the SKIP_ARG
+ that failed and any that precede it (either they also failed, or were not
+ triggered). To do this, we maintain a count of executed SKIP_ARGs. If a
+ SKIP_ARG gets to top level, the match is re-run with md->ignore_skip_arg
+ set to the count of the one that failed. */
+
+ case OP_SKIP_ARG:
+ md->skip_arg_count++;
+ if (md->skip_arg_count <= md->ignore_skip_arg)
+ {
+ ecode += PRIV(OP_lengths)[*ecode] + ecode[1];
+ break;
+ }
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md,
+ eptrb, RM57);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+
+ /* Pass back the current skip name by overloading md->start_match_ptr and
+ returning the special MATCH_SKIP_ARG return code. This will either be
+ caught by a matching MARK, or get to the top, where it causes a rematch
+ with md->ignore_skip_arg set to the value of md->skip_arg_count. */
+
+ md->start_match_ptr = ecode + 2;
+ RRETURN(MATCH_SKIP_ARG);
+
+ /* For THEN (and THEN_ARG) we pass back the address of the opcode, so that
+ the branch in which it occurs can be determined. Overload the start of
+ match pointer to do this. */
+
+ case OP_THEN:
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+ eptrb, RM54);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ md->start_match_ptr = ecode;
+ RRETURN(MATCH_THEN);
+
+ case OP_THEN_ARG:
+ md->nomatch_mark = ecode + 2;
+ md->mark = NULL; /* In case previously set by assertion */
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top,
+ md, eptrb, RM58);
+ if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&
+ md->mark == NULL) md->mark = ecode + 2;
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ md->start_match_ptr = ecode;
+ RRETURN(MATCH_THEN);
+
+ /* Handle an atomic group that does not contain any capturing parentheses.
+ This can be handled like an assertion. Prior to 8.13, all atomic groups
+ were handled this way. In 8.13, the code was changed as below for ONCE, so
+ that backups pass through the group and thereby reset captured values.
+ However, this uses a lot more stack, so in 8.20, atomic groups that do not
+ contain any captures generate OP_ONCE_NC, which can be handled in the old,
+ less stack intensive way.
+
+ Check the alternative branches in turn - the matching won't pass the KET
+ for this kind of subpattern. If any one branch matches, we carry on as at
+ the end of a normal bracket, leaving the subject pointer, but resetting
+ the start-of-match value in case it was changed by \K. */
+
+ case OP_ONCE_NC:
+ prev = ecode;
+ saved_eptr = eptr;
+ save_mark = md->mark;
+ do
+ {
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM64);
+ if (rrc == MATCH_MATCH) /* Note: _not_ MATCH_ACCEPT */
+ {
+ mstart = md->start_match_ptr;
+ break;
+ }
+ if (rrc == MATCH_THEN)
+ {
+ next = ecode + GET(ecode,1);
+ if (md->start_match_ptr < next &&
+ (*ecode == OP_ALT || *next == OP_ALT))
+ rrc = MATCH_NOMATCH;
+ }
+
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ ecode += GET(ecode,1);
+ md->mark = save_mark;
+ }
+ while (*ecode == OP_ALT);
+
+ /* If hit the end of the group (which could be repeated), fail */
+
+ if (*ecode != OP_ONCE_NC && *ecode != OP_ALT) RRETURN(MATCH_NOMATCH);
+
+ /* Continue as from after the group, updating the offsets high water
+ mark, since extracts may have been taken. */
+
+ do ecode += GET(ecode, 1); while (*ecode == OP_ALT);
+
+ offset_top = md->end_offset_top;
+ eptr = md->end_match_ptr;
+
+ /* For a non-repeating ket, just continue at this level. This also
+ happens for a repeating ket if no characters were matched in the group.
+ This is the forcible breaking of infinite loops as implemented in Perl
+ 5.005. */
+
+ if (*ecode == OP_KET || eptr == saved_eptr)
+ {
+ ecode += 1+LINK_SIZE;
+ break;
+ }
+
+ /* The repeating kets try the rest of the pattern or restart from the
+ preceding bracket, in the appropriate order. The second "call" of match()
+ uses tail recursion, to avoid using another stack frame. */
+
+ if (*ecode == OP_KETRMIN)
+ {
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM65);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ ecode = prev;
+ goto TAIL_RECURSE;
+ }
+ else /* OP_KETRMAX */
+ {
+ RMATCH(eptr, prev, offset_top, md, eptrb, RM66);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ ecode += 1 + LINK_SIZE;
+ goto TAIL_RECURSE;
+ }
+ /* Control never gets here */
+
+ /* Handle a capturing bracket, other than those that are possessive with an
+ unlimited repeat. If there is space in the offset vector, save the current
+ subject position in the working slot at the top of the vector. We mustn't
+ change the current values of the data slot, because they may be set from a
+ previous iteration of this group, and be referred to by a reference inside
+ the group. A failure to match might occur after the group has succeeded,
+ if something later on doesn't match. For this reason, we need to restore
+ the working value and also the values of the final offsets, in case they
+ were set by a previous iteration of the same bracket.
+
+ If there isn't enough space in the offset vector, treat this as if it were
+ a non-capturing bracket. Don't worry about setting the flag for the error
+ case here; that is handled in the code for KET. */
+
+ case OP_CBRA:
+ case OP_SCBRA:
+ number = GET2(ecode, 1+LINK_SIZE);
+ offset = number << 1;
+
+#ifdef PCRE_DEBUG
+ printf("start bracket %d\n", number);
+ printf("subject=");
+ pchars(eptr, 16, TRUE, md);
+ printf("\n");
+#endif
+
+ if (offset < md->offset_max)
+ {
+ save_offset1 = md->offset_vector[offset];
+ save_offset2 = md->offset_vector[offset+1];
+ save_offset3 = md->offset_vector[md->offset_end - number];
+ save_capture_last = md->capture_last;
+ save_mark = md->mark;
+
+ DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
+ md->offset_vector[md->offset_end - number] =
+ (int)(eptr - md->start_subject);
+
+ for (;;)
+ {
+ if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP;
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+ eptrb, RM1);
+ if (rrc == MATCH_ONCE) break; /* Backing up through an atomic group */
+
+ /* If we backed up to a THEN, check whether it is within the current
+ branch by comparing the address of the THEN that is passed back with
+ the end of the branch. If it is within the current branch, and the
+ branch is one of two or more alternatives (it either starts or ends
+ with OP_ALT), we have reached the limit of THEN's action, so convert
+ the return code to NOMATCH, which will cause normal backtracking to
+ happen from now on. Otherwise, THEN is passed back to an outer
+ alternative. This implements Perl's treatment of parenthesized groups,
+ where a group not containing | does not affect the current alternative,
+ that is, (X) is NOT the same as (X|(*F)). */
+
+ if (rrc == MATCH_THEN)
+ {
+ next = ecode + GET(ecode,1);
+ if (md->start_match_ptr < next &&
+ (*ecode == OP_ALT || *next == OP_ALT))
+ rrc = MATCH_NOMATCH;
+ }
+
+ /* Anything other than NOMATCH is passed back. */
+
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ md->capture_last = save_capture_last;
+ ecode += GET(ecode, 1);
+ md->mark = save_mark;
+ if (*ecode != OP_ALT) break;
+ }
+
+ DPRINTF(("bracket %d failed\n", number));
+ md->offset_vector[offset] = save_offset1;
+ md->offset_vector[offset+1] = save_offset2;
+ md->offset_vector[md->offset_end - number] = save_offset3;
+
+ /* At this point, rrc will be one of MATCH_ONCE or MATCH_NOMATCH. */
+
+ RRETURN(rrc);
+ }
+
+ /* FALL THROUGH ... Insufficient room for saving captured contents. Treat
+ as a non-capturing bracket. */
+
+ /* VVVVVVVVVVVVVVVVVVVVVVVVV */
+ /* VVVVVVVVVVVVVVVVVVVVVVVVV */
+
+ DPRINTF(("insufficient capture room: treat as non-capturing\n"));
+
+ /* VVVVVVVVVVVVVVVVVVVVVVVVV */
+ /* VVVVVVVVVVVVVVVVVVVVVVVVV */
+
+ /* Non-capturing or atomic group, except for possessive with unlimited
+ repeat and ONCE group with no captures. Loop for all the alternatives.
+
+ When we get to the final alternative within the brackets, we used to return
+ the result of a recursive call to match() whatever happened so it was
+ possible to reduce stack usage by turning this into a tail recursion,
+ except in the case of a possibly empty group. However, now that there is
+ the possiblity of (*THEN) occurring in the final alternative, this
+ optimization is no longer always possible.
+
+ We can optimize if we know there are no (*THEN)s in the pattern; at present
+ this is the best that can be done.
+
+ MATCH_ONCE is returned when the end of an atomic group is successfully
+ reached, but subsequent matching fails. It passes back up the tree (causing
+ captured values to be reset) until the original atomic group level is
+ reached. This is tested by comparing md->once_target with the start of the
+ group. At this point, the return is converted into MATCH_NOMATCH so that
+ previous backup points can be taken. */
+
+ case OP_ONCE:
+ case OP_BRA:
+ case OP_SBRA:
+ DPRINTF(("start non-capturing bracket\n"));
+
+ for (;;)
+ {
+ if (op >= OP_SBRA || op == OP_ONCE)
+ md->match_function_type = MATCH_CBEGROUP;
+
+ /* If this is not a possibly empty group, and there are no (*THEN)s in
+ the pattern, and this is the final alternative, optimize as described
+ above. */
+
+ else if (!md->hasthen && ecode[GET(ecode, 1)] != OP_ALT)
+ {
+ ecode += PRIV(OP_lengths)[*ecode];
+ goto TAIL_RECURSE;
+ }
+
+ /* In all other cases, we have to make another call to match(). */
+
+ save_mark = md->mark;
+ save_capture_last = md->capture_last;
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb,
+ RM2);
+
+ /* See comment in the code for capturing groups above about handling
+ THEN. */
+
+ if (rrc == MATCH_THEN)
+ {
+ next = ecode + GET(ecode,1);
+ if (md->start_match_ptr < next &&
+ (*ecode == OP_ALT || *next == OP_ALT))
+ rrc = MATCH_NOMATCH;
+ }
+
+ if (rrc != MATCH_NOMATCH)
+ {
+ if (rrc == MATCH_ONCE)
+ {
+ const pcre_uchar *scode = ecode;
+ if (*scode != OP_ONCE) /* If not at start, find it */
+ {
+ while (*scode == OP_ALT) scode += GET(scode, 1);
+ scode -= GET(scode, 1);
+ }
+ if (md->once_target == scode) rrc = MATCH_NOMATCH;
+ }
+ RRETURN(rrc);
+ }
+ ecode += GET(ecode, 1);
+ md->mark = save_mark;
+ if (*ecode != OP_ALT) break;
+ md->capture_last = save_capture_last;
+ }
+
+ RRETURN(MATCH_NOMATCH);
+
+ /* Handle possessive capturing brackets with an unlimited repeat. We come
+ here from BRAZERO with allow_zero set TRUE. The offset_vector values are
+ handled similarly to the normal case above. However, the matching is
+ different. The end of these brackets will always be OP_KETRPOS, which
+ returns MATCH_KETRPOS without going further in the pattern. By this means
+ we can handle the group by iteration rather than recursion, thereby
+ reducing the amount of stack needed. */
+
+ case OP_CBRAPOS:
+ case OP_SCBRAPOS:
+ allow_zero = FALSE;
+
+ POSSESSIVE_CAPTURE:
+ number = GET2(ecode, 1+LINK_SIZE);
+ offset = number << 1;
+
+#ifdef PCRE_DEBUG
+ printf("start possessive bracket %d\n", number);
+ printf("subject=");
+ pchars(eptr, 16, TRUE, md);
+ printf("\n");
+#endif
+
+ if (offset < md->offset_max)
+ {
+ matched_once = FALSE;
+ code_offset = (int)(ecode - md->start_code);
+
+ save_offset1 = md->offset_vector[offset];
+ save_offset2 = md->offset_vector[offset+1];
+ save_offset3 = md->offset_vector[md->offset_end - number];
+ save_capture_last = md->capture_last;
+
+ DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
+
+ /* Each time round the loop, save the current subject position for use
+ when the group matches. For MATCH_MATCH, the group has matched, so we
+ restart it with a new subject starting position, remembering that we had
+ at least one match. For MATCH_NOMATCH, carry on with the alternatives, as
+ usual. If we haven't matched any alternatives in any iteration, check to
+ see if a previous iteration matched. If so, the group has matched;
+ continue from afterwards. Otherwise it has failed; restore the previous
+ capture values before returning NOMATCH. */
+
+ for (;;)
+ {
+ md->offset_vector[md->offset_end - number] =
+ (int)(eptr - md->start_subject);
+ if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP;
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+ eptrb, RM63);
+ if (rrc == MATCH_KETRPOS)
+ {
+ offset_top = md->end_offset_top;
+ eptr = md->end_match_ptr;
+ ecode = md->start_code + code_offset;
+ save_capture_last = md->capture_last;
+ matched_once = TRUE;
+ mstart = md->start_match_ptr; /* In case \K changed it */
+ continue;
+ }
+
+ /* See comment in the code for capturing groups above about handling
+ THEN. */
+
+ if (rrc == MATCH_THEN)
+ {
+ next = ecode + GET(ecode,1);
+ if (md->start_match_ptr < next &&
+ (*ecode == OP_ALT || *next == OP_ALT))
+ rrc = MATCH_NOMATCH;
+ }
+
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ md->capture_last = save_capture_last;
+ ecode += GET(ecode, 1);
+ if (*ecode != OP_ALT) break;
+ }
+
+ if (!matched_once)
+ {
+ md->offset_vector[offset] = save_offset1;
+ md->offset_vector[offset+1] = save_offset2;
+ md->offset_vector[md->offset_end - number] = save_offset3;
+ }
+
+ if (allow_zero || matched_once)
+ {
+ ecode += 1 + LINK_SIZE;
+ break;
+ }
+
+ RRETURN(MATCH_NOMATCH);
+ }
+
+ /* FALL THROUGH ... Insufficient room for saving captured contents. Treat
+ as a non-capturing bracket. */
+
+ /* VVVVVVVVVVVVVVVVVVVVVVVVV */
+ /* VVVVVVVVVVVVVVVVVVVVVVVVV */
+
+ DPRINTF(("insufficient capture room: treat as non-capturing\n"));
+
+ /* VVVVVVVVVVVVVVVVVVVVVVVVV */
+ /* VVVVVVVVVVVVVVVVVVVVVVVVV */
+
+ /* Non-capturing possessive bracket with unlimited repeat. We come here
+ from BRAZERO with allow_zero = TRUE. The code is similar to the above,
+ without the capturing complication. It is written out separately for speed
+ and cleanliness. */
+
+ case OP_BRAPOS:
+ case OP_SBRAPOS:
+ allow_zero = FALSE;
+
+ POSSESSIVE_NON_CAPTURE:
+ matched_once = FALSE;
+ code_offset = (int)(ecode - md->start_code);
+ save_capture_last = md->capture_last;
+
+ for (;;)
+ {
+ if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP;
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+ eptrb, RM48);
+ if (rrc == MATCH_KETRPOS)
+ {
+ offset_top = md->end_offset_top;
+ eptr = md->end_match_ptr;
+ ecode = md->start_code + code_offset;
+ matched_once = TRUE;
+ mstart = md->start_match_ptr; /* In case \K reset it */
+ continue;
+ }
+
+ /* See comment in the code for capturing groups above about handling
+ THEN. */
+
+ if (rrc == MATCH_THEN)
+ {
+ next = ecode + GET(ecode,1);
+ if (md->start_match_ptr < next &&
+ (*ecode == OP_ALT || *next == OP_ALT))
+ rrc = MATCH_NOMATCH;
+ }
+
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ ecode += GET(ecode, 1);
+ if (*ecode != OP_ALT) break;
+ md->capture_last = save_capture_last;
+ }
+
+ if (matched_once || allow_zero)
+ {
+ ecode += 1 + LINK_SIZE;
+ break;
+ }
+ RRETURN(MATCH_NOMATCH);
+
+ /* Control never reaches here. */
+
+ /* Conditional group: compilation checked that there are no more than two
+ branches. If the condition is false, skipping the first branch takes us
+ past the end of the item if there is only one branch, but that's exactly
+ what we want. */
+
+ case OP_COND:
+ case OP_SCOND:
+
+ /* The variable codelink will be added to ecode when the condition is
+ false, to get to the second branch. Setting it to the offset to the ALT
+ or KET, then incrementing ecode achieves this effect. We now have ecode
+ pointing to the condition or callout. */
+
+ codelink = GET(ecode, 1); /* Offset to the second branch */
+ ecode += 1 + LINK_SIZE; /* From this opcode */
+
+ /* Because of the way auto-callout works during compile, a callout item is
+ inserted between OP_COND and an assertion condition. */
+
+ if (*ecode == OP_CALLOUT)
+ {
+ if (PUBL(callout) != NULL)
+ {
+ PUBL(callout_block) cb;
+ cb.version = 2; /* Version 1 of the callout block */
+ cb.callout_number = ecode[1];
+ cb.offset_vector = md->offset_vector;
+#if defined COMPILE_PCRE8
+ cb.subject = (PCRE_SPTR)md->start_subject;
+#elif defined COMPILE_PCRE16
+ cb.subject = (PCRE_SPTR16)md->start_subject;
+#elif defined COMPILE_PCRE32
+ cb.subject = (PCRE_SPTR32)md->start_subject;
+#endif
+ cb.subject_length = (int)(md->end_subject - md->start_subject);
+ cb.start_match = (int)(mstart - md->start_subject);
+ cb.current_position = (int)(eptr - md->start_subject);
+ cb.pattern_position = GET(ecode, 2);
+ cb.next_item_length = GET(ecode, 2 + LINK_SIZE);
+ cb.capture_top = offset_top/2;
+ cb.capture_last = md->capture_last & CAPLMASK;
+ /* Internal change requires this for API compatibility. */
+ if (cb.capture_last == 0) cb.capture_last = -1;
+ cb.callout_data = md->callout_data;
+ cb.mark = md->nomatch_mark;
+ if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH);
+ if (rrc < 0) RRETURN(rrc);
+ }
+
+ /* Advance ecode past the callout, so it now points to the condition. We
+ must adjust codelink so that the value of ecode+codelink is unchanged. */
+
+ ecode += PRIV(OP_lengths)[OP_CALLOUT];
+ codelink -= PRIV(OP_lengths)[OP_CALLOUT];
+ }
+
+ /* Test the various possible conditions */
+
+ condition = FALSE;
+ switch(condcode = *ecode)
+ {
+ case OP_RREF: /* Numbered group recursion test */
+ if (md->recursive != NULL) /* Not recursing => FALSE */
+ {
+ unsigned int recno = GET2(ecode, 1); /* Recursion group number*/
+ condition = (recno == RREF_ANY || recno == md->recursive->group_num);
+ }
+ break;
+
+ case OP_DNRREF: /* Duplicate named group recursion test */
+ if (md->recursive != NULL)
+ {
+ int count = GET2(ecode, 1 + IMM2_SIZE);
+ pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size;
+ while (count-- > 0)
+ {
+ unsigned int recno = GET2(slot, 0);
+ condition = recno == md->recursive->group_num;
+ if (condition) break;
+ slot += md->name_entry_size;
+ }
+ }
+ break;
+
+ case OP_CREF: /* Numbered group used test */
+ offset = GET2(ecode, 1) << 1; /* Doubled ref number */
+ condition = offset < offset_top && md->offset_vector[offset] >= 0;
+ break;
+
+ case OP_DNCREF: /* Duplicate named group used test */
+ {
+ int count = GET2(ecode, 1 + IMM2_SIZE);
+ pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size;
+ while (count-- > 0)
+ {
+ offset = GET2(slot, 0) << 1;
+ condition = offset < offset_top && md->offset_vector[offset] >= 0;
+ if (condition) break;
+ slot += md->name_entry_size;
+ }
+ }
+ break;
+
+ case OP_DEF: /* DEFINE - always false */
+ break;
+
+ /* The condition is an assertion. Call match() to evaluate it - setting
+ md->match_function_type to MATCH_CONDASSERT causes it to stop at the end
+ of an assertion. */
+
+ default:
+ md->match_function_type = MATCH_CONDASSERT;
+ RMATCH(eptr, ecode, offset_top, md, NULL, RM3);
+ if (rrc == MATCH_MATCH)
+ {
+ if (md->end_offset_top > offset_top)
+ offset_top = md->end_offset_top; /* Captures may have happened */
+ condition = TRUE;
+
+ /* Advance ecode past the assertion to the start of the first branch,
+ but adjust it so that the general choosing code below works. */
+
+ ecode += GET(ecode, 1);
+ while (*ecode == OP_ALT) ecode += GET(ecode, 1);
+ ecode += 1 + LINK_SIZE - PRIV(OP_lengths)[condcode];
+ }
+
+ /* PCRE doesn't allow the effect of (*THEN) to escape beyond an
+ assertion; it is therefore treated as NOMATCH. Any other return is an
+ error. */
+
+ else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN)
+ {
+ RRETURN(rrc); /* Need braces because of following else */
+ }
+ break;
+ }
+
+ /* Choose branch according to the condition */
+
+ ecode += condition? PRIV(OP_lengths)[condcode] : codelink;
+
+ /* We are now at the branch that is to be obeyed. As there is only one, we
+ can use tail recursion to avoid using another stack frame, except when
+ there is unlimited repeat of a possibly empty group. In the latter case, a
+ recursive call to match() is always required, unless the second alternative
+ doesn't exist, in which case we can just plough on. Note that, for
+ compatibility with Perl, the | in a conditional group is NOT treated as
+ creating two alternatives. If a THEN is encountered in the branch, it
+ propagates out to the enclosing alternative (unless nested in a deeper set
+ of alternatives, of course). */
+
+ if (condition || ecode[-(1+LINK_SIZE)] == OP_ALT)
+ {
+ if (op != OP_SCOND)
+ {
+ goto TAIL_RECURSE;
+ }
+
+ md->match_function_type = MATCH_CBEGROUP;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM49);
+ RRETURN(rrc);
+ }
+
+ /* Condition false & no alternative; continue after the group. */
+
+ else
+ {
+ }
+ break;
+
+
+ /* Before OP_ACCEPT there may be any number of OP_CLOSE opcodes,
+ to close any currently open capturing brackets. */
+
+ case OP_CLOSE:
+ number = GET2(ecode, 1); /* Must be less than 65536 */
+ offset = number << 1;
+
+#ifdef PCRE_DEBUG
+ printf("end bracket %d at *ACCEPT", number);
+ printf("\n");
+#endif
+
+ md->capture_last = (md->capture_last & OVFLMASK) | number;
+ if (offset >= md->offset_max) md->capture_last |= OVFLBIT; else
+ {
+ md->offset_vector[offset] =
+ md->offset_vector[md->offset_end - number];
+ md->offset_vector[offset+1] = (int)(eptr - md->start_subject);
+ if (offset_top <= offset) offset_top = offset + 2;
+ }
+ ecode += 1 + IMM2_SIZE;
+ break;
+
+
+ /* End of the pattern, either real or forced. */
+
+ case OP_END:
+ case OP_ACCEPT:
+ case OP_ASSERT_ACCEPT:
+
+ /* If we have matched an empty string, fail if not in an assertion and not
+ in a recursion if either PCRE_NOTEMPTY is set, or if PCRE_NOTEMPTY_ATSTART
+ is set and we have matched at the start of the subject. In both cases,
+ backtracking will then try other alternatives, if any. */
+
+ if (eptr == mstart && op != OP_ASSERT_ACCEPT &&
+ md->recursive == NULL &&
+ (md->notempty ||
+ (md->notempty_atstart &&
+ mstart == md->start_subject + md->start_offset)))
+ RRETURN(MATCH_NOMATCH);
+
+ /* Otherwise, we have a match. */
+
+ md->end_match_ptr = eptr; /* Record where we ended */
+ md->end_offset_top = offset_top; /* and how many extracts were taken */
+ md->start_match_ptr = mstart; /* and the start (\K can modify) */
+
+ /* For some reason, the macros don't work properly if an expression is
+ given as the argument to RRETURN when the heap is in use. */
+
+ rrc = (op == OP_END)? MATCH_MATCH : MATCH_ACCEPT;
+ RRETURN(rrc);
+
+ /* Assertion brackets. Check the alternative branches in turn - the
+ matching won't pass the KET for an assertion. If any one branch matches,
+ the assertion is true. Lookbehind assertions have an OP_REVERSE item at the
+ start of each branch to move the current point backwards, so the code at
+ this level is identical to the lookahead case. When the assertion is part
+ of a condition, we want to return immediately afterwards. The caller of
+ this incarnation of the match() function will have set MATCH_CONDASSERT in
+ md->match_function type, and one of these opcodes will be the first opcode
+ that is processed. We use a local variable that is preserved over calls to
+ match() to remember this case. */
+
+ case OP_ASSERT:
+ case OP_ASSERTBACK:
+ save_mark = md->mark;
+ if (md->match_function_type == MATCH_CONDASSERT)
+ {
+ condassert = TRUE;
+ md->match_function_type = 0;
+ }
+ else condassert = FALSE;
+
+ /* Loop for each branch */
+
+ do
+ {
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM4);
+
+ /* A match means that the assertion is true; break out of the loop
+ that matches its alternatives. */
+
+ if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
+ {
+ mstart = md->start_match_ptr; /* In case \K reset it */
+ break;
+ }
+
+ /* If not matched, restore the previous mark setting. */
+
+ md->mark = save_mark;
+
+ /* See comment in the code for capturing groups above about handling
+ THEN. */
+
+ if (rrc == MATCH_THEN)
+ {
+ next = ecode + GET(ecode,1);
+ if (md->start_match_ptr < next &&
+ (*ecode == OP_ALT || *next == OP_ALT))
+ rrc = MATCH_NOMATCH;
+ }
+
+ /* Anything other than NOMATCH causes the entire assertion to fail,
+ passing back the return code. This includes COMMIT, SKIP, PRUNE and an
+ uncaptured THEN, which means they take their normal effect. This
+ consistent approach does not always have exactly the same effect as in
+ Perl. */
+
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ ecode += GET(ecode, 1);
+ }
+ while (*ecode == OP_ALT); /* Continue for next alternative */
+
+ /* If we have tried all the alternative branches, the assertion has
+ failed. If not, we broke out after a match. */
+
+ if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH);
+
+ /* If checking an assertion for a condition, return MATCH_MATCH. */
+
+ if (condassert) RRETURN(MATCH_MATCH);
+
+ /* Continue from after a successful assertion, updating the offsets high
+ water mark, since extracts may have been taken during the assertion. */
+
+ do ecode += GET(ecode,1); while (*ecode == OP_ALT);
+ ecode += 1 + LINK_SIZE;
+ offset_top = md->end_offset_top;
+ continue;
+
+ /* Negative assertion: all branches must fail to match for the assertion to
+ succeed. */
+
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK_NOT:
+ save_mark = md->mark;
+ if (md->match_function_type == MATCH_CONDASSERT)
+ {
+ condassert = TRUE;
+ md->match_function_type = 0;
+ }
+ else condassert = FALSE;
+
+ /* Loop for each alternative branch. */
+
+ do
+ {
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM5);
+ md->mark = save_mark; /* Always restore the mark setting */
+
+ switch(rrc)
+ {
+ case MATCH_MATCH: /* A successful match means */
+ case MATCH_ACCEPT: /* the assertion has failed. */
+ RRETURN(MATCH_NOMATCH);
+
+ case MATCH_NOMATCH: /* Carry on with next branch */
+ break;
+
+ /* See comment in the code for capturing groups above about handling
+ THEN. */
+
+ case MATCH_THEN:
+ next = ecode + GET(ecode,1);
+ if (md->start_match_ptr < next &&
+ (*ecode == OP_ALT || *next == OP_ALT))
+ {
+ rrc = MATCH_NOMATCH;
+ break;
+ }
+ /* Otherwise fall through. */
+
+ /* COMMIT, SKIP, PRUNE, and an uncaptured THEN cause the whole
+ assertion to fail to match, without considering any more alternatives.
+ Failing to match means the assertion is true. This is a consistent
+ approach, but does not always have the same effect as in Perl. */
+
+ case MATCH_COMMIT:
+ case MATCH_SKIP:
+ case MATCH_SKIP_ARG:
+ case MATCH_PRUNE:
+ do ecode += GET(ecode,1); while (*ecode == OP_ALT);
+ goto NEG_ASSERT_TRUE; /* Break out of alternation loop */
+
+ /* Anything else is an error */
+
+ default:
+ RRETURN(rrc);
+ }
+
+ /* Continue with next branch */
+
+ ecode += GET(ecode,1);
+ }
+ while (*ecode == OP_ALT);
+
+ /* All branches in the assertion failed to match. */
+
+ NEG_ASSERT_TRUE:
+ if (condassert) RRETURN(MATCH_MATCH); /* Condition assertion */
+ ecode += 1 + LINK_SIZE; /* Continue with current branch */
+ continue;
+
+ /* Move the subject pointer back. This occurs only at the start of
+ each branch of a lookbehind assertion. If we are too close to the start to
+ move back, this match function fails. When working with UTF-8 we move
+ back a number of characters, not bytes. */
+
+ case OP_REVERSE:
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ i = GET(ecode, 1);
+ while (i-- > 0)
+ {
+ eptr--;
+ if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH);
+ BACKCHAR(eptr);
+ }
+ }
+ else
+#endif
+
+ /* No UTF-8 support, or not in UTF-8 mode: count is byte count */
+
+ {
+ eptr -= GET(ecode, 1);
+ if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH);
+ }
+
+ /* Save the earliest consulted character, then skip to next op code */
+
+ if (eptr < md->start_used_ptr) md->start_used_ptr = eptr;
+ ecode += 1 + LINK_SIZE;
+ break;
+
+ /* The callout item calls an external function, if one is provided, passing
+ details of the match so far. This is mainly for debugging, though the
+ function is able to force a failure. */
+
+ case OP_CALLOUT:
+ if (PUBL(callout) != NULL)
+ {
+ PUBL(callout_block) cb;
+ cb.version = 2; /* Version 1 of the callout block */
+ cb.callout_number = ecode[1];
+ cb.offset_vector = md->offset_vector;
+#if defined COMPILE_PCRE8
+ cb.subject = (PCRE_SPTR)md->start_subject;
+#elif defined COMPILE_PCRE16
+ cb.subject = (PCRE_SPTR16)md->start_subject;
+#elif defined COMPILE_PCRE32
+ cb.subject = (PCRE_SPTR32)md->start_subject;
+#endif
+ cb.subject_length = (int)(md->end_subject - md->start_subject);
+ cb.start_match = (int)(mstart - md->start_subject);
+ cb.current_position = (int)(eptr - md->start_subject);
+ cb.pattern_position = GET(ecode, 2);
+ cb.next_item_length = GET(ecode, 2 + LINK_SIZE);
+ cb.capture_top = offset_top/2;
+ cb.capture_last = md->capture_last & CAPLMASK;
+ /* Internal change requires this for API compatibility. */
+ if (cb.capture_last == 0) cb.capture_last = -1;
+ cb.callout_data = md->callout_data;
+ cb.mark = md->nomatch_mark;
+ if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH);
+ if (rrc < 0) RRETURN(rrc);
+ }
+ ecode += 2 + 2*LINK_SIZE;
+ break;
+
+ /* Recursion either matches the current regex, or some subexpression. The
+ offset data is the offset to the starting bracket from the start of the
+ whole pattern. (This is so that it works from duplicated subpatterns.)
+
+ The state of the capturing groups is preserved over recursion, and
+ re-instated afterwards. We don't know how many are started and not yet
+ finished (offset_top records the completed total) so we just have to save
+ all the potential data. There may be up to 65535 such values, which is too
+ large to put on the stack, but using malloc for small numbers seems
+ expensive. As a compromise, the stack is used when there are no more than
+ REC_STACK_SAVE_MAX values to store; otherwise malloc is used.
+
+ There are also other values that have to be saved. We use a chained
+ sequence of blocks that actually live on the stack. Thanks to Robin Houston
+ for the original version of this logic. It has, however, been hacked around
+ a lot, so he is not to blame for the current way it works. */
+
+ case OP_RECURSE:
+ {
+ recursion_info *ri;
+ unsigned int recno;
+
+ callpat = md->start_code + GET(ecode, 1);
+ recno = (callpat == md->start_code)? 0 :
+ GET2(callpat, 1 + LINK_SIZE);
+
+ /* Check for repeating a recursion without advancing the subject pointer.
+ This should catch convoluted mutual recursions. (Some simple cases are
+ caught at compile time.) */
+
+ for (ri = md->recursive; ri != NULL; ri = ri->prevrec)
+ if (recno == ri->group_num && eptr == ri->subject_position)
+ RRETURN(PCRE_ERROR_RECURSELOOP);
+
+ /* Add to "recursing stack" */
+
+ new_recursive.group_num = recno;
+ new_recursive.saved_capture_last = md->capture_last;
+ new_recursive.subject_position = eptr;
+ new_recursive.prevrec = md->recursive;
+ md->recursive = &new_recursive;
+
+ /* Where to continue from afterwards */
+
+ ecode += 1 + LINK_SIZE;
+
+ /* Now save the offset data */
+
+ new_recursive.saved_max = md->offset_end;
+ if (new_recursive.saved_max <= REC_STACK_SAVE_MAX)
+ new_recursive.offset_save = stacksave;
+ else
+ {
+ new_recursive.offset_save =
+ (int *)(PUBL(malloc))(new_recursive.saved_max * sizeof(int));
+ if (new_recursive.offset_save == NULL) RRETURN(PCRE_ERROR_NOMEMORY);
+ }
+ memcpy(new_recursive.offset_save, md->offset_vector,
+ new_recursive.saved_max * sizeof(int));
+
+ /* OK, now we can do the recursion. After processing each alternative,
+ restore the offset data and the last captured value. If there were nested
+ recursions, md->recursive might be changed, so reset it before looping.
+ */
+
+ DPRINTF(("Recursing into group %d\n", new_recursive.group_num));
+ cbegroup = (*callpat >= OP_SBRA);
+ do
+ {
+ if (cbegroup) md->match_function_type = MATCH_CBEGROUP;
+ RMATCH(eptr, callpat + PRIV(OP_lengths)[*callpat], offset_top,
+ md, eptrb, RM6);
+ memcpy(md->offset_vector, new_recursive.offset_save,
+ new_recursive.saved_max * sizeof(int));
+ md->capture_last = new_recursive.saved_capture_last;
+ md->recursive = new_recursive.prevrec;
+ if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
+ {
+ DPRINTF(("Recursion matched\n"));
+ if (new_recursive.offset_save != stacksave)
+ (PUBL(free))(new_recursive.offset_save);
+
+ /* Set where we got to in the subject, and reset the start in case
+ it was changed by \K. This *is* propagated back out of a recursion,
+ for Perl compatibility. */
+
+ eptr = md->end_match_ptr;
+ mstart = md->start_match_ptr;
+ goto RECURSION_MATCHED; /* Exit loop; end processing */
+ }
+
+ /* PCRE does not allow THEN, SKIP, PRUNE or COMMIT to escape beyond a
+ recursion; they cause a NOMATCH for the entire recursion. These codes
+ are defined in a range that can be tested for. */
+
+ if (rrc >= MATCH_BACKTRACK_MIN && rrc <= MATCH_BACKTRACK_MAX)
+ RRETURN(MATCH_NOMATCH);
+
+ /* Any return code other than NOMATCH is an error. */
+
+ if (rrc != MATCH_NOMATCH)
+ {
+ DPRINTF(("Recursion gave error %d\n", rrc));
+ if (new_recursive.offset_save != stacksave)
+ (PUBL(free))(new_recursive.offset_save);
+ RRETURN(rrc);
+ }
+
+ md->recursive = &new_recursive;
+ callpat += GET(callpat, 1);
+ }
+ while (*callpat == OP_ALT);
+
+ DPRINTF(("Recursion didn't match\n"));
+ md->recursive = new_recursive.prevrec;
+ if (new_recursive.offset_save != stacksave)
+ (PUBL(free))(new_recursive.offset_save);
+ RRETURN(MATCH_NOMATCH);
+ }
+
+ RECURSION_MATCHED:
+ break;
+
+ /* An alternation is the end of a branch; scan along to find the end of the
+ bracketed group and go to there. */
+
+ case OP_ALT:
+ do ecode += GET(ecode,1); while (*ecode == OP_ALT);
+ break;
+
+ /* BRAZERO, BRAMINZERO and SKIPZERO occur just before a bracket group,
+ indicating that it may occur zero times. It may repeat infinitely, or not
+ at all - i.e. it could be ()* or ()? or even (){0} in the pattern. Brackets
+ with fixed upper repeat limits are compiled as a number of copies, with the
+ optional ones preceded by BRAZERO or BRAMINZERO. */
+
+ case OP_BRAZERO:
+ next = ecode + 1;
+ RMATCH(eptr, next, offset_top, md, eptrb, RM10);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ do next += GET(next, 1); while (*next == OP_ALT);
+ ecode = next + 1 + LINK_SIZE;
+ break;
+
+ case OP_BRAMINZERO:
+ next = ecode + 1;
+ do next += GET(next, 1); while (*next == OP_ALT);
+ RMATCH(eptr, next + 1+LINK_SIZE, offset_top, md, eptrb, RM11);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ ecode++;
+ break;
+
+ case OP_SKIPZERO:
+ next = ecode+1;
+ do next += GET(next,1); while (*next == OP_ALT);
+ ecode = next + 1 + LINK_SIZE;
+ break;
+
+ /* BRAPOSZERO occurs before a possessive bracket group. Don't do anything
+ here; just jump to the group, with allow_zero set TRUE. */
+
+ case OP_BRAPOSZERO:
+ op = *(++ecode);
+ allow_zero = TRUE;
+ if (op == OP_CBRAPOS || op == OP_SCBRAPOS) goto POSSESSIVE_CAPTURE;
+ goto POSSESSIVE_NON_CAPTURE;
+
+ /* End of a group, repeated or non-repeating. */
+
+ case OP_KET:
+ case OP_KETRMIN:
+ case OP_KETRMAX:
+ case OP_KETRPOS:
+ prev = ecode - GET(ecode, 1);
+
+ /* If this was a group that remembered the subject start, in order to break
+ infinite repeats of empty string matches, retrieve the subject start from
+ the chain. Otherwise, set it NULL. */
+
+ if (*prev >= OP_SBRA || *prev == OP_ONCE)
+ {
+ saved_eptr = eptrb->epb_saved_eptr; /* Value at start of group */
+ eptrb = eptrb->epb_prev; /* Backup to previous group */
+ }
+ else saved_eptr = NULL;
+
+ /* If we are at the end of an assertion group or a non-capturing atomic
+ group, stop matching and return MATCH_MATCH, but record the current high
+ water mark for use by positive assertions. We also need to record the match
+ start in case it was changed by \K. */
+
+ if ((*prev >= OP_ASSERT && *prev <= OP_ASSERTBACK_NOT) ||
+ *prev == OP_ONCE_NC)
+ {
+ md->end_match_ptr = eptr; /* For ONCE_NC */
+ md->end_offset_top = offset_top;
+ md->start_match_ptr = mstart;
+ RRETURN(MATCH_MATCH); /* Sets md->mark */
+ }
+
+ /* For capturing groups we have to check the group number back at the start
+ and if necessary complete handling an extraction by setting the offsets and
+ bumping the high water mark. 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. We just have to record
+ the current subject position and start match pointer and give a MATCH
+ return. */
+
+ if (*prev == OP_CBRA || *prev == OP_SCBRA ||
+ *prev == OP_CBRAPOS || *prev == OP_SCBRAPOS)
+ {
+ number = GET2(prev, 1+LINK_SIZE);
+ offset = number << 1;
+
+#ifdef PCRE_DEBUG
+ printf("end bracket %d", number);
+ printf("\n");
+#endif
+
+ /* Handle a recursively called group. */
+
+ if (md->recursive != NULL && md->recursive->group_num == number)
+ {
+ md->end_match_ptr = eptr;
+ md->start_match_ptr = mstart;
+ RRETURN(MATCH_MATCH);
+ }
+
+ /* Deal with capturing */
+
+ md->capture_last = (md->capture_last & OVFLMASK) | number;
+ if (offset >= md->offset_max) md->capture_last |= OVFLBIT; else
+ {
+ /* If offset is greater than offset_top, it means that we are
+ "skipping" a capturing group, and that group's offsets must be marked
+ unset. In earlier versions of PCRE, all the offsets were unset at the
+ start of matching, but this doesn't work because atomic groups and
+ assertions can cause a value to be set that should later be unset.
+ Example: matching /(?>(a))b|(a)c/ against "ac". This sets group 1 as
+ part of the atomic group, but this is not on the final matching path,
+ so must be unset when 2 is set. (If there is no group 2, there is no
+ problem, because offset_top will then be 2, indicating no capture.) */
+
+ if (offset > offset_top)
+ {
+ register int *iptr = md->offset_vector + offset_top;
+ register int *iend = md->offset_vector + offset;
+ while (iptr < iend) *iptr++ = -1;
+ }
+
+ /* Now make the extraction */
+
+ md->offset_vector[offset] =
+ md->offset_vector[md->offset_end - number];
+ md->offset_vector[offset+1] = (int)(eptr - md->start_subject);
+ if (offset_top <= offset) offset_top = offset + 2;
+ }
+ }
+
+ /* For an ordinary non-repeating ket, just continue at this level. This
+ also happens for a repeating ket if no characters were matched in the
+ group. This is the forcible breaking of infinite loops as implemented in
+ Perl 5.005. For a non-repeating atomic group that includes captures,
+ establish a backup point by processing the rest of the pattern at a lower
+ level. If this results in a NOMATCH return, pass MATCH_ONCE back to the
+ original OP_ONCE level, thereby bypassing intermediate backup points, but
+ resetting any captures that happened along the way. */
+
+ if (*ecode == OP_KET || eptr == saved_eptr)
+ {
+ if (*prev == OP_ONCE)
+ {
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM12);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ md->once_target = prev; /* Level at which to change to MATCH_NOMATCH */
+ RRETURN(MATCH_ONCE);
+ }
+ ecode += 1 + LINK_SIZE; /* Carry on at this level */
+ break;
+ }
+
+ /* OP_KETRPOS is a possessive repeating ket. Remember the current position,
+ and return the MATCH_KETRPOS. This makes it possible to do the repeats one
+ at a time from the outer level, thus saving stack. */
+
+ if (*ecode == OP_KETRPOS)
+ {
+ md->start_match_ptr = mstart; /* In case \K reset it */
+ md->end_match_ptr = eptr;
+ md->end_offset_top = offset_top;
+ RRETURN(MATCH_KETRPOS);
+ }
+
+ /* The normal repeating kets try the rest of the pattern or restart from
+ the preceding bracket, in the appropriate order. In the second case, we can
+ use tail recursion to avoid using another stack frame, unless we have an
+ an atomic group or an unlimited repeat of a group that can match an empty
+ string. */
+
+ if (*ecode == OP_KETRMIN)
+ {
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM7);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (*prev == OP_ONCE)
+ {
+ RMATCH(eptr, prev, offset_top, md, eptrb, RM8);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ md->once_target = prev; /* Level at which to change to MATCH_NOMATCH */
+ RRETURN(MATCH_ONCE);
+ }
+ if (*prev >= OP_SBRA) /* Could match an empty string */
+ {
+ RMATCH(eptr, prev, offset_top, md, eptrb, RM50);
+ RRETURN(rrc);
+ }
+ ecode = prev;
+ goto TAIL_RECURSE;
+ }
+ else /* OP_KETRMAX */
+ {
+ RMATCH(eptr, prev, offset_top, md, eptrb, RM13);
+ if (rrc == MATCH_ONCE && md->once_target == prev) rrc = MATCH_NOMATCH;
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (*prev == OP_ONCE)
+ {
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM9);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ md->once_target = prev;
+ RRETURN(MATCH_ONCE);
+ }
+ ecode += 1 + LINK_SIZE;
+ goto TAIL_RECURSE;
+ }
+ /* Control never gets here */
+
+ /* Not multiline mode: start of subject assertion, unless notbol. */
+
+ case OP_CIRC:
+ if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH);
+
+ /* Start of subject assertion */
+
+ case OP_SOD:
+ if (eptr != md->start_subject) RRETURN(MATCH_NOMATCH);
+ ecode++;
+ break;
+
+ /* Multiline mode: start of subject unless notbol, or after any newline. */
+
+ case OP_CIRCM:
+ if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH);
+ if (eptr != md->start_subject &&
+ (eptr == md->end_subject || !WAS_NEWLINE(eptr)))
+ RRETURN(MATCH_NOMATCH);
+ ecode++;
+ break;
+
+ /* Start of match assertion */
+
+ case OP_SOM:
+ if (eptr != md->start_subject + md->start_offset) RRETURN(MATCH_NOMATCH);
+ ecode++;
+ break;
+
+ /* Reset the start of match point */
+
+ case OP_SET_SOM:
+ mstart = eptr;
+ ecode++;
+ break;
+
+ /* Multiline mode: assert before any newline, or before end of subject
+ unless noteol is set. */
+
+ case OP_DOLLM:
+ if (eptr < md->end_subject)
+ {
+ if (!IS_NEWLINE(eptr))
+ {
+ if (md->partial != 0 &&
+ eptr + 1 >= md->end_subject &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ UCHAR21TEST(eptr) == NLBLOCK->nl[0])
+ {
+ md->hitend = TRUE;
+ if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ }
+ RRETURN(MATCH_NOMATCH);
+ }
+ }
+ else
+ {
+ if (md->noteol) RRETURN(MATCH_NOMATCH);
+ SCHECK_PARTIAL();
+ }
+ ecode++;
+ break;
+
+ /* Not multiline mode: assert before a terminating newline or before end of
+ subject unless noteol is set. */
+
+ case OP_DOLL:
+ if (md->noteol) RRETURN(MATCH_NOMATCH);
+ if (!md->endonly) goto ASSERT_NL_OR_EOS;
+
+ /* ... else fall through for endonly */
+
+ /* End of subject assertion (\z) */
+
+ case OP_EOD:
+ if (eptr < md->end_subject) RRETURN(MATCH_NOMATCH);
+ SCHECK_PARTIAL();
+ ecode++;
+ break;
+
+ /* End of subject or ending \n assertion (\Z) */
+
+ case OP_EODN:
+ ASSERT_NL_OR_EOS:
+ if (eptr < md->end_subject &&
+ (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen))
+ {
+ if (md->partial != 0 &&
+ eptr + 1 >= md->end_subject &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ UCHAR21TEST(eptr) == NLBLOCK->nl[0])
+ {
+ md->hitend = TRUE;
+ if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ }
+ RRETURN(MATCH_NOMATCH);
+ }
+
+ /* Either at end of string or \n before end. */
+
+ SCHECK_PARTIAL();
+ ecode++;
+ break;
+
+ /* Word boundary assertions */
+
+ case OP_NOT_WORD_BOUNDARY:
+ case OP_WORD_BOUNDARY:
+ {
+
+ /* Find out if the previous and current characters are "word" characters.
+ It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to
+ be "non-word" characters. Remember the earliest consulted character for
+ partial matching. */
+
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ /* Get status of previous character */
+
+ if (eptr == md->start_subject) prev_is_word = FALSE; else
+ {
+ PCRE_PUCHAR lastptr = eptr - 1;
+ BACKCHAR(lastptr);
+ if (lastptr < md->start_used_ptr) md->start_used_ptr = lastptr;
+ GETCHAR(c, lastptr);
+#ifdef SUPPORT_UCP
+ if (md->use_ucp)
+ {
+ if (c == '_') prev_is_word = TRUE; else
+ {
+ int cat = UCD_CATEGORY(c);
+ prev_is_word = (cat == ucp_L || cat == ucp_N);
+ }
+ }
+ else
+#endif
+ prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
+ }
+
+ /* Get status of next character */
+
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ cur_is_word = FALSE;
+ }
+ else
+ {
+ GETCHAR(c, eptr);
+#ifdef SUPPORT_UCP
+ if (md->use_ucp)
+ {
+ if (c == '_') cur_is_word = TRUE; else
+ {
+ int cat = UCD_CATEGORY(c);
+ cur_is_word = (cat == ucp_L || cat == ucp_N);
+ }
+ }
+ else
+#endif
+ cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
+ }
+ }
+ else
+#endif
+
+ /* Not in UTF-8 mode, but we may still have PCRE_UCP set, and for
+ consistency with the behaviour of \w we do use it in this case. */
+
+ {
+ /* Get status of previous character */
+
+ if (eptr == md->start_subject) prev_is_word = FALSE; else
+ {
+ if (eptr <= md->start_used_ptr) md->start_used_ptr = eptr - 1;
+#ifdef SUPPORT_UCP
+ if (md->use_ucp)
+ {
+ c = eptr[-1];
+ if (c == '_') prev_is_word = TRUE; else
+ {
+ int cat = UCD_CATEGORY(c);
+ prev_is_word = (cat == ucp_L || cat == ucp_N);
+ }
+ }
+ else
+#endif
+ prev_is_word = MAX_255(eptr[-1])
+ && ((md->ctypes[eptr[-1]] & ctype_word) != 0);
+ }
+
+ /* Get status of next character */
+
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ cur_is_word = FALSE;
+ }
+ else
+#ifdef SUPPORT_UCP
+ if (md->use_ucp)
+ {
+ c = *eptr;
+ if (c == '_') cur_is_word = TRUE; else
+ {
+ int cat = UCD_CATEGORY(c);
+ cur_is_word = (cat == ucp_L || cat == ucp_N);
+ }
+ }
+ else
+#endif
+ cur_is_word = MAX_255(*eptr)
+ && ((md->ctypes[*eptr] & ctype_word) != 0);
+ }
+
+ /* Now see if the situation is what we want */
+
+ if ((*ecode++ == OP_WORD_BOUNDARY)?
+ cur_is_word == prev_is_word : cur_is_word != prev_is_word)
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ /* Match any single character type except newline; have to take care with
+ CRLF newlines and partial matching. */
+
+ case OP_ANY:
+ if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
+ if (md->partial != 0 &&
+ eptr + 1 >= md->end_subject &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ UCHAR21TEST(eptr) == NLBLOCK->nl[0])
+ {
+ md->hitend = TRUE;
+ if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ }
+
+ /* Fall through */
+
+ /* Match any single character whatsoever. */
+
+ case OP_ALLANY:
+ if (eptr >= md->end_subject) /* DO NOT merge the eptr++ here; it must */
+ { /* not be updated before SCHECK_PARTIAL. */
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ eptr++;
+#ifdef SUPPORT_UTF
+ if (utf) ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+#endif
+ ecode++;
+ break;
+
+ /* Match a single byte, even in UTF-8 mode. This opcode really does match
+ any byte, even newline, independent of the setting of PCRE_DOTALL. */
+
+ case OP_ANYBYTE:
+ if (eptr >= md->end_subject) /* DO NOT merge the eptr++ here; it must */
+ { /* not be updated before SCHECK_PARTIAL. */
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ eptr++;
+ ecode++;
+ break;
+
+ case OP_NOT_DIGIT:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if (
+#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
+ c < 256 &&
+#endif
+ (md->ctypes[c] & ctype_digit) != 0
+ )
+ RRETURN(MATCH_NOMATCH);
+ ecode++;
+ break;
+
+ case OP_DIGIT:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if (
+#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
+ c > 255 ||
+#endif
+ (md->ctypes[c] & ctype_digit) == 0
+ )
+ RRETURN(MATCH_NOMATCH);
+ ecode++;
+ break;
+
+ case OP_NOT_WHITESPACE:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if (
+#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
+ c < 256 &&
+#endif
+ (md->ctypes[c] & ctype_space) != 0
+ )
+ RRETURN(MATCH_NOMATCH);
+ ecode++;
+ break;
+
+ case OP_WHITESPACE:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if (
+#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
+ c > 255 ||
+#endif
+ (md->ctypes[c] & ctype_space) == 0
+ )
+ RRETURN(MATCH_NOMATCH);
+ ecode++;
+ break;
+
+ case OP_NOT_WORDCHAR:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if (
+#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
+ c < 256 &&
+#endif
+ (md->ctypes[c] & ctype_word) != 0
+ )
+ RRETURN(MATCH_NOMATCH);
+ ecode++;
+ break;
+
+ case OP_WORDCHAR:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if (
+#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
+ c > 255 ||
+#endif
+ (md->ctypes[c] & ctype_word) == 0
+ )
+ RRETURN(MATCH_NOMATCH);
+ ecode++;
+ break;
+
+ case OP_ANYNL:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ switch(c)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+
+ case CHAR_CR:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ }
+ else if (UCHAR21TEST(eptr) == CHAR_LF) eptr++;
+ break;
+
+ case CHAR_LF:
+ break;
+
+ case CHAR_VT:
+ case CHAR_FF:
+ case CHAR_NEL:
+#ifndef EBCDIC
+ case 0x2028:
+ case 0x2029:
+#endif /* Not EBCDIC */
+ if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+ break;
+ }
+ ecode++;
+ break;
+
+ case OP_NOT_HSPACE:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ switch(c)
+ {
+ HSPACE_CASES: RRETURN(MATCH_NOMATCH); /* Byte and multibyte cases */
+ default: break;
+ }
+ ecode++;
+ break;
+
+ case OP_HSPACE:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ switch(c)
+ {
+ HSPACE_CASES: break; /* Byte and multibyte cases */
+ default: RRETURN(MATCH_NOMATCH);
+ }
+ ecode++;
+ break;
+
+ case OP_NOT_VSPACE:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ switch(c)
+ {
+ VSPACE_CASES: RRETURN(MATCH_NOMATCH);
+ default: break;
+ }
+ ecode++;
+ break;
+
+ case OP_VSPACE:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ switch(c)
+ {
+ VSPACE_CASES: break;
+ default: RRETURN(MATCH_NOMATCH);
+ }
+ ecode++;
+ break;
+
+#ifdef SUPPORT_UCP
+ /* Check the next character by Unicode property. We will get here only
+ if the support is in the binary; otherwise a compile-time error occurs. */
+
+ case OP_PROP:
+ case OP_NOTPROP:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ {
+ const pcre_uint32 *cp;
+ const ucd_record *prop = GET_UCD(c);
+
+ switch(ecode[1])
+ {
+ case PT_ANY:
+ if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
+ break;
+
+ case PT_LAMP:
+ if ((prop->chartype == ucp_Lu ||
+ prop->chartype == ucp_Ll ||
+ prop->chartype == ucp_Lt) == (op == OP_NOTPROP))
+ RRETURN(MATCH_NOMATCH);
+ break;
+
+ case PT_GC:
+ if ((ecode[2] != PRIV(ucp_gentype)[prop->chartype]) == (op == OP_PROP))
+ RRETURN(MATCH_NOMATCH);
+ break;
+
+ case PT_PC:
+ if ((ecode[2] != prop->chartype) == (op == OP_PROP))
+ RRETURN(MATCH_NOMATCH);
+ break;
+
+ case PT_SC:
+ if ((ecode[2] != prop->script) == (op == OP_PROP))
+ RRETURN(MATCH_NOMATCH);
+ break;
+
+ /* These are specials */
+
+ case PT_ALNUM:
+ if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N) == (op == OP_NOTPROP))
+ RRETURN(MATCH_NOMATCH);
+ break;
+
+ /* Perl space used to exclude VT, but from Perl 5.18 it is included,
+ which means that Perl space and POSIX space are now identical. PCRE
+ was changed at release 8.34. */
+
+ case PT_SPACE: /* Perl space */
+ case PT_PXSPACE: /* POSIX space */
+ switch(c)
+ {
+ HSPACE_CASES:
+ VSPACE_CASES:
+ if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
+ break;
+
+ default:
+ if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) ==
+ (op == OP_NOTPROP)) RRETURN(MATCH_NOMATCH);
+ break;
+ }
+ break;
+
+ case PT_WORD:
+ if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
+ c == CHAR_UNDERSCORE) == (op == OP_NOTPROP))
+ RRETURN(MATCH_NOMATCH);
+ break;
+
+ case PT_CLIST:
+ cp = PRIV(ucd_caseless_sets) + ecode[2];
+ for (;;)
+ {
+ if (c < *cp)
+ { if (op == OP_PROP) { RRETURN(MATCH_NOMATCH); } else break; }
+ if (c == *cp++)
+ { if (op == OP_PROP) break; else { RRETURN(MATCH_NOMATCH); } }
+ }
+ break;
+
+ case PT_UCNC:
+ if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
+ c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
+ c >= 0xe000) == (op == OP_NOTPROP))
+ RRETURN(MATCH_NOMATCH);
+ break;
+
+ /* This should never occur */
+
+ default:
+ RRETURN(PCRE_ERROR_INTERNAL);
+ }
+
+ ecode += 3;
+ }
+ break;
+
+ /* Match an extended Unicode sequence. We will get here only if the support
+ is in the binary; otherwise a compile-time error occurs. */
+
+ case OP_EXTUNI:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ else
+ {
+ int lgb, rgb;
+ GETCHARINCTEST(c, eptr);
+ lgb = UCD_GRAPHBREAK(c);
+ while (eptr < md->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;
+ lgb = rgb;
+ eptr += len;
+ }
+ }
+ CHECK_PARTIAL();
+ ecode++;
+ break;
+#endif /* SUPPORT_UCP */
+
+
+ /* Match a back reference, possibly repeatedly. Look past the end of the
+ item to see if there is repeat information following. The code is similar
+ to that for character classes, but repeated for efficiency. Then obey
+ similar code to character type repeats - written out again for speed.
+ However, if the referenced string is the empty string, always treat
+ it as matched, any number of times (otherwise there could be infinite
+ loops). If the reference is unset, there are two possibilities:
+
+ (a) In the default, Perl-compatible state, set the length negative;
+ this ensures that every attempt at a match fails. We can't just fail
+ here, because of the possibility of quantifiers with zero minima.
+
+ (b) If the JavaScript compatibility flag is set, set the length to zero
+ so that the back reference matches an empty string.
+
+ Otherwise, set the length to the length of what was matched by the
+ referenced subpattern.
+
+ The OP_REF and OP_REFI opcodes are used for a reference to a numbered group
+ or to a non-duplicated named group. For a duplicated named group, OP_DNREF
+ and OP_DNREFI are used. In this case we must scan the list of groups to
+ which the name refers, and use the first one that is set. */
+
+ case OP_DNREF:
+ case OP_DNREFI:
+ caseless = op == OP_DNREFI;
+ {
+ int count = GET2(ecode, 1+IMM2_SIZE);
+ pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size;
+ ecode += 1 + 2*IMM2_SIZE;
+
+ /* Setting the default length first and initializing 'offset' avoids
+ compiler warnings in the REF_REPEAT code. */
+
+ length = (md->jscript_compat)? 0 : -1;
+ offset = 0;
+
+ while (count-- > 0)
+ {
+ offset = GET2(slot, 0) << 1;
+ if (offset < offset_top && md->offset_vector[offset] >= 0)
+ {
+ length = md->offset_vector[offset+1] - md->offset_vector[offset];
+ break;
+ }
+ slot += md->name_entry_size;
+ }
+ }
+ goto REF_REPEAT;
+
+ case OP_REF:
+ case OP_REFI:
+ caseless = op == OP_REFI;
+ offset = GET2(ecode, 1) << 1; /* Doubled ref number */
+ ecode += 1 + IMM2_SIZE;
+ if (offset >= offset_top || md->offset_vector[offset] < 0)
+ length = (md->jscript_compat)? 0 : -1;
+ else
+ length = md->offset_vector[offset+1] - md->offset_vector[offset];
+
+ /* Set up for repetition, or handle the non-repeated case */
+
+ REF_REPEAT:
+ switch (*ecode)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ c = *ecode++ - OP_CRSTAR;
+ minimize = (c & 1) != 0;
+ min = rep_min[c]; /* Pick up values from tables; */
+ max = rep_max[c]; /* zero for max => infinity */
+ if (max == 0) max = INT_MAX;
+ break;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ minimize = (*ecode == OP_CRMINRANGE);
+ min = GET2(ecode, 1);
+ max = GET2(ecode, 1 + IMM2_SIZE);
+ if (max == 0) max = INT_MAX;
+ ecode += 1 + 2 * IMM2_SIZE;
+ break;
+
+ default: /* No repeat follows */
+ if ((length = match_ref(offset, eptr, length, md, caseless)) < 0)
+ {
+ if (length == -2) eptr = md->end_subject; /* Partial match */
+ CHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ eptr += length;
+ continue; /* With the main loop */
+ }
+
+ /* Handle repeated back references. If the length of the reference is
+ zero, just continue with the main loop. If the length is negative, it
+ means the reference is unset in non-Java-compatible mode. If the minimum is
+ zero, we can continue at the same level without recursion. For any other
+ minimum, carrying on will result in NOMATCH. */
+
+ if (length == 0) continue;
+ if (length < 0 && min == 0) continue;
+
+ /* First, ensure the minimum number of matches are present. We get back
+ the length of the reference string explicitly rather than passing the
+ address of eptr, so that eptr can be a register variable. */
+
+ for (i = 1; i <= min; i++)
+ {
+ int slength;
+ if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0)
+ {
+ if (slength == -2) eptr = md->end_subject; /* Partial match */
+ CHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ eptr += slength;
+ }
+
+ /* If min = max, continue at the same level without recursion.
+ They are not both allowed to be zero. */
+
+ if (min == max) continue;
+
+ /* If minimizing, keep trying and advancing the pointer */
+
+ if (minimize)
+ {
+ for (fi = min;; fi++)
+ {
+ int slength;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM14);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0)
+ {
+ if (slength == -2) eptr = md->end_subject; /* Partial match */
+ CHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ eptr += slength;
+ }
+ /* Control never gets here */
+ }
+
+ /* If maximizing, find the longest string and work backwards */
+
+ else
+ {
+ pp = eptr;
+ for (i = min; i < max; i++)
+ {
+ int slength;
+ if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0)
+ {
+ /* Can't use CHECK_PARTIAL because we don't want to update eptr in
+ the soft partial matching case. */
+
+ if (slength == -2 && md->partial != 0 &&
+ md->end_subject > md->start_used_ptr)
+ {
+ md->hitend = TRUE;
+ if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ }
+ break;
+ }
+ eptr += slength;
+ }
+
+ while (eptr >= pp)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM15);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ eptr -= length;
+ }
+ RRETURN(MATCH_NOMATCH);
+ }
+ /* Control never gets here */
+
+ /* Match a bit-mapped character class, possibly repeatedly. This op code is
+ used when all the characters in the class have values in the range 0-255,
+ and either the matching is caseful, or the characters are in the range
+ 0-127 when UTF-8 processing is enabled. The only difference between
+ OP_CLASS and OP_NCLASS occurs when a data character outside the range is
+ encountered.
+
+ First, look past the end of the item to see if there is repeat information
+ following. Then obey similar code to character type repeats - written out
+ again for speed. */
+
+ case OP_NCLASS:
+ case OP_CLASS:
+ {
+ /* The data variable is saved across frames, so the byte map needs to
+ be stored there. */
+#define BYTE_MAP ((pcre_uint8 *)data)
+ data = ecode + 1; /* Save for matching */
+ ecode += 1 + (32 / sizeof(pcre_uchar)); /* Advance past the item */
+
+ switch (*ecode)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ case OP_CRPOSSTAR:
+ case OP_CRPOSPLUS:
+ case OP_CRPOSQUERY:
+ c = *ecode++ - OP_CRSTAR;
+ if (c < OP_CRPOSSTAR - OP_CRSTAR) minimize = (c & 1) != 0;
+ else possessive = TRUE;
+ min = rep_min[c]; /* Pick up values from tables; */
+ max = rep_max[c]; /* zero for max => infinity */
+ if (max == 0) max = INT_MAX;
+ break;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ case OP_CRPOSRANGE:
+ minimize = (*ecode == OP_CRMINRANGE);
+ possessive = (*ecode == OP_CRPOSRANGE);
+ min = GET2(ecode, 1);
+ max = GET2(ecode, 1 + IMM2_SIZE);
+ if (max == 0) max = INT_MAX;
+ ecode += 1 + 2 * IMM2_SIZE;
+ break;
+
+ default: /* No repeat follows */
+ min = max = 1;
+ break;
+ }
+
+ /* First, ensure the minimum number of matches are present. */
+
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINC(c, eptr);
+ if (c > 255)
+ {
+ if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
+ }
+ else
+ if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
+ }
+ }
+ else
+#endif
+ /* Not UTF mode */
+ {
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ c = *eptr++;
+#ifndef COMPILE_PCRE8
+ if (c > 255)
+ {
+ if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
+ }
+ else
+#endif
+ if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
+ }
+ }
+
+ /* If max == min we can continue with the main loop without the
+ need to recurse. */
+
+ if (min == max) continue;
+
+ /* If minimizing, keep testing the rest of the expression and advancing
+ the pointer while it matches the class. */
+
+ if (minimize)
+ {
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM16);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINC(c, eptr);
+ if (c > 255)
+ {
+ if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
+ }
+ else
+ if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
+ }
+ }
+ else
+#endif
+ /* Not UTF mode */
+ {
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM17);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ c = *eptr++;
+#ifndef COMPILE_PCRE8
+ if (c > 255)
+ {
+ if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
+ }
+ else
+#endif
+ if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
+ }
+ }
+ /* Control never gets here */
+ }
+
+ /* If maximizing, find the longest possible run, then work backwards. */
+
+ else
+ {
+ pp = eptr;
+
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLEN(c, eptr, len);
+ if (c > 255)
+ {
+ if (op == OP_CLASS) break;
+ }
+ else
+ if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break;
+ eptr += len;
+ }
+
+ if (possessive) continue; /* No backtracking */
+
+ for (;;)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM18);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (eptr-- == pp) break; /* Stop if tried at original pos */
+ BACKCHAR(eptr);
+ }
+ }
+ else
+#endif
+ /* Not UTF mode */
+ {
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ c = *eptr;
+#ifndef COMPILE_PCRE8
+ if (c > 255)
+ {
+ if (op == OP_CLASS) break;
+ }
+ else
+#endif
+ if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break;
+ eptr++;
+ }
+
+ if (possessive) continue; /* No backtracking */
+
+ while (eptr >= pp)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM19);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ eptr--;
+ }
+ }
+
+ RRETURN(MATCH_NOMATCH);
+ }
+#undef BYTE_MAP
+ }
+ /* Control never gets here */
+
+
+ /* Match an extended character class. In the 8-bit library, this opcode is
+ encountered only when UTF-8 mode mode is supported. In the 16-bit and
+ 32-bit libraries, codepoints greater than 255 may be encountered even when
+ UTF is not supported. */
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+ {
+ data = ecode + 1 + LINK_SIZE; /* Save for matching */
+ ecode += GET(ecode, 1); /* Advance past the item */
+
+ switch (*ecode)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ case OP_CRPOSSTAR:
+ case OP_CRPOSPLUS:
+ case OP_CRPOSQUERY:
+ c = *ecode++ - OP_CRSTAR;
+ if (c < OP_CRPOSSTAR - OP_CRSTAR) minimize = (c & 1) != 0;
+ else possessive = TRUE;
+ min = rep_min[c]; /* Pick up values from tables; */
+ max = rep_max[c]; /* zero for max => infinity */
+ if (max == 0) max = INT_MAX;
+ break;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ case OP_CRPOSRANGE:
+ minimize = (*ecode == OP_CRMINRANGE);
+ possessive = (*ecode == OP_CRPOSRANGE);
+ min = GET2(ecode, 1);
+ max = GET2(ecode, 1 + IMM2_SIZE);
+ if (max == 0) max = INT_MAX;
+ ecode += 1 + 2 * IMM2_SIZE;
+ break;
+
+ default: /* No repeat follows */
+ min = max = 1;
+ break;
+ }
+
+ /* First, ensure the minimum number of matches are present. */
+
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if (!PRIV(xclass)(c, data, utf)) RRETURN(MATCH_NOMATCH);
+ }
+
+ /* If max == min we can continue with the main loop without the
+ need to recurse. */
+
+ if (min == max) continue;
+
+ /* If minimizing, keep testing the rest of the expression and advancing
+ the pointer while it matches the class. */
+
+ if (minimize)
+ {
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM20);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if (!PRIV(xclass)(c, data, utf)) RRETURN(MATCH_NOMATCH);
+ }
+ /* Control never gets here */
+ }
+
+ /* If maximizing, find the longest possible run, then work backwards. */
+
+ else
+ {
+ pp = eptr;
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+#ifdef SUPPORT_UTF
+ GETCHARLENTEST(c, eptr, len);
+#else
+ c = *eptr;
+#endif
+ if (!PRIV(xclass)(c, data, utf)) break;
+ eptr += len;
+ }
+
+ if (possessive) continue; /* No backtracking */
+
+ for(;;)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM21);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (eptr-- == pp) break; /* Stop if tried at original pos */
+#ifdef SUPPORT_UTF
+ if (utf) BACKCHAR(eptr);
+#endif
+ }
+ RRETURN(MATCH_NOMATCH);
+ }
+
+ /* Control never gets here */
+ }
+#endif /* End of XCLASS */
+
+ /* Match a single character, casefully */
+
+ case OP_CHAR:
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ length = 1;
+ ecode++;
+ GETCHARLEN(fc, ecode, length);
+ if (length > md->end_subject - eptr)
+ {
+ CHECK_PARTIAL(); /* Not SCHECK_PARTIAL() */
+ RRETURN(MATCH_NOMATCH);
+ }
+ while (length-- > 0) if (*ecode++ != UCHAR21INC(eptr)) RRETURN(MATCH_NOMATCH);
+ }
+ else
+#endif
+ /* Not UTF mode */
+ {
+ if (md->end_subject - eptr < 1)
+ {
+ SCHECK_PARTIAL(); /* This one can use SCHECK_PARTIAL() */
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH);
+ ecode += 2;
+ }
+ break;
+
+ /* Match a single character, caselessly. If we are at the end of the
+ subject, give up immediately. */
+
+ case OP_CHARI:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ length = 1;
+ ecode++;
+ GETCHARLEN(fc, ecode, length);
+
+ /* If the pattern character's value is < 128, we have only one byte, and
+ we know that its other case must also be one byte long, so we can use the
+ fast lookup table. We know that there is at least one byte left in the
+ subject. */
+
+ if (fc < 128)
+ {
+ pcre_uint32 cc = UCHAR21(eptr);
+ if (md->lcc[fc] != TABLE_GET(cc, md->lcc, cc)) RRETURN(MATCH_NOMATCH);
+ ecode++;
+ eptr++;
+ }
+
+ /* Otherwise we must pick up the subject character. Note that we cannot
+ use the value of "length" to check for sufficient bytes left, because the
+ other case of the character may have more or fewer bytes. */
+
+ else
+ {
+ pcre_uint32 dc;
+ GETCHARINC(dc, eptr);
+ ecode += length;
+
+ /* If we have Unicode property support, we can use it to test the other
+ case of the character, if there is one. */
+
+ if (fc != dc)
+ {
+#ifdef SUPPORT_UCP
+ if (dc != UCD_OTHERCASE(fc))
+#endif
+ RRETURN(MATCH_NOMATCH);
+ }
+ }
+ }
+ else
+#endif /* SUPPORT_UTF */
+
+ /* Not UTF mode */
+ {
+ if (TABLE_GET(ecode[1], md->lcc, ecode[1])
+ != TABLE_GET(*eptr, md->lcc, *eptr)) RRETURN(MATCH_NOMATCH);
+ eptr++;
+ ecode += 2;
+ }
+ break;
+
+ /* Match a single character repeatedly. */
+
+ case OP_EXACT:
+ case OP_EXACTI:
+ min = max = GET2(ecode, 1);
+ ecode += 1 + IMM2_SIZE;
+ goto REPEATCHAR;
+
+ case OP_POSUPTO:
+ case OP_POSUPTOI:
+ possessive = TRUE;
+ /* Fall through */
+
+ case OP_UPTO:
+ case OP_UPTOI:
+ case OP_MINUPTO:
+ case OP_MINUPTOI:
+ min = 0;
+ max = GET2(ecode, 1);
+ minimize = *ecode == OP_MINUPTO || *ecode == OP_MINUPTOI;
+ ecode += 1 + IMM2_SIZE;
+ goto REPEATCHAR;
+
+ case OP_POSSTAR:
+ case OP_POSSTARI:
+ possessive = TRUE;
+ min = 0;
+ max = INT_MAX;
+ ecode++;
+ goto REPEATCHAR;
+
+ case OP_POSPLUS:
+ case OP_POSPLUSI:
+ possessive = TRUE;
+ min = 1;
+ max = INT_MAX;
+ ecode++;
+ goto REPEATCHAR;
+
+ case OP_POSQUERY:
+ case OP_POSQUERYI:
+ possessive = TRUE;
+ min = 0;
+ max = 1;
+ ecode++;
+ goto REPEATCHAR;
+
+ case OP_STAR:
+ case OP_STARI:
+ case OP_MINSTAR:
+ case OP_MINSTARI:
+ case OP_PLUS:
+ case OP_PLUSI:
+ case OP_MINPLUS:
+ case OP_MINPLUSI:
+ case OP_QUERY:
+ case OP_QUERYI:
+ case OP_MINQUERY:
+ case OP_MINQUERYI:
+ c = *ecode++ - ((op < OP_STARI)? OP_STAR : OP_STARI);
+ minimize = (c & 1) != 0;
+ min = rep_min[c]; /* Pick up values from tables; */
+ max = rep_max[c]; /* zero for max => infinity */
+ if (max == 0) max = INT_MAX;
+
+ /* Common code for all repeated single-character matches. We first check
+ for the minimum number of characters. If the minimum equals the maximum, we
+ are done. Otherwise, if minimizing, check the rest of the pattern for a
+ match; if there isn't one, advance up to the maximum, one character at a
+ time.
+
+ If maximizing, advance up to the maximum number of matching characters,
+ until eptr is past the end of the maximum run. If possessive, we are
+ then done (no backing up). Otherwise, match at this position; anything
+ other than no match is immediately returned. For nomatch, back up one
+ character, unless we are matching \R and the last thing matched was
+ \r\n, in which case, back up two bytes. When we reach the first optional
+ character position, we can save stack by doing a tail recurse.
+
+ The various UTF/non-UTF and caseful/caseless cases are handled separately,
+ for speed. */
+
+ REPEATCHAR:
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ length = 1;
+ charptr = ecode;
+ GETCHARLEN(fc, ecode, length);
+ ecode += length;
+
+ /* Handle multibyte character matching specially here. There is
+ support for caseless matching if UCP support is present. */
+
+ if (length > 1)
+ {
+#ifdef SUPPORT_UCP
+ pcre_uint32 othercase;
+ if (op >= OP_STARI && /* Caseless */
+ (othercase = UCD_OTHERCASE(fc)) != fc)
+ oclength = PRIV(ord2utf)(othercase, occhars);
+ else oclength = 0;
+#endif /* SUPPORT_UCP */
+
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr <= md->end_subject - length &&
+ memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length;
+#ifdef SUPPORT_UCP
+ else if (oclength > 0 &&
+ eptr <= md->end_subject - oclength &&
+ memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength;
+#endif /* SUPPORT_UCP */
+ else
+ {
+ CHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ }
+
+ if (min == max) continue;
+
+ if (minimize)
+ {
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM22);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr <= md->end_subject - length &&
+ memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length;
+#ifdef SUPPORT_UCP
+ else if (oclength > 0 &&
+ eptr <= md->end_subject - oclength &&
+ memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength;
+#endif /* SUPPORT_UCP */
+ else
+ {
+ CHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ }
+ /* Control never gets here */
+ }
+
+ else /* Maximize */
+ {
+ pp = eptr;
+ for (i = min; i < max; i++)
+ {
+ if (eptr <= md->end_subject - length &&
+ memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length;
+#ifdef SUPPORT_UCP
+ else if (oclength > 0 &&
+ eptr <= md->end_subject - oclength &&
+ memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength;
+#endif /* SUPPORT_UCP */
+ else
+ {
+ CHECK_PARTIAL();
+ break;
+ }
+ }
+
+ if (possessive) continue; /* No backtracking */
+ for(;;)
+ {
+ if (eptr == pp) goto TAIL_RECURSE;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM23);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+#ifdef SUPPORT_UCP
+ eptr--;
+ BACKCHAR(eptr);
+#else /* without SUPPORT_UCP */
+ eptr -= length;
+#endif /* SUPPORT_UCP */
+ }
+ }
+ /* Control never gets here */
+ }
+
+ /* If the length of a UTF-8 character is 1, we fall through here, and
+ obey the code as for non-UTF-8 characters below, though in this case the
+ value of fc will always be < 128. */
+ }
+ else
+#endif /* SUPPORT_UTF */
+ /* When not in UTF-8 mode, load a single-byte character. */
+ fc = *ecode++;
+
+ /* The value of fc at this point is always one character, though we may
+ or may not be in UTF mode. The code is duplicated for the caseless and
+ caseful cases, for speed, since matching characters is likely to be quite
+ common. First, ensure the minimum number of matches are present. If min =
+ max, continue at the same level without recursing. Otherwise, if
+ minimizing, keep trying the rest of the expression and advancing one
+ matching character if failing, up to the maximum. Alternatively, if
+ maximizing, find the maximum number of characters and work backwards. */
+
+ DPRINTF(("matching %c{%d,%d} against subject %.*s\n", fc, min, max,
+ max, (char *)eptr));
+
+ if (op >= OP_STARI) /* Caseless */
+ {
+#ifdef COMPILE_PCRE8
+ /* fc must be < 128 if UTF is enabled. */
+ foc = md->fcc[fc];
+#else
+#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UCP
+ if (utf && fc > 127)
+ foc = UCD_OTHERCASE(fc);
+#else
+ if (utf && fc > 127)
+ foc = fc;
+#endif /* SUPPORT_UCP */
+ else
+#endif /* SUPPORT_UTF */
+ foc = TABLE_GET(fc, md->fcc, fc);
+#endif /* COMPILE_PCRE8 */
+
+ for (i = 1; i <= min; i++)
+ {
+ pcre_uint32 cc; /* Faster than pcre_uchar */
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ cc = UCHAR21TEST(eptr);
+ if (fc != cc && foc != cc) RRETURN(MATCH_NOMATCH);
+ eptr++;
+ }
+ if (min == max) continue;
+ if (minimize)
+ {
+ for (fi = min;; fi++)
+ {
+ pcre_uint32 cc; /* Faster than pcre_uchar */
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM24);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ cc = UCHAR21TEST(eptr);
+ if (fc != cc && foc != cc) RRETURN(MATCH_NOMATCH);
+ eptr++;
+ }
+ /* Control never gets here */
+ }
+ else /* Maximize */
+ {
+ pp = eptr;
+ for (i = min; i < max; i++)
+ {
+ pcre_uint32 cc; /* Faster than pcre_uchar */
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ cc = UCHAR21TEST(eptr);
+ if (fc != cc && foc != cc) break;
+ eptr++;
+ }
+ if (possessive) continue; /* No backtracking */
+ for (;;)
+ {
+ if (eptr == pp) goto TAIL_RECURSE;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM25);
+ eptr--;
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ }
+ /* Control never gets here */
+ }
+ }
+
+ /* Caseful comparisons (includes all multi-byte characters) */
+
+ else
+ {
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (fc != UCHAR21INCTEST(eptr)) RRETURN(MATCH_NOMATCH);
+ }
+
+ if (min == max) continue;
+
+ if (minimize)
+ {
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM26);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (fc != UCHAR21INCTEST(eptr)) RRETURN(MATCH_NOMATCH);
+ }
+ /* Control never gets here */
+ }
+ else /* Maximize */
+ {
+ pp = eptr;
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ if (fc != UCHAR21TEST(eptr)) break;
+ eptr++;
+ }
+ if (possessive) continue; /* No backtracking */
+ for (;;)
+ {
+ if (eptr == pp) goto TAIL_RECURSE;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM27);
+ eptr--;
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ }
+ /* Control never gets here */
+ }
+ }
+ /* Control never gets here */
+
+ /* Match a negated single one-byte character. The character we are
+ checking can be multibyte. */
+
+ case OP_NOT:
+ case OP_NOTI:
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ register pcre_uint32 ch, och;
+
+ ecode++;
+ GETCHARINC(ch, ecode);
+ GETCHARINC(c, eptr);
+
+ if (op == OP_NOT)
+ {
+ if (ch == c) RRETURN(MATCH_NOMATCH);
+ }
+ else
+ {
+#ifdef SUPPORT_UCP
+ if (ch > 127)
+ och = UCD_OTHERCASE(ch);
+#else
+ if (ch > 127)
+ och = ch;
+#endif /* SUPPORT_UCP */
+ else
+ och = TABLE_GET(ch, md->fcc, ch);
+ if (ch == c || och == c) RRETURN(MATCH_NOMATCH);
+ }
+ }
+ else
+#endif
+ {
+ register pcre_uint32 ch = ecode[1];
+ c = *eptr++;
+ if (ch == c || (op == OP_NOTI && TABLE_GET(ch, md->fcc, ch) == c))
+ RRETURN(MATCH_NOMATCH);
+ ecode += 2;
+ }
+ break;
+
+ /* Match a negated single one-byte character repeatedly. This is almost a
+ repeat of the code for a repeated single character, but I haven't found a
+ nice way of commoning these up that doesn't require a test of the
+ positive/negative option for each character match. Maybe that wouldn't add
+ very much to the time taken, but character matching *is* what this is all
+ about... */
+
+ case OP_NOTEXACT:
+ case OP_NOTEXACTI:
+ min = max = GET2(ecode, 1);
+ ecode += 1 + IMM2_SIZE;
+ goto REPEATNOTCHAR;
+
+ case OP_NOTUPTO:
+ case OP_NOTUPTOI:
+ case OP_NOTMINUPTO:
+ case OP_NOTMINUPTOI:
+ min = 0;
+ max = GET2(ecode, 1);
+ minimize = *ecode == OP_NOTMINUPTO || *ecode == OP_NOTMINUPTOI;
+ ecode += 1 + IMM2_SIZE;
+ goto REPEATNOTCHAR;
+
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSSTARI:
+ possessive = TRUE;
+ min = 0;
+ max = INT_MAX;
+ ecode++;
+ goto REPEATNOTCHAR;
+
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSPLUSI:
+ possessive = TRUE;
+ min = 1;
+ max = INT_MAX;
+ ecode++;
+ goto REPEATNOTCHAR;
+
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSQUERYI:
+ possessive = TRUE;
+ min = 0;
+ max = 1;
+ ecode++;
+ goto REPEATNOTCHAR;
+
+ case OP_NOTPOSUPTO:
+ case OP_NOTPOSUPTOI:
+ possessive = TRUE;
+ min = 0;
+ max = GET2(ecode, 1);
+ ecode += 1 + IMM2_SIZE;
+ goto REPEATNOTCHAR;
+
+ case OP_NOTSTAR:
+ case OP_NOTSTARI:
+ case OP_NOTMINSTAR:
+ case OP_NOTMINSTARI:
+ case OP_NOTPLUS:
+ case OP_NOTPLUSI:
+ case OP_NOTMINPLUS:
+ case OP_NOTMINPLUSI:
+ case OP_NOTQUERY:
+ case OP_NOTQUERYI:
+ case OP_NOTMINQUERY:
+ case OP_NOTMINQUERYI:
+ c = *ecode++ - ((op >= OP_NOTSTARI)? OP_NOTSTARI: OP_NOTSTAR);
+ minimize = (c & 1) != 0;
+ min = rep_min[c]; /* Pick up values from tables; */
+ max = rep_max[c]; /* zero for max => infinity */
+ if (max == 0) max = INT_MAX;
+
+ /* Common code for all repeated single-byte matches. */
+
+ REPEATNOTCHAR:
+ GETCHARINCTEST(fc, ecode);
+
+ /* The code is duplicated for the caseless and caseful cases, for speed,
+ since matching characters is likely to be quite common. First, ensure the
+ minimum number of matches are present. If min = max, continue at the same
+ level without recursing. Otherwise, if minimizing, keep trying the rest of
+ the expression and advancing one matching character if failing, up to the
+ maximum. Alternatively, if maximizing, find the maximum number of
+ characters and work backwards. */
+
+ DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", fc, min, max,
+ max, (char *)eptr));
+
+ if (op >= OP_NOTSTARI) /* Caseless */
+ {
+#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UCP
+ if (utf && fc > 127)
+ foc = UCD_OTHERCASE(fc);
+#else
+ if (utf && fc > 127)
+ foc = fc;
+#endif /* SUPPORT_UCP */
+ else
+#endif /* SUPPORT_UTF */
+ foc = TABLE_GET(fc, md->fcc, fc);
+
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ register pcre_uint32 d;
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINC(d, eptr);
+ if (fc == d || (unsigned int)foc == d) RRETURN(MATCH_NOMATCH);
+ }
+ }
+ else
+#endif /* SUPPORT_UTF */
+ /* Not UTF mode */
+ {
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (fc == *eptr || foc == *eptr) RRETURN(MATCH_NOMATCH);
+ eptr++;
+ }
+ }
+
+ if (min == max) continue;
+
+ if (minimize)
+ {
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ register pcre_uint32 d;
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM28);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINC(d, eptr);
+ if (fc == d || (unsigned int)foc == d) RRETURN(MATCH_NOMATCH);
+ }
+ }
+ else
+#endif /*SUPPORT_UTF */
+ /* Not UTF mode */
+ {
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM29);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (fc == *eptr || foc == *eptr) RRETURN(MATCH_NOMATCH);
+ eptr++;
+ }
+ }
+ /* Control never gets here */
+ }
+
+ /* Maximize case */
+
+ else
+ {
+ pp = eptr;
+
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ register pcre_uint32 d;
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLEN(d, eptr, len);
+ if (fc == d || (unsigned int)foc == d) break;
+ eptr += len;
+ }
+ if (possessive) continue; /* No backtracking */
+ for(;;)
+ {
+ if (eptr == pp) goto TAIL_RECURSE;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM30);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ eptr--;
+ BACKCHAR(eptr);
+ }
+ }
+ else
+#endif /* SUPPORT_UTF */
+ /* Not UTF mode */
+ {
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ if (fc == *eptr || foc == *eptr) break;
+ eptr++;
+ }
+ if (possessive) continue; /* No backtracking */
+ for (;;)
+ {
+ if (eptr == pp) goto TAIL_RECURSE;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM31);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ eptr--;
+ }
+ }
+ /* Control never gets here */
+ }
+ }
+
+ /* Caseful comparisons */
+
+ else
+ {
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ register pcre_uint32 d;
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINC(d, eptr);
+ if (fc == d) RRETURN(MATCH_NOMATCH);
+ }
+ }
+ else
+#endif
+ /* Not UTF mode */
+ {
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (fc == *eptr++) RRETURN(MATCH_NOMATCH);
+ }
+ }
+
+ if (min == max) continue;
+
+ if (minimize)
+ {
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ register pcre_uint32 d;
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM32);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINC(d, eptr);
+ if (fc == d) RRETURN(MATCH_NOMATCH);
+ }
+ }
+ else
+#endif
+ /* Not UTF mode */
+ {
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM33);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (fc == *eptr++) RRETURN(MATCH_NOMATCH);
+ }
+ }
+ /* Control never gets here */
+ }
+
+ /* Maximize case */
+
+ else
+ {
+ pp = eptr;
+
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ register pcre_uint32 d;
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLEN(d, eptr, len);
+ if (fc == d) break;
+ eptr += len;
+ }
+ if (possessive) continue; /* No backtracking */
+ for(;;)
+ {
+ if (eptr == pp) goto TAIL_RECURSE;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM34);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ eptr--;
+ BACKCHAR(eptr);
+ }
+ }
+ else
+#endif
+ /* Not UTF mode */
+ {
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ if (fc == *eptr) break;
+ eptr++;
+ }
+ if (possessive) continue; /* No backtracking */
+ for (;;)
+ {
+ if (eptr == pp) goto TAIL_RECURSE;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM35);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ eptr--;
+ }
+ }
+ /* Control never gets here */
+ }
+ }
+ /* Control never gets here */
+
+ /* Match a single character type repeatedly; several different opcodes
+ share code. This is very similar to the code for single characters, but we
+ repeat it in the interests of efficiency. */
+
+ case OP_TYPEEXACT:
+ min = max = GET2(ecode, 1);
+ minimize = TRUE;
+ ecode += 1 + IMM2_SIZE;
+ goto REPEATTYPE;
+
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ min = 0;
+ max = GET2(ecode, 1);
+ minimize = *ecode == OP_TYPEMINUPTO;
+ ecode += 1 + IMM2_SIZE;
+ goto REPEATTYPE;
+
+ case OP_TYPEPOSSTAR:
+ possessive = TRUE;
+ min = 0;
+ max = INT_MAX;
+ ecode++;
+ goto REPEATTYPE;
+
+ case OP_TYPEPOSPLUS:
+ possessive = TRUE;
+ min = 1;
+ max = INT_MAX;
+ ecode++;
+ goto REPEATTYPE;
+
+ case OP_TYPEPOSQUERY:
+ possessive = TRUE;
+ min = 0;
+ max = 1;
+ ecode++;
+ goto REPEATTYPE;
+
+ case OP_TYPEPOSUPTO:
+ possessive = TRUE;
+ min = 0;
+ max = GET2(ecode, 1);
+ ecode += 1 + IMM2_SIZE;
+ goto REPEATTYPE;
+
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ c = *ecode++ - OP_TYPESTAR;
+ minimize = (c & 1) != 0;
+ min = rep_min[c]; /* Pick up values from tables; */
+ max = rep_max[c]; /* zero for max => infinity */
+ if (max == 0) max = INT_MAX;
+
+ /* Common code for all repeated single character type matches. Note that
+ in UTF-8 mode, '.' matches a character of any length, but for the other
+ character types, the valid characters are all one-byte long. */
+
+ REPEATTYPE:
+ ctype = *ecode++; /* Code for the character type */
+
+#ifdef SUPPORT_UCP
+ if (ctype == OP_PROP || ctype == OP_NOTPROP)
+ {
+ prop_fail_result = ctype == OP_NOTPROP;
+ prop_type = *ecode++;
+ prop_value = *ecode++;
+ }
+ else prop_type = -1;
+#endif
+
+ /* First, ensure the minimum number of matches are present. Use inline
+ code for maximizing the speed, and do the type test once at the start
+ (i.e. keep it out of the loop). Separate the UTF-8 code completely as that
+ is tidier. Also separate the UCP code, which can be the same for both UTF-8
+ and single-bytes. */
+
+ if (min > 0)
+ {
+#ifdef SUPPORT_UCP
+ if (prop_type >= 0)
+ {
+ switch(prop_type)
+ {
+ case PT_ANY:
+ if (prop_fail_result) RRETURN(MATCH_NOMATCH);
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ }
+ break;
+
+ case PT_LAMP:
+ for (i = 1; i <= min; i++)
+ {
+ int chartype;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ chartype = UCD_CHARTYPE(c);
+ if ((chartype == ucp_Lu ||
+ chartype == ucp_Ll ||
+ chartype == ucp_Lt) == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case PT_GC:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case PT_PC:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case PT_SC:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case PT_ALNUM:
+ for (i = 1; i <= min; i++)
+ {
+ int category;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ category = UCD_CATEGORY(c);
+ if ((category == ucp_L || category == ucp_N) == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ /* Perl space used to exclude VT, but from Perl 5.18 it is included,
+ which means that Perl space and POSIX space are now identical. PCRE
+ was changed at release 8.34. */
+
+ case PT_SPACE: /* Perl space */
+ case PT_PXSPACE: /* POSIX space */
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ switch(c)
+ {
+ HSPACE_CASES:
+ VSPACE_CASES:
+ if (prop_fail_result) RRETURN(MATCH_NOMATCH);
+ break;
+
+ default:
+ if ((UCD_CATEGORY(c) == ucp_Z) == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ break;
+ }
+ }
+ break;
+
+ case PT_WORD:
+ for (i = 1; i <= min; i++)
+ {
+ int category;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ category = UCD_CATEGORY(c);
+ if ((category == ucp_L || category == ucp_N || c == CHAR_UNDERSCORE)
+ == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case PT_CLIST:
+ for (i = 1; i <= min; i++)
+ {
+ const pcre_uint32 *cp;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ cp = PRIV(ucd_caseless_sets) + prop_value;
+ for (;;)
+ {
+ if (c < *cp)
+ { if (prop_fail_result) break; else { RRETURN(MATCH_NOMATCH); } }
+ if (c == *cp++)
+ { if (prop_fail_result) { RRETURN(MATCH_NOMATCH); } else break; }
+ }
+ }
+ break;
+
+ case PT_UCNC:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
+ c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
+ c >= 0xe000) == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ /* This should not occur */
+
+ default:
+ RRETURN(PCRE_ERROR_INTERNAL);
+ }
+ }
+
+ /* Match extended Unicode sequences. We will get here only if the
+ support is in the binary; otherwise a compile-time error occurs. */
+
+ else if (ctype == OP_EXTUNI)
+ {
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ else
+ {
+ int lgb, rgb;
+ GETCHARINCTEST(c, eptr);
+ lgb = UCD_GRAPHBREAK(c);
+ while (eptr < md->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;
+ lgb = rgb;
+ eptr += len;
+ }
+ }
+ CHECK_PARTIAL();
+ }
+ }
+
+ else
+#endif /* SUPPORT_UCP */
+
+/* Handle all other cases when the coding is UTF-8 */
+
+#ifdef SUPPORT_UTF
+ if (utf) switch(ctype)
+ {
+ case OP_ANY:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
+ if (md->partial != 0 &&
+ eptr + 1 >= md->end_subject &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ UCHAR21(eptr) == NLBLOCK->nl[0])
+ {
+ md->hitend = TRUE;
+ if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ }
+ eptr++;
+ ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+ }
+ break;
+
+ case OP_ALLANY:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ eptr++;
+ ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+ }
+ break;
+
+ case OP_ANYBYTE:
+ if (eptr > md->end_subject - min) RRETURN(MATCH_NOMATCH);
+ eptr += min;
+ break;
+
+ case OP_ANYNL:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINC(c, eptr);
+ switch(c)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+
+ case CHAR_CR:
+ if (eptr < md->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++;
+ break;
+
+ case CHAR_LF:
+ break;
+
+ case CHAR_VT:
+ case CHAR_FF:
+ case CHAR_NEL:
+#ifndef EBCDIC
+ case 0x2028:
+ case 0x2029:
+#endif /* Not EBCDIC */
+ if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+ break;
+ }
+ }
+ break;
+
+ case OP_NOT_HSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINC(c, eptr);
+ switch(c)
+ {
+ HSPACE_CASES: RRETURN(MATCH_NOMATCH); /* Byte and multibyte cases */
+ default: break;
+ }
+ }
+ break;
+
+ case OP_HSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINC(c, eptr);
+ switch(c)
+ {
+ HSPACE_CASES: break; /* Byte and multibyte cases */
+ default: RRETURN(MATCH_NOMATCH);
+ }
+ }
+ break;
+
+ case OP_NOT_VSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINC(c, eptr);
+ switch(c)
+ {
+ VSPACE_CASES: RRETURN(MATCH_NOMATCH);
+ default: break;
+ }
+ }
+ break;
+
+ case OP_VSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINC(c, eptr);
+ switch(c)
+ {
+ VSPACE_CASES: break;
+ default: RRETURN(MATCH_NOMATCH);
+ }
+ }
+ break;
+
+ case OP_NOT_DIGIT:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINC(c, eptr);
+ if (c < 128 && (md->ctypes[c] & ctype_digit) != 0)
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case OP_DIGIT:
+ for (i = 1; i <= min; i++)
+ {
+ pcre_uint32 cc;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ cc = UCHAR21(eptr);
+ if (cc >= 128 || (md->ctypes[cc] & ctype_digit) == 0)
+ RRETURN(MATCH_NOMATCH);
+ eptr++;
+ /* No need to skip more bytes - we know it's a 1-byte character */
+ }
+ break;
+
+ case OP_NOT_WHITESPACE:
+ for (i = 1; i <= min; i++)
+ {
+ pcre_uint32 cc;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ cc = UCHAR21(eptr);
+ if (cc < 128 && (md->ctypes[cc] & ctype_space) != 0)
+ RRETURN(MATCH_NOMATCH);
+ eptr++;
+ ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+ }
+ break;
+
+ case OP_WHITESPACE:
+ for (i = 1; i <= min; i++)
+ {
+ pcre_uint32 cc;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ cc = UCHAR21(eptr);
+ if (cc >= 128 || (md->ctypes[cc] & ctype_space) == 0)
+ RRETURN(MATCH_NOMATCH);
+ eptr++;
+ /* No need to skip more bytes - we know it's a 1-byte character */
+ }
+ break;
+
+ case OP_NOT_WORDCHAR:
+ for (i = 1; i <= min; i++)
+ {
+ pcre_uint32 cc;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ cc = UCHAR21(eptr);
+ if (cc < 128 && (md->ctypes[cc] & ctype_word) != 0)
+ RRETURN(MATCH_NOMATCH);
+ eptr++;
+ ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+ }
+ break;
+
+ case OP_WORDCHAR:
+ for (i = 1; i <= min; i++)
+ {
+ pcre_uint32 cc;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ cc = UCHAR21(eptr);
+ if (cc >= 128 || (md->ctypes[cc] & ctype_word) == 0)
+ RRETURN(MATCH_NOMATCH);
+ eptr++;
+ /* No need to skip more bytes - we know it's a 1-byte character */
+ }
+ break;
+
+ default:
+ RRETURN(PCRE_ERROR_INTERNAL);
+ } /* End switch(ctype) */
+
+ else
+#endif /* SUPPORT_UTF */
+
+ /* Code for the non-UTF-8 case for minimum matching of operators other
+ than OP_PROP and OP_NOTPROP. */
+
+ switch(ctype)
+ {
+ case OP_ANY:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
+ if (md->partial != 0 &&
+ eptr + 1 >= md->end_subject &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ *eptr == NLBLOCK->nl[0])
+ {
+ md->hitend = TRUE;
+ if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ }
+ eptr++;
+ }
+ break;
+
+ case OP_ALLANY:
+ if (eptr > md->end_subject - min)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ eptr += min;
+ break;
+
+ case OP_ANYBYTE:
+ if (eptr > md->end_subject - min)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ eptr += min;
+ break;
+
+ case OP_ANYNL:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ switch(*eptr++)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+
+ case CHAR_CR:
+ if (eptr < md->end_subject && *eptr == CHAR_LF) eptr++;
+ break;
+
+ case CHAR_LF:
+ break;
+
+ case CHAR_VT:
+ case CHAR_FF:
+ case CHAR_NEL:
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ case 0x2028:
+ case 0x2029:
+#endif
+ if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+ break;
+ }
+ }
+ break;
+
+ case OP_NOT_HSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ switch(*eptr++)
+ {
+ default: break;
+ HSPACE_BYTE_CASES:
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ HSPACE_MULTIBYTE_CASES:
+#endif
+ RRETURN(MATCH_NOMATCH);
+ }
+ }
+ break;
+
+ case OP_HSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ switch(*eptr++)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ HSPACE_BYTE_CASES:
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ HSPACE_MULTIBYTE_CASES:
+#endif
+ break;
+ }
+ }
+ break;
+
+ case OP_NOT_VSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ switch(*eptr++)
+ {
+ VSPACE_BYTE_CASES:
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ VSPACE_MULTIBYTE_CASES:
+#endif
+ RRETURN(MATCH_NOMATCH);
+ default: break;
+ }
+ }
+ break;
+
+ case OP_VSPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ switch(*eptr++)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ VSPACE_BYTE_CASES:
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ VSPACE_MULTIBYTE_CASES:
+#endif
+ break;
+ }
+ }
+ break;
+
+ case OP_NOT_DIGIT:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_digit) != 0)
+ RRETURN(MATCH_NOMATCH);
+ eptr++;
+ }
+ break;
+
+ case OP_DIGIT:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_digit) == 0)
+ RRETURN(MATCH_NOMATCH);
+ eptr++;
+ }
+ break;
+
+ case OP_NOT_WHITESPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_space) != 0)
+ RRETURN(MATCH_NOMATCH);
+ eptr++;
+ }
+ break;
+
+ case OP_WHITESPACE:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_space) == 0)
+ RRETURN(MATCH_NOMATCH);
+ eptr++;
+ }
+ break;
+
+ case OP_NOT_WORDCHAR:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_word) != 0)
+ RRETURN(MATCH_NOMATCH);
+ eptr++;
+ }
+ break;
+
+ case OP_WORDCHAR:
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_word) == 0)
+ RRETURN(MATCH_NOMATCH);
+ eptr++;
+ }
+ break;
+
+ default:
+ RRETURN(PCRE_ERROR_INTERNAL);
+ }
+ }
+
+ /* If min = max, continue at the same level without recursing */
+
+ if (min == max) continue;
+
+ /* If minimizing, we have to test the rest of the pattern before each
+ subsequent match. Again, separate the UTF-8 case for speed, and also
+ separate the UCP cases. */
+
+ if (minimize)
+ {
+#ifdef SUPPORT_UCP
+ if (prop_type >= 0)
+ {
+ switch(prop_type)
+ {
+ case PT_ANY:
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM36);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if (prop_fail_result) RRETURN(MATCH_NOMATCH);
+ }
+ /* Control never gets here */
+
+ case PT_LAMP:
+ for (fi = min;; fi++)
+ {
+ int chartype;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM37);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ chartype = UCD_CHARTYPE(c);
+ if ((chartype == ucp_Lu ||
+ chartype == ucp_Ll ||
+ chartype == ucp_Lt) == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ }
+ /* Control never gets here */
+
+ case PT_GC:
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM38);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ }
+ /* Control never gets here */
+
+ case PT_PC:
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM39);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ }
+ /* Control never gets here */
+
+ case PT_SC:
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM40);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ }
+ /* Control never gets here */
+
+ case PT_ALNUM:
+ for (fi = min;; fi++)
+ {
+ int category;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM59);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ category = UCD_CATEGORY(c);
+ if ((category == ucp_L || category == ucp_N) == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ }
+ /* Control never gets here */
+
+ /* Perl space used to exclude VT, but from Perl 5.18 it is included,
+ which means that Perl space and POSIX space are now identical. PCRE
+ was changed at release 8.34. */
+
+ case PT_SPACE: /* Perl space */
+ case PT_PXSPACE: /* POSIX space */
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM61);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ switch(c)
+ {
+ HSPACE_CASES:
+ VSPACE_CASES:
+ if (prop_fail_result) RRETURN(MATCH_NOMATCH);
+ break;
+
+ default:
+ if ((UCD_CATEGORY(c) == ucp_Z) == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ break;
+ }
+ }
+ /* Control never gets here */
+
+ case PT_WORD:
+ for (fi = min;; fi++)
+ {
+ int category;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM62);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ category = UCD_CATEGORY(c);
+ if ((category == ucp_L ||
+ category == ucp_N ||
+ c == CHAR_UNDERSCORE)
+ == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ }
+ /* Control never gets here */
+
+ case PT_CLIST:
+ for (fi = min;; fi++)
+ {
+ const pcre_uint32 *cp;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM67);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ cp = PRIV(ucd_caseless_sets) + prop_value;
+ for (;;)
+ {
+ if (c < *cp)
+ { if (prop_fail_result) break; else { RRETURN(MATCH_NOMATCH); } }
+ if (c == *cp++)
+ { if (prop_fail_result) { RRETURN(MATCH_NOMATCH); } else break; }
+ }
+ }
+ /* Control never gets here */
+
+ case PT_UCNC:
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM60);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(c, eptr);
+ if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
+ c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
+ c >= 0xe000) == prop_fail_result)
+ RRETURN(MATCH_NOMATCH);
+ }
+ /* Control never gets here */
+
+ /* This should never occur */
+ default:
+ RRETURN(PCRE_ERROR_INTERNAL);
+ }
+ }
+
+ /* Match extended Unicode sequences. We will get here only if the
+ support is in the binary; otherwise a compile-time error occurs. */
+
+ else if (ctype == OP_EXTUNI)
+ {
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM41);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ else
+ {
+ int lgb, rgb;
+ GETCHARINCTEST(c, eptr);
+ lgb = UCD_GRAPHBREAK(c);
+ while (eptr < md->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;
+ lgb = rgb;
+ eptr += len;
+ }
+ }
+ CHECK_PARTIAL();
+ }
+ }
+ else
+#endif /* SUPPORT_UCP */
+
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM42);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (ctype == OP_ANY && IS_NEWLINE(eptr))
+ RRETURN(MATCH_NOMATCH);
+ GETCHARINC(c, eptr);
+ switch(ctype)
+ {
+ case OP_ANY: /* This is the non-NL case */
+ if (md->partial != 0 && /* Take care with CRLF partial */
+ eptr >= md->end_subject &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ c == NLBLOCK->nl[0])
+ {
+ md->hitend = TRUE;
+ if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ }
+ break;
+
+ case OP_ALLANY:
+ case OP_ANYBYTE:
+ break;
+
+ case OP_ANYNL:
+ switch(c)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ case CHAR_CR:
+ if (eptr < md->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++;
+ break;
+
+ case CHAR_LF:
+ break;
+
+ case CHAR_VT:
+ case CHAR_FF:
+ case CHAR_NEL:
+#ifndef EBCDIC
+ case 0x2028:
+ case 0x2029:
+#endif /* Not EBCDIC */
+ if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+ break;
+ }
+ break;
+
+ case OP_NOT_HSPACE:
+ switch(c)
+ {
+ HSPACE_CASES: RRETURN(MATCH_NOMATCH);
+ default: break;
+ }
+ break;
+
+ case OP_HSPACE:
+ switch(c)
+ {
+ HSPACE_CASES: break;
+ default: RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case OP_NOT_VSPACE:
+ switch(c)
+ {
+ VSPACE_CASES: RRETURN(MATCH_NOMATCH);
+ default: break;
+ }
+ break;
+
+ case OP_VSPACE:
+ switch(c)
+ {
+ VSPACE_CASES: break;
+ default: RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case OP_NOT_DIGIT:
+ if (c < 256 && (md->ctypes[c] & ctype_digit) != 0)
+ RRETURN(MATCH_NOMATCH);
+ break;
+
+ case OP_DIGIT:
+ if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0)
+ RRETURN(MATCH_NOMATCH);
+ break;
+
+ case OP_NOT_WHITESPACE:
+ if (c < 256 && (md->ctypes[c] & ctype_space) != 0)
+ RRETURN(MATCH_NOMATCH);
+ break;
+
+ case OP_WHITESPACE:
+ if (c >= 256 || (md->ctypes[c] & ctype_space) == 0)
+ RRETURN(MATCH_NOMATCH);
+ break;
+
+ case OP_NOT_WORDCHAR:
+ if (c < 256 && (md->ctypes[c] & ctype_word) != 0)
+ RRETURN(MATCH_NOMATCH);
+ break;
+
+ case OP_WORDCHAR:
+ if (c >= 256 || (md->ctypes[c] & ctype_word) == 0)
+ RRETURN(MATCH_NOMATCH);
+ break;
+
+ default:
+ RRETURN(PCRE_ERROR_INTERNAL);
+ }
+ }
+ }
+ else
+#endif
+ /* Not UTF mode */
+ {
+ for (fi = min;; fi++)
+ {
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM43);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (fi >= max) RRETURN(MATCH_NOMATCH);
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ if (ctype == OP_ANY && IS_NEWLINE(eptr))
+ RRETURN(MATCH_NOMATCH);
+ c = *eptr++;
+ switch(ctype)
+ {
+ case OP_ANY: /* This is the non-NL case */
+ if (md->partial != 0 && /* Take care with CRLF partial */
+ eptr >= md->end_subject &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ c == NLBLOCK->nl[0])
+ {
+ md->hitend = TRUE;
+ if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ }
+ break;
+
+ case OP_ALLANY:
+ case OP_ANYBYTE:
+ break;
+
+ case OP_ANYNL:
+ switch(c)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ case CHAR_CR:
+ if (eptr < md->end_subject && *eptr == CHAR_LF) eptr++;
+ break;
+
+ case CHAR_LF:
+ break;
+
+ case CHAR_VT:
+ case CHAR_FF:
+ case CHAR_NEL:
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ case 0x2028:
+ case 0x2029:
+#endif
+ if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+ break;
+ }
+ break;
+
+ case OP_NOT_HSPACE:
+ switch(c)
+ {
+ default: break;
+ HSPACE_BYTE_CASES:
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ HSPACE_MULTIBYTE_CASES:
+#endif
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case OP_HSPACE:
+ switch(c)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ HSPACE_BYTE_CASES:
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ HSPACE_MULTIBYTE_CASES:
+#endif
+ break;
+ }
+ break;
+
+ case OP_NOT_VSPACE:
+ switch(c)
+ {
+ default: break;
+ VSPACE_BYTE_CASES:
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ VSPACE_MULTIBYTE_CASES:
+#endif
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case OP_VSPACE:
+ switch(c)
+ {
+ default: RRETURN(MATCH_NOMATCH);
+ VSPACE_BYTE_CASES:
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ VSPACE_MULTIBYTE_CASES:
+#endif
+ break;
+ }
+ break;
+
+ case OP_NOT_DIGIT:
+ if (MAX_255(c) && (md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);
+ break;
+
+ case OP_DIGIT:
+ if (!MAX_255(c) || (md->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH);
+ break;
+
+ case OP_NOT_WHITESPACE:
+ if (MAX_255(c) && (md->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH);
+ break;
+
+ case OP_WHITESPACE:
+ if (!MAX_255(c) || (md->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH);
+ break;
+
+ case OP_NOT_WORDCHAR:
+ if (MAX_255(c) && (md->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH);
+ break;
+
+ case OP_WORDCHAR:
+ if (!MAX_255(c) || (md->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH);
+ break;
+
+ default:
+ RRETURN(PCRE_ERROR_INTERNAL);
+ }
+ }
+ }
+ /* Control never gets here */
+ }
+
+ /* If maximizing, it is worth using inline code for speed, doing the type
+ test once at the start (i.e. keep it out of the loop). Again, keep the
+ UTF-8 and UCP stuff separate. */
+
+ else
+ {
+ pp = eptr; /* Remember where we started */
+
+#ifdef SUPPORT_UCP
+ if (prop_type >= 0)
+ {
+ switch(prop_type)
+ {
+ case PT_ANY:
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLENTEST(c, eptr, len);
+ if (prop_fail_result) break;
+ eptr+= len;
+ }
+ break;
+
+ case PT_LAMP:
+ for (i = min; i < max; i++)
+ {
+ int chartype;
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLENTEST(c, eptr, len);
+ chartype = UCD_CHARTYPE(c);
+ if ((chartype == ucp_Lu ||
+ chartype == ucp_Ll ||
+ chartype == ucp_Lt) == prop_fail_result)
+ break;
+ eptr+= len;
+ }
+ break;
+
+ case PT_GC:
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLENTEST(c, eptr, len);
+ if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result) break;
+ eptr+= len;
+ }
+ break;
+
+ case PT_PC:
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLENTEST(c, eptr, len);
+ if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result) break;
+ eptr+= len;
+ }
+ break;
+
+ case PT_SC:
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLENTEST(c, eptr, len);
+ if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result) break;
+ eptr+= len;
+ }
+ break;
+
+ case PT_ALNUM:
+ for (i = min; i < max; i++)
+ {
+ int category;
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLENTEST(c, eptr, len);
+ category = UCD_CATEGORY(c);
+ if ((category == ucp_L || category == ucp_N) == prop_fail_result)
+ break;
+ eptr+= len;
+ }
+ break;
+
+ /* Perl space used to exclude VT, but from Perl 5.18 it is included,
+ which means that Perl space and POSIX space are now identical. PCRE
+ was changed at release 8.34. */
+
+ case PT_SPACE: /* Perl space */
+ case PT_PXSPACE: /* POSIX space */
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLENTEST(c, eptr, len);
+ switch(c)
+ {
+ HSPACE_CASES:
+ VSPACE_CASES:
+ if (prop_fail_result) goto ENDLOOP99; /* Break the loop */
+ break;
+
+ default:
+ if ((UCD_CATEGORY(c) == ucp_Z) == prop_fail_result)
+ goto ENDLOOP99; /* Break the loop */
+ break;
+ }
+ eptr+= len;
+ }
+ ENDLOOP99:
+ break;
+
+ case PT_WORD:
+ for (i = min; i < max; i++)
+ {
+ int category;
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLENTEST(c, eptr, len);
+ category = UCD_CATEGORY(c);
+ if ((category == ucp_L || category == ucp_N ||
+ c == CHAR_UNDERSCORE) == prop_fail_result)
+ break;
+ eptr+= len;
+ }
+ break;
+
+ case PT_CLIST:
+ for (i = min; i < max; i++)
+ {
+ const pcre_uint32 *cp;
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLENTEST(c, eptr, len);
+ cp = PRIV(ucd_caseless_sets) + prop_value;
+ for (;;)
+ {
+ if (c < *cp)
+ { if (prop_fail_result) break; else goto GOT_MAX; }
+ if (c == *cp++)
+ { if (prop_fail_result) goto GOT_MAX; else break; }
+ }
+ eptr += len;
+ }
+ GOT_MAX:
+ break;
+
+ case PT_UCNC:
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLENTEST(c, eptr, len);
+ if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
+ c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) ||
+ c >= 0xe000) == prop_fail_result)
+ break;
+ eptr += len;
+ }
+ break;
+
+ default:
+ RRETURN(PCRE_ERROR_INTERNAL);
+ }
+
+ /* eptr is now past the end of the maximum run */
+
+ if (possessive) continue; /* No backtracking */
+ for(;;)
+ {
+ if (eptr == pp) goto TAIL_RECURSE;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM44);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ eptr--;
+ if (utf) BACKCHAR(eptr);
+ }
+ }
+
+ /* Match extended Unicode grapheme clusters. We will get here only if the
+ support is in the binary; otherwise a compile-time error occurs. */
+
+ else if (ctype == OP_EXTUNI)
+ {
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ else
+ {
+ int lgb, rgb;
+ GETCHARINCTEST(c, eptr);
+ lgb = UCD_GRAPHBREAK(c);
+ while (eptr < md->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;
+ lgb = rgb;
+ eptr += len;
+ }
+ }
+ CHECK_PARTIAL();
+ }
+
+ /* eptr is now past the end of the maximum run */
+
+ if (possessive) continue; /* No backtracking */
+
+ for(;;)
+ {
+ int lgb, rgb;
+ PCRE_PUCHAR fptr;
+
+ if (eptr == pp) goto TAIL_RECURSE; /* At start of char run */
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM45);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+
+ /* Backtracking over an extended grapheme cluster involves inspecting
+ the previous two characters (if present) to see if a break is
+ permitted between them. */
+
+ eptr--;
+ if (!utf) c = *eptr; else
+ {
+ BACKCHAR(eptr);
+ GETCHAR(c, eptr);
+ }
+ rgb = UCD_GRAPHBREAK(c);
+
+ for (;;)
+ {
+ if (eptr == pp) goto TAIL_RECURSE; /* At start of char run */
+ fptr = eptr - 1;
+ if (!utf) c = *fptr; else
+ {
+ BACKCHAR(fptr);
+ GETCHAR(c, fptr);
+ }
+ lgb = UCD_GRAPHBREAK(c);
+ if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
+ eptr = fptr;
+ rgb = lgb;
+ }
+ }
+ }
+
+ else
+#endif /* SUPPORT_UCP */
+
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ switch(ctype)
+ {
+ case OP_ANY:
+ if (max < INT_MAX)
+ {
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ if (IS_NEWLINE(eptr)) break;
+ if (md->partial != 0 && /* Take care with CRLF partial */
+ eptr + 1 >= md->end_subject &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ UCHAR21(eptr) == NLBLOCK->nl[0])
+ {
+ md->hitend = TRUE;
+ if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ }
+ eptr++;
+ ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+ }
+ }
+
+ /* Handle unlimited UTF-8 repeat */
+
+ else
+ {
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ if (IS_NEWLINE(eptr)) break;
+ if (md->partial != 0 && /* Take care with CRLF partial */
+ eptr + 1 >= md->end_subject &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ UCHAR21(eptr) == NLBLOCK->nl[0])
+ {
+ md->hitend = TRUE;
+ if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ }
+ eptr++;
+ ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+ }
+ }
+ break;
+
+ case OP_ALLANY:
+ if (max < INT_MAX)
+ {
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ eptr++;
+ ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+ }
+ }
+ else
+ {
+ eptr = md->end_subject; /* Unlimited UTF-8 repeat */
+ SCHECK_PARTIAL();
+ }
+ break;
+
+ /* The byte case is the same as non-UTF8 */
+
+ case OP_ANYBYTE:
+ c = max - min;
+ if (c > (unsigned int)(md->end_subject - eptr))
+ {
+ eptr = md->end_subject;
+ SCHECK_PARTIAL();
+ }
+ else eptr += c;
+ break;
+
+ case OP_ANYNL:
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLEN(c, eptr, len);
+ if (c == CHAR_CR)
+ {
+ if (++eptr >= md->end_subject) break;
+ if (UCHAR21(eptr) == CHAR_LF) eptr++;
+ }
+ else
+ {
+ if (c != CHAR_LF &&
+ (md->bsr_anycrlf ||
+ (c != CHAR_VT && c != CHAR_FF && c != CHAR_NEL
+#ifndef EBCDIC
+ && c != 0x2028 && c != 0x2029
+#endif /* Not EBCDIC */
+ )))
+ break;
+ eptr += len;
+ }
+ }
+ break;
+
+ case OP_NOT_HSPACE:
+ case OP_HSPACE:
+ for (i = min; i < max; i++)
+ {
+ BOOL gotspace;
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLEN(c, eptr, len);
+ switch(c)
+ {
+ HSPACE_CASES: gotspace = TRUE; break;
+ default: gotspace = FALSE; break;
+ }
+ if (gotspace == (ctype == OP_NOT_HSPACE)) break;
+ eptr += len;
+ }
+ break;
+
+ case OP_NOT_VSPACE:
+ case OP_VSPACE:
+ for (i = min; i < max; i++)
+ {
+ BOOL gotspace;
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLEN(c, eptr, len);
+ switch(c)
+ {
+ VSPACE_CASES: gotspace = TRUE; break;
+ default: gotspace = FALSE; break;
+ }
+ if (gotspace == (ctype == OP_NOT_VSPACE)) break;
+ eptr += len;
+ }
+ break;
+
+ case OP_NOT_DIGIT:
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLEN(c, eptr, len);
+ if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break;
+ eptr+= len;
+ }
+ break;
+
+ case OP_DIGIT:
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLEN(c, eptr, len);
+ if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break;
+ eptr+= len;
+ }
+ break;
+
+ case OP_NOT_WHITESPACE:
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLEN(c, eptr, len);
+ if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break;
+ eptr+= len;
+ }
+ break;
+
+ case OP_WHITESPACE:
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLEN(c, eptr, len);
+ if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break;
+ eptr+= len;
+ }
+ break;
+
+ case OP_NOT_WORDCHAR:
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLEN(c, eptr, len);
+ if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break;
+ eptr+= len;
+ }
+ break;
+
+ case OP_WORDCHAR:
+ for (i = min; i < max; i++)
+ {
+ int len = 1;
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLEN(c, eptr, len);
+ if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break;
+ eptr+= len;
+ }
+ break;
+
+ default:
+ RRETURN(PCRE_ERROR_INTERNAL);
+ }
+
+ if (possessive) continue; /* No backtracking */
+ for(;;)
+ {
+ if (eptr == pp) goto TAIL_RECURSE;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM46);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ eptr--;
+ BACKCHAR(eptr);
+ if (ctype == OP_ANYNL && eptr > pp && UCHAR21(eptr) == CHAR_NL &&
+ UCHAR21(eptr - 1) == CHAR_CR) eptr--;
+ }
+ }
+ else
+#endif /* SUPPORT_UTF */
+ /* Not UTF mode */
+ {
+ switch(ctype)
+ {
+ case OP_ANY:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ if (IS_NEWLINE(eptr)) break;
+ if (md->partial != 0 && /* Take care with CRLF partial */
+ eptr + 1 >= md->end_subject &&
+ NLBLOCK->nltype == NLTYPE_FIXED &&
+ NLBLOCK->nllen == 2 &&
+ *eptr == NLBLOCK->nl[0])
+ {
+ md->hitend = TRUE;
+ if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ }
+ eptr++;
+ }
+ break;
+
+ case OP_ALLANY:
+ case OP_ANYBYTE:
+ c = max - min;
+ if (c > (unsigned int)(md->end_subject - eptr))
+ {
+ eptr = md->end_subject;
+ SCHECK_PARTIAL();
+ }
+ else eptr += c;
+ break;
+
+ case OP_ANYNL:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ c = *eptr;
+ if (c == CHAR_CR)
+ {
+ if (++eptr >= md->end_subject) break;
+ if (*eptr == CHAR_LF) eptr++;
+ }
+ else
+ {
+ if (c != CHAR_LF && (md->bsr_anycrlf ||
+ (c != CHAR_VT && c != CHAR_FF && c != CHAR_NEL
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ && c != 0x2028 && c != 0x2029
+#endif
+ ))) break;
+ eptr++;
+ }
+ }
+ break;
+
+ case OP_NOT_HSPACE:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ switch(*eptr)
+ {
+ default: eptr++; break;
+ HSPACE_BYTE_CASES:
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ HSPACE_MULTIBYTE_CASES:
+#endif
+ goto ENDLOOP00;
+ }
+ }
+ ENDLOOP00:
+ break;
+
+ case OP_HSPACE:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ switch(*eptr)
+ {
+ default: goto ENDLOOP01;
+ HSPACE_BYTE_CASES:
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ HSPACE_MULTIBYTE_CASES:
+#endif
+ eptr++; break;
+ }
+ }
+ ENDLOOP01:
+ break;
+
+ case OP_NOT_VSPACE:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ switch(*eptr)
+ {
+ default: eptr++; break;
+ VSPACE_BYTE_CASES:
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ VSPACE_MULTIBYTE_CASES:
+#endif
+ goto ENDLOOP02;
+ }
+ }
+ ENDLOOP02:
+ break;
+
+ case OP_VSPACE:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ switch(*eptr)
+ {
+ default: goto ENDLOOP03;
+ VSPACE_BYTE_CASES:
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ VSPACE_MULTIBYTE_CASES:
+#endif
+ eptr++; break;
+ }
+ }
+ ENDLOOP03:
+ break;
+
+ case OP_NOT_DIGIT:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_digit) != 0) break;
+ eptr++;
+ }
+ break;
+
+ case OP_DIGIT:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_digit) == 0) break;
+ eptr++;
+ }
+ break;
+
+ case OP_NOT_WHITESPACE:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_space) != 0) break;
+ eptr++;
+ }
+ break;
+
+ case OP_WHITESPACE:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_space) == 0) break;
+ eptr++;
+ }
+ break;
+
+ case OP_NOT_WORDCHAR:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_word) != 0) break;
+ eptr++;
+ }
+ break;
+
+ case OP_WORDCHAR:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_word) == 0) break;
+ eptr++;
+ }
+ break;
+
+ default:
+ RRETURN(PCRE_ERROR_INTERNAL);
+ }
+
+ if (possessive) continue; /* No backtracking */
+ for (;;)
+ {
+ if (eptr == pp) goto TAIL_RECURSE;
+ RMATCH(eptr, ecode, offset_top, md, eptrb, RM47);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ eptr--;
+ if (ctype == OP_ANYNL && eptr > pp && *eptr == CHAR_LF &&
+ eptr[-1] == CHAR_CR) eptr--;
+ }
+ }
+
+ /* Control never gets here */
+ }
+
+ /* There's been some horrible disaster. Arrival here can only mean there is
+ something seriously wrong in the code above or the OP_xxx definitions. */
+
+ default:
+ DPRINTF(("Unknown opcode %d\n", *ecode));
+ RRETURN(PCRE_ERROR_UNKNOWN_OPCODE);
+ }
+
+ /* Do not stick any code in here without much thought; it is assumed
+ that "continue" in the code above comes out to here to repeat the main
+ loop. */
+
+ } /* End of main loop */
+/* Control never reaches here */
+
+
+/* When compiling to use the heap rather than the stack for recursive calls to
+match(), the RRETURN() macro jumps here. The number that is saved in
+frame->Xwhere indicates which label we actually want to return to. */
+
+#ifdef NO_RECURSE
+#define LBL(val) case val: goto L_RM##val;
+HEAP_RETURN:
+switch (frame->Xwhere)
+ {
+ LBL( 1) LBL( 2) LBL( 3) LBL( 4) LBL( 5) LBL( 6) LBL( 7) LBL( 8)
+ LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(17)
+ LBL(19) LBL(24) LBL(25) LBL(26) LBL(27) LBL(29) LBL(31) LBL(33)
+ LBL(35) LBL(43) LBL(47) LBL(48) LBL(49) LBL(50) LBL(51) LBL(52)
+ LBL(53) LBL(54) LBL(55) LBL(56) LBL(57) LBL(58) LBL(63) LBL(64)
+ LBL(65) LBL(66)
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ LBL(20) LBL(21)
+#endif
+#ifdef SUPPORT_UTF
+ LBL(16) LBL(18)
+ LBL(22) LBL(23) LBL(28) LBL(30)
+ LBL(32) LBL(34) LBL(42) LBL(46)
+#ifdef SUPPORT_UCP
+ LBL(36) LBL(37) LBL(38) LBL(39) LBL(40) LBL(41) LBL(44) LBL(45)
+ LBL(59) LBL(60) LBL(61) LBL(62) LBL(67)
+#endif /* SUPPORT_UCP */
+#endif /* SUPPORT_UTF */
+ default:
+ DPRINTF(("jump error in pcre match: label %d non-existent\n", frame->Xwhere));
+ return PCRE_ERROR_INTERNAL;
+ }
+#undef LBL
+#endif /* NO_RECURSE */
+}
+
+
+/***************************************************************************
+****************************************************************************
+ RECURSION IN THE match() FUNCTION
+
+Undefine all the macros that were defined above to handle this. */
+
+#ifdef NO_RECURSE
+#undef eptr
+#undef ecode
+#undef mstart
+#undef offset_top
+#undef eptrb
+#undef flags
+
+#undef callpat
+#undef charptr
+#undef data
+#undef next
+#undef pp
+#undef prev
+#undef saved_eptr
+
+#undef new_recursive
+
+#undef cur_is_word
+#undef condition
+#undef prev_is_word
+
+#undef ctype
+#undef length
+#undef max
+#undef min
+#undef number
+#undef offset
+#undef op
+#undef save_capture_last
+#undef save_offset1
+#undef save_offset2
+#undef save_offset3
+#undef stacksave
+
+#undef newptrb
+
+#endif
+
+/* These two are defined as macros in both cases */
+
+#undef fc
+#undef fi
+
+/***************************************************************************
+***************************************************************************/
+
+
+#ifdef NO_RECURSE
+/*************************************************
+* Release allocated heap frames *
+*************************************************/
+
+/* This function releases all the allocated frames. The base frame is on the
+machine stack, and so must not be freed.
+
+Argument: the address of the base frame
+Returns: nothing
+*/
+
+static void
+release_match_heapframes (heapframe *frame_base)
+{
+heapframe *nextframe = frame_base->Xnextframe;
+while (nextframe != NULL)
+ {
+ heapframe *oldframe = nextframe;
+ nextframe = nextframe->Xnextframe;
+ (PUBL(stack_free))(oldframe);
+ }
+}
+#endif
+
+
+/*************************************************
+* Execute a Regular Expression *
+*************************************************/
+
+/* This function applies a compiled re to a subject string and picks out
+portions of the string if it matches. Two elements in the vector are set for
+each substring: the offsets to the start and end of the substring.
+
+Arguments:
+ argument_re points to the compiled expression
+ extra_data points to extra data or is NULL
+ subject points to the subject string
+ length length of subject string (may contain binary zeros)
+ start_offset where to start in the subject string
+ options option bits
+ offsets points to a vector of ints to be filled in with offsets
+ offsetcount the number of elements in the vector
+
+Returns: > 0 => success; value is the number of elements filled in
+ = 0 => success, but offsets is not big enough
+ -1 => failed to match
+ < -1 => some kind of unexpected problem
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_exec(const pcre *argument_re, const pcre_extra *extra_data,
+ PCRE_SPTR subject, int length, int start_offset, int options, int *offsets,
+ int offsetcount)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_exec(const pcre16 *argument_re, const pcre16_extra *extra_data,
+ PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets,
+ int offsetcount)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre32_exec(const pcre32 *argument_re, const pcre32_extra *extra_data,
+ PCRE_SPTR32 subject, int length, int start_offset, int options, int *offsets,
+ int offsetcount)
+#endif
+{
+int rc, ocount, arg_offset_max;
+int newline;
+BOOL using_temporary_offsets = FALSE;
+BOOL anchored;
+BOOL startline;
+BOOL firstline;
+BOOL utf;
+BOOL has_first_char = FALSE;
+BOOL has_req_char = FALSE;
+pcre_uchar first_char = 0;
+pcre_uchar first_char2 = 0;
+pcre_uchar req_char = 0;
+pcre_uchar req_char2 = 0;
+match_data match_block;
+match_data *md = &match_block;
+const pcre_uint8 *tables;
+const pcre_uint8 *start_bits = NULL;
+PCRE_PUCHAR start_match = (PCRE_PUCHAR)subject + start_offset;
+PCRE_PUCHAR end_subject;
+PCRE_PUCHAR start_partial = NULL;
+PCRE_PUCHAR match_partial = NULL;
+PCRE_PUCHAR req_char_ptr = start_match - 1;
+
+const pcre_study_data *study;
+const REAL_PCRE *re = (const REAL_PCRE *)argument_re;
+
+#ifdef NO_RECURSE
+heapframe frame_zero;
+frame_zero.Xprevframe = NULL; /* Marks the top level */
+frame_zero.Xnextframe = NULL; /* None are allocated yet */
+md->match_frames_base = &frame_zero;
+#endif
+
+/* Check for the special magic call that measures the size of the stack used
+per recursive call of match(). Without the funny casting for sizeof, a Windows
+compiler gave this error: "unary minus operator applied to unsigned type,
+result still unsigned". Hopefully the cast fixes that. */
+
+if (re == NULL && extra_data == NULL && subject == NULL && length == -999 &&
+ start_offset == -999)
+#ifdef NO_RECURSE
+ return -((int)sizeof(heapframe));
+#else
+ return match(NULL, NULL, NULL, 0, NULL, NULL, 0);
+#endif
+
+/* Plausibility checks */
+
+if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
+if (re == NULL || subject == NULL || (offsets == NULL && offsetcount > 0))
+ return PCRE_ERROR_NULL;
+if (offsetcount < 0) return PCRE_ERROR_BADCOUNT;
+if (length < 0) return PCRE_ERROR_BADLENGTH;
+if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET;
+
+/* Check that the first field in the block is the magic number. If it is not,
+return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to
+REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which
+means that the pattern is likely compiled with different endianness. */
+
+if (re->magic_number != MAGIC_NUMBER)
+ return re->magic_number == REVERSED_MAGIC_NUMBER?
+ PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC;
+if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
+
+/* These two settings are used in the code for checking a UTF-8 string that
+follows immediately afterwards. Other values in the md block are used only
+during "normal" pcre_exec() processing, not when the JIT support is in use,
+so they are set up later. */
+
+/* PCRE_UTF16 has the same value as PCRE_UTF8. */
+utf = md->utf = (re->options & PCRE_UTF8) != 0;
+md->partial = ((options & PCRE_PARTIAL_HARD) != 0)? 2 :
+ ((options & PCRE_PARTIAL_SOFT) != 0)? 1 : 0;
+
+/* Check a UTF-8 string if required. Pass back the character offset and error
+code for an invalid string if a results vector is available. */
+
+#ifdef SUPPORT_UTF
+if (utf && (options & PCRE_NO_UTF8_CHECK) == 0)
+ {
+ int erroroffset;
+ int errorcode = PRIV(valid_utf)((PCRE_PUCHAR)subject, length, &erroroffset);
+ if (errorcode != 0)
+ {
+ if (offsetcount >= 2)
+ {
+ offsets[0] = erroroffset;
+ offsets[1] = errorcode;
+ }
+#if defined COMPILE_PCRE8
+ return (errorcode <= PCRE_UTF8_ERR5 && md->partial > 1)?
+ PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8;
+#elif defined COMPILE_PCRE16
+ return (errorcode <= PCRE_UTF16_ERR1 && md->partial > 1)?
+ PCRE_ERROR_SHORTUTF16 : PCRE_ERROR_BADUTF16;
+#elif defined COMPILE_PCRE32
+ return PCRE_ERROR_BADUTF32;
+#endif
+ }
+#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
+ /* Check that a start_offset points to the start of a UTF character. */
+ if (start_offset > 0 && start_offset < length &&
+ NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset]))
+ return PCRE_ERROR_BADUTF8_OFFSET;
+#endif
+ }
+#endif
+
+/* 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 flag is set. */
+
+#ifdef SUPPORT_JIT
+if (extra_data != NULL
+ && (extra_data->flags & (PCRE_EXTRA_EXECUTABLE_JIT |
+ PCRE_EXTRA_TABLES)) == PCRE_EXTRA_EXECUTABLE_JIT
+ && extra_data->executable_jit != NULL
+ && (options & ~PUBLIC_JIT_EXEC_OPTIONS) == 0)
+ {
+ rc = PRIV(jit_exec)(extra_data, (const pcre_uchar *)subject, length,
+ start_offset, options, offsets, offsetcount);
+
+ /* PCRE_ERROR_NULL means that the selected normal or partial matching
+ mode is not compiled. In this case we simply fallback to interpreter. */
+
+ if (rc != PCRE_ERROR_JIT_BADOPTION) return rc;
+ }
+#endif
+
+/* Carry on with non-JIT matching. This information is for finding all the
+numbers associated with a given name, for condition testing. */
+
+md->name_table = (pcre_uchar *)re + re->name_table_offset;
+md->name_count = re->name_count;
+md->name_entry_size = re->name_entry_size;
+
+/* Fish out the optional data from the extra_data structure, first setting
+the default values. */
+
+study = NULL;
+md->match_limit = MATCH_LIMIT;
+md->match_limit_recursion = MATCH_LIMIT_RECURSION;
+md->callout_data = NULL;
+
+/* The table pointer is always in native byte order. */
+
+tables = re->tables;
+
+/* The two limit values override the defaults, whatever their value. */
+
+if (extra_data != NULL)
+ {
+ register unsigned int flags = extra_data->flags;
+ if ((flags & PCRE_EXTRA_STUDY_DATA) != 0)
+ study = (const pcre_study_data *)extra_data->study_data;
+ if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0)
+ md->match_limit = extra_data->match_limit;
+ if ((flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION) != 0)
+ md->match_limit_recursion = extra_data->match_limit_recursion;
+ if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0)
+ md->callout_data = extra_data->callout_data;
+ if ((flags & PCRE_EXTRA_TABLES) != 0) tables = extra_data->tables;
+ }
+
+/* Limits in the regex override only if they are smaller. */
+
+if ((re->flags & PCRE_MLSET) != 0 && re->limit_match < md->match_limit)
+ md->match_limit = re->limit_match;
+
+if ((re->flags & PCRE_RLSET) != 0 &&
+ re->limit_recursion < md->match_limit_recursion)
+ md->match_limit_recursion = re->limit_recursion;
+
+/* If the exec call supplied NULL for tables, use the inbuilt ones. This
+is a feature that makes it possible to save compiled regex and re-use them
+in other programs later. */
+
+if (tables == NULL) tables = PRIV(default_tables);
+
+/* Set up other data */
+
+anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
+startline = (re->flags & PCRE_STARTLINE) != 0;
+firstline = (re->options & PCRE_FIRSTLINE) != 0;
+
+/* The code starts after the real_pcre block and the capture name table. */
+
+md->start_code = (const pcre_uchar *)re + re->name_table_offset +
+ re->name_count * re->name_entry_size;
+
+md->start_subject = (PCRE_PUCHAR)subject;
+md->start_offset = start_offset;
+md->end_subject = md->start_subject + length;
+end_subject = md->end_subject;
+
+md->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
+md->use_ucp = (re->options & PCRE_UCP) != 0;
+md->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
+md->ignore_skip_arg = 0;
+
+/* Some options are unpacked into BOOL variables in the hope that testing
+them will be faster than individual option bits. */
+
+md->notbol = (options & PCRE_NOTBOL) != 0;
+md->noteol = (options & PCRE_NOTEOL) != 0;
+md->notempty = (options & PCRE_NOTEMPTY) != 0;
+md->notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0;
+
+md->hitend = FALSE;
+md->mark = md->nomatch_mark = NULL; /* In case never set */
+
+md->recursive = NULL; /* No recursion at top level */
+md->hasthen = (re->flags & PCRE_HASTHEN) != 0;
+
+md->lcc = tables + lcc_offset;
+md->fcc = tables + fcc_offset;
+md->ctypes = tables + ctypes_offset;
+
+/* Handle different \R options. */
+
+switch (options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE))
+ {
+ case 0:
+ if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0)
+ md->bsr_anycrlf = (re->options & PCRE_BSR_ANYCRLF) != 0;
+ else
+#ifdef BSR_ANYCRLF
+ md->bsr_anycrlf = TRUE;
+#else
+ md->bsr_anycrlf = FALSE;
+#endif
+ break;
+
+ case PCRE_BSR_ANYCRLF:
+ md->bsr_anycrlf = TRUE;
+ break;
+
+ case PCRE_BSR_UNICODE:
+ md->bsr_anycrlf = FALSE;
+ break;
+
+ default: return PCRE_ERROR_BADNEWLINE;
+ }
+
+/* Handle different types of newline. The three bits give eight cases. If
+nothing is set at run time, whatever was used at compile time applies. */
+
+switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options :
+ (pcre_uint32)options) & PCRE_NEWLINE_BITS)
+ {
+ case 0: newline = NEWLINE; break; /* Compile-time default */
+ case PCRE_NEWLINE_CR: newline = CHAR_CR; break;
+ case PCRE_NEWLINE_LF: newline = CHAR_NL; break;
+ case PCRE_NEWLINE_CR+
+ PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break;
+ case PCRE_NEWLINE_ANY: newline = -1; break;
+ case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
+ default: return PCRE_ERROR_BADNEWLINE;
+ }
+
+if (newline == -2)
+ {
+ md->nltype = NLTYPE_ANYCRLF;
+ }
+else if (newline < 0)
+ {
+ md->nltype = NLTYPE_ANY;
+ }
+else
+ {
+ md->nltype = NLTYPE_FIXED;
+ if (newline > 255)
+ {
+ md->nllen = 2;
+ md->nl[0] = (newline >> 8) & 255;
+ md->nl[1] = newline & 255;
+ }
+ else
+ {
+ md->nllen = 1;
+ md->nl[0] = newline;
+ }
+ }
+
+/* Partial matching was originally supported only for a restricted set of
+regexes; from release 8.00 there are no restrictions, but the bits are still
+defined (though never set). So there's no harm in leaving this code. */
+
+if (md->partial && (re->flags & PCRE_NOPARTIAL) != 0)
+ return PCRE_ERROR_BADPARTIAL;
+
+/* If the expression has got more back references than the offsets supplied can
+hold, we get a temporary chunk of working store to use during the matching.
+Otherwise, we can use the vector supplied, rounding down its size to a multiple
+of 3. */
+
+ocount = offsetcount - (offsetcount % 3);
+arg_offset_max = (2*ocount)/3;
+
+if (re->top_backref > 0 && re->top_backref >= ocount/3)
+ {
+ ocount = re->top_backref * 3 + 3;
+ md->offset_vector = (int *)(PUBL(malloc))(ocount * sizeof(int));
+ if (md->offset_vector == NULL) return PCRE_ERROR_NOMEMORY;
+ using_temporary_offsets = TRUE;
+ DPRINTF(("Got memory to hold back references\n"));
+ }
+else md->offset_vector = offsets;
+md->offset_end = ocount;
+md->offset_max = (2*ocount)/3;
+md->capture_last = 0;
+
+/* Reset the working variable associated with each extraction. These should
+never be used unless previously set, but they get saved and restored, and so we
+initialize them to avoid reading uninitialized locations. Also, unset the
+offsets for the matched string. This is really just for tidiness with callouts,
+in case they inspect these fields. */
+
+if (md->offset_vector != NULL)
+ {
+ register int *iptr = md->offset_vector + ocount;
+ register int *iend = iptr - re->top_bracket;
+ if (iend < md->offset_vector + 2) iend = md->offset_vector + 2;
+ while (--iptr >= iend) *iptr = -1;
+ md->offset_vector[0] = md->offset_vector[1] = -1;
+ }
+
+/* Set up the first character to match, if available. The first_char value is
+never set for an anchored regular expression, but the anchoring may be forced
+at run time, so we have to test for anchoring. The first char may be unset for
+an unanchored pattern, of course. If there's no first char and the pattern was
+studied, there may be a bitmap of possible first characters. */
+
+if (!anchored)
+ {
+ if ((re->flags & PCRE_FIRSTSET) != 0)
+ {
+ has_first_char = TRUE;
+ first_char = first_char2 = (pcre_uchar)(re->first_char);
+ if ((re->flags & PCRE_FCH_CASELESS) != 0)
+ {
+ first_char2 = TABLE_GET(first_char, md->fcc, first_char);
+#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
+ if (utf && first_char > 127)
+ first_char2 = UCD_OTHERCASE(first_char);
+#endif
+ }
+ }
+ else
+ if (!startline && study != NULL &&
+ (study->flags & PCRE_STUDY_MAPPED) != 0)
+ start_bits = study->start_bits;
+ }
+
+/* For anchored or unanchored matches, there may be a "last known required
+character" set. */
+
+if ((re->flags & PCRE_REQCHSET) != 0)
+ {
+ has_req_char = TRUE;
+ req_char = req_char2 = (pcre_uchar)(re->req_char);
+ if ((re->flags & PCRE_RCH_CASELESS) != 0)
+ {
+ req_char2 = TABLE_GET(req_char, md->fcc, req_char);
+#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
+ if (utf && req_char > 127)
+ req_char2 = UCD_OTHERCASE(req_char);
+#endif
+ }
+ }
+
+
+/* ==========================================================================*/
+
+/* Loop for handling unanchored repeated matching attempts; for anchored regexs
+the loop runs just once. */
+
+for(;;)
+ {
+ PCRE_PUCHAR save_end_subject = end_subject;
+ PCRE_PUCHAR new_start_match;
+
+ /* If firstline is TRUE, the start of the match is constrained to the first
+ line of a multiline string. That is, the match must be before or at the first
+ newline. Implement this by temporarily adjusting end_subject so that we stop
+ scanning at a newline. If the match fails at the newline, later code breaks
+ this loop. */
+
+ if (firstline)
+ {
+ PCRE_PUCHAR t = start_match;
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ while (t < md->end_subject && !IS_NEWLINE(t))
+ {
+ t++;
+ ACROSSCHAR(t < end_subject, *t, t++);
+ }
+ }
+ else
+#endif
+ while (t < md->end_subject && !IS_NEWLINE(t)) t++;
+ end_subject = t;
+ }
+
+ /* There are some optimizations that avoid running the match if a known
+ starting point is not found, or if a known later character is not present.
+ However, there is an option that disables these, for testing and for ensuring
+ that all callouts do actually occur. The option can be set in the regex by
+ (*NO_START_OPT) or passed in match-time options. */
+
+ if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)
+ {
+ /* Advance to a unique first char if there is one. */
+
+ if (has_first_char)
+ {
+ pcre_uchar smc;
+
+ if (first_char != first_char2)
+ while (start_match < end_subject &&
+ (smc = UCHAR21TEST(start_match)) != first_char && smc != first_char2)
+ start_match++;
+ else
+ while (start_match < end_subject && UCHAR21TEST(start_match) != first_char)
+ start_match++;
+ }
+
+ /* Or to just after a linebreak for a multiline match */
+
+ else if (startline)
+ {
+ if (start_match > md->start_subject + start_offset)
+ {
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ while (start_match < end_subject && !WAS_NEWLINE(start_match))
+ {
+ start_match++;
+ ACROSSCHAR(start_match < end_subject, *start_match,
+ start_match++);
+ }
+ }
+ else
+#endif
+ while (start_match < end_subject && !WAS_NEWLINE(start_match))
+ start_match++;
+
+ /* If we have just passed a CR and the newline option is ANY or ANYCRLF,
+ and we are now at a LF, advance the match position by one more character.
+ */
+
+ if (start_match[-1] == CHAR_CR &&
+ (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
+ start_match < end_subject &&
+ UCHAR21TEST(start_match) == CHAR_NL)
+ start_match++;
+ }
+ }
+
+ /* Or to a non-unique first byte after study */
+
+ else if (start_bits != NULL)
+ {
+ while (start_match < end_subject)
+ {
+ register pcre_uint32 c = UCHAR21TEST(start_match);
+#ifndef COMPILE_PCRE8
+ if (c > 255) c = 255;
+#endif
+ if ((start_bits[c/8] & (1 << (c&7))) != 0) break;
+ start_match++;
+ }
+ }
+ } /* Starting optimizations */
+
+ /* Restore fudged end_subject */
+
+ end_subject = save_end_subject;
+
+ /* The following two optimizations are disabled for partial matching or if
+ disabling is explicitly requested. */
+
+ if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0 && !md->partial)
+ {
+ /* If the pattern was studied, a minimum subject length may be set. This 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
+ bytes to avoid spending too much time in this optimization. */
+
+ if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 &&
+ (pcre_uint32)(end_subject - start_match) < study->minlength)
+ {
+ rc = MATCH_NOMATCH;
+ break;
+ }
+
+ /* If req_char is set, we know that that character must appear in the
+ subject for the match to succeed. If the first character is set, req_char
+ must be later in the subject; otherwise the test starts at the match 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.
+
+ 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. */
+
+ if (has_req_char && end_subject - start_match < REQ_BYTE_MAX)
+ {
+ register PCRE_PUCHAR p = start_match + (has_first_char? 1:0);
+
+ /* We don't need to repeat the search if we haven't yet reached the
+ place we found it at last time. */
+
+ if (p > req_char_ptr)
+ {
+ if (req_char != req_char2)
+ {
+ while (p < end_subject)
+ {
+ register pcre_uint32 pp = UCHAR21INCTEST(p);
+ if (pp == req_char || pp == req_char2) { p--; break; }
+ }
+ }
+ else
+ {
+ while (p < end_subject)
+ {
+ if (UCHAR21INCTEST(p) == req_char) { p--; break; }
+ }
+ }
+
+ /* If we can't find the required character, break the matching loop,
+ forcing a match failure. */
+
+ if (p >= end_subject)
+ {
+ rc = MATCH_NOMATCH;
+ break;
+ }
+
+ /* If we have found the required character, save the point where we
+ found it, so that we don't search again next time round the loop if
+ the start hasn't passed this character yet. */
+
+ req_char_ptr = p;
+ }
+ }
+ }
+
+#ifdef PCRE_DEBUG /* Sigh. Some compilers never learn. */
+ printf(">>>> Match against: ");
+ pchars(start_match, end_subject - start_match, TRUE, md);
+ printf("\n");
+#endif
+
+ /* OK, we can now run the match. If "hitend" is set afterwards, remember the
+ first starting point for which a partial match was found. */
+
+ md->start_match_ptr = start_match;
+ md->start_used_ptr = start_match;
+ md->match_call_count = 0;
+ md->match_function_type = 0;
+ md->end_offset_top = 0;
+ md->skip_arg_count = 0;
+ rc = match(start_match, md->start_code, start_match, 2, md, NULL, 0);
+ if (md->hitend && start_partial == NULL)
+ {
+ start_partial = md->start_used_ptr;
+ match_partial = start_match;
+ }
+
+ switch(rc)
+ {
+ /* If MATCH_SKIP_ARG reaches this level it means that a MARK that matched
+ the SKIP's arg was not found. In this circumstance, Perl ignores the SKIP
+ entirely. The only way we can do that is to re-do the match at the same
+ point, with a flag to force SKIP with an argument to be ignored. Just
+ treating this case as NOMATCH does not work because it does not check other
+ alternatives in patterns such as A(*SKIP:A)B|AC when the subject is AC. */
+
+ case MATCH_SKIP_ARG:
+ new_start_match = start_match;
+ md->ignore_skip_arg = md->skip_arg_count;
+ break;
+
+ /* SKIP passes back the next starting point explicitly, but if it is no
+ greater than the match we have just done, treat it as NOMATCH. */
+
+ case MATCH_SKIP:
+ if (md->start_match_ptr > start_match)
+ {
+ new_start_match = md->start_match_ptr;
+ break;
+ }
+ /* Fall through */
+
+ /* NOMATCH and PRUNE advance by one character. THEN at this level acts
+ exactly like PRUNE. Unset ignore SKIP-with-argument. */
+
+ case MATCH_NOMATCH:
+ case MATCH_PRUNE:
+ case MATCH_THEN:
+ md->ignore_skip_arg = 0;
+ new_start_match = start_match + 1;
+#ifdef SUPPORT_UTF
+ if (utf)
+ ACROSSCHAR(new_start_match < end_subject, *new_start_match,
+ new_start_match++);
+#endif
+ break;
+
+ /* COMMIT disables the bumpalong, but otherwise behaves as NOMATCH. */
+
+ case MATCH_COMMIT:
+ rc = MATCH_NOMATCH;
+ goto ENDLOOP;
+
+ /* Any other return is either a match, or some kind of error. */
+
+ default:
+ goto ENDLOOP;
+ }
+
+ /* Control reaches here for the various types of "no match at this point"
+ result. Reset the code to MATCH_NOMATCH for subsequent checking. */
+
+ rc = MATCH_NOMATCH;
+
+ /* If PCRE_FIRSTLINE is set, the match must happen before or at the first
+ newline in the subject (though it may continue over the newline). Therefore,
+ if we have just failed to match, starting at a newline, do not continue. */
+
+ if (firstline && IS_NEWLINE(start_match)) break;
+
+ /* Advance to new matching position */
+
+ start_match = new_start_match;
+
+ /* Break the loop if the pattern is anchored or if we have passed the end of
+ the subject. */
+
+ if (anchored || start_match > end_subject) break;
+
+ /* If we have just passed a CR and we are now at a LF, and the pattern does
+ not contain any explicit matches for \r or \n, and the newline option is CRLF
+ or ANY or ANYCRLF, advance the match position by one more character. In
+ normal matching start_match will aways be greater than the first position at
+ this stage, but a failed *SKIP can cause a return at the same point, which is
+ why the first test exists. */
+
+ if (start_match > (PCRE_PUCHAR)subject + start_offset &&
+ start_match[-1] == CHAR_CR &&
+ start_match < end_subject &&
+ *start_match == CHAR_NL &&
+ (re->flags & PCRE_HASCRORLF) == 0 &&
+ (md->nltype == NLTYPE_ANY ||
+ md->nltype == NLTYPE_ANYCRLF ||
+ md->nllen == 2))
+ start_match++;
+
+ md->mark = NULL; /* Reset for start of next match attempt */
+ } /* End of for(;;) "bumpalong" loop */
+
+/* ==========================================================================*/
+
+/* We reach here when rc is not MATCH_NOMATCH, or if one of the stopping
+conditions is true:
+
+(1) The pattern is anchored or the match was failed by (*COMMIT);
+
+(2) We are past the end of the subject;
+
+(3) PCRE_FIRSTLINE is set and we have failed to match at a newline, because
+ this option requests that a match occur at or before the first newline in
+ the subject.
+
+When we have a match and the offset vector is big enough to deal with any
+backreferences, captured substring offsets will already be set up. In the case
+where we had to get some local store to hold offsets for backreference
+processing, copy those that we can. In this case there need not be overflow if
+certain parts of the pattern were not used, even though there are more
+capturing parentheses than vector slots. */
+
+ENDLOOP:
+
+if (rc == MATCH_MATCH || rc == MATCH_ACCEPT)
+ {
+ if (using_temporary_offsets)
+ {
+ if (arg_offset_max >= 4)
+ {
+ memcpy(offsets + 2, md->offset_vector + 2,
+ (arg_offset_max - 2) * sizeof(int));
+ DPRINTF(("Copied offsets from temporary memory\n"));
+ }
+ if (md->end_offset_top > arg_offset_max) md->capture_last |= OVFLBIT;
+ DPRINTF(("Freeing temporary memory\n"));
+ (PUBL(free))(md->offset_vector);
+ }
+
+ /* Set the return code to the number of captured strings, or 0 if there were
+ too many to fit into the vector. */
+
+ rc = ((md->capture_last & OVFLBIT) != 0 &&
+ md->end_offset_top >= arg_offset_max)?
+ 0 : md->end_offset_top/2;
+
+ /* If there is space in the offset vector, set any unused pairs at the end of
+ the pattern to -1 for backwards compatibility. It is documented that this
+ happens. In earlier versions, the whole set of potential capturing offsets
+ was set to -1 each time round the loop, but this is handled differently now.
+ "Gaps" are set to -1 dynamically instead (this fixes a bug). Thus, it is only
+ those at the end that need unsetting here. We can't just unset them all at
+ the start of the whole thing because they may get set in one branch that is
+ not the final matching branch. */
+
+ if (md->end_offset_top/2 <= re->top_bracket && offsets != NULL)
+ {
+ register int *iptr, *iend;
+ int resetcount = 2 + re->top_bracket * 2;
+ if (resetcount > offsetcount) resetcount = offsetcount;
+ iptr = offsets + md->end_offset_top;
+ iend = offsets + resetcount;
+ while (iptr < iend) *iptr++ = -1;
+ }
+
+ /* If there is space, set up the whole thing as substring 0. The value of
+ md->start_match_ptr might be modified if \K was encountered on the success
+ matching path. */
+
+ if (offsetcount < 2) rc = 0; else
+ {
+ offsets[0] = (int)(md->start_match_ptr - md->start_subject);
+ offsets[1] = (int)(md->end_match_ptr - md->start_subject);
+ }
+
+ /* Return MARK data if requested */
+
+ if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0)
+ *(extra_data->mark) = (pcre_uchar *)md->mark;
+ DPRINTF((">>>> returning %d\n", rc));
+#ifdef NO_RECURSE
+ release_match_heapframes(&frame_zero);
+#endif
+ return rc;
+ }
+
+/* Control gets here if there has been an error, or if the overall match
+attempt has failed at all permitted starting positions. */
+
+if (using_temporary_offsets)
+ {
+ DPRINTF(("Freeing temporary memory\n"));
+ (PUBL(free))(md->offset_vector);
+ }
+
+/* For anything other than nomatch or partial match, just return the code. */
+
+if (rc != MATCH_NOMATCH && rc != PCRE_ERROR_PARTIAL)
+ {
+ DPRINTF((">>>> error: returning %d\n", rc));
+#ifdef NO_RECURSE
+ release_match_heapframes(&frame_zero);
+#endif
+ return rc;
+ }
+
+/* Handle partial matches - disable any mark data */
+
+if (match_partial != NULL)
+ {
+ DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n"));
+ md->mark = NULL;
+ if (offsetcount > 1)
+ {
+ offsets[0] = (int)(start_partial - (PCRE_PUCHAR)subject);
+ offsets[1] = (int)(end_subject - (PCRE_PUCHAR)subject);
+ if (offsetcount > 2)
+ offsets[2] = (int)(match_partial - (PCRE_PUCHAR)subject);
+ }
+ rc = PCRE_ERROR_PARTIAL;
+ }
+
+/* This is the classic nomatch case */
+
+else
+ {
+ DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n"));
+ rc = PCRE_ERROR_NOMATCH;
+ }
+
+/* Return the MARK data if it has been requested. */
+
+if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0)
+ *(extra_data->mark) = (pcre_uchar *)md->nomatch_mark;
+#ifdef NO_RECURSE
+ release_match_heapframes(&frame_zero);
+#endif
+return rc;
+}
+
+/* End of pcre_exec.c */
diff --git a/plugins/Pcre16/src/pcre_fullinfo.c b/plugins/Pcre16/src/pcre_fullinfo.c
new file mode 100644
index 0000000000..a6c2ece6ca
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_fullinfo.c
@@ -0,0 +1,245 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2013 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 external function pcre_fullinfo(), which returns
+information about a compiled pattern. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+
+/*************************************************
+* Return info about compiled pattern *
+*************************************************/
+
+/* This is a newer "info" function which has an extensible interface so
+that additional items can be added compatibly.
+
+Arguments:
+ argument_re points to compiled code
+ extra_data points extra data, or NULL
+ what what information is required
+ where where to put the information
+
+Returns: 0 if data returned, negative on error
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_fullinfo(const pcre *argument_re, const pcre_extra *extra_data,
+ int what, void *where)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_fullinfo(const pcre16 *argument_re, const pcre16_extra *extra_data,
+ int what, void *where)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre32_fullinfo(const pcre32 *argument_re, const pcre32_extra *extra_data,
+ int what, void *where)
+#endif
+{
+const REAL_PCRE *re = (const REAL_PCRE *)argument_re;
+const pcre_study_data *study = NULL;
+
+if (re == NULL || where == NULL) return PCRE_ERROR_NULL;
+
+if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0)
+ study = (const pcre_study_data *)extra_data->study_data;
+
+/* Check that the first field in the block is the magic number. If it is not,
+return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to
+REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which
+means that the pattern is likely compiled with different endianness. */
+
+if (re->magic_number != MAGIC_NUMBER)
+ return re->magic_number == REVERSED_MAGIC_NUMBER?
+ PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC;
+
+/* Check that this pattern was compiled in the correct bit mode */
+
+if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
+
+switch (what)
+ {
+ case PCRE_INFO_OPTIONS:
+ *((unsigned long int *)where) = re->options & PUBLIC_COMPILE_OPTIONS;
+ break;
+
+ case PCRE_INFO_SIZE:
+ *((size_t *)where) = re->size;
+ break;
+
+ case PCRE_INFO_STUDYSIZE:
+ *((size_t *)where) = (study == NULL)? 0 : study->size;
+ break;
+
+ case PCRE_INFO_JITSIZE:
+#ifdef SUPPORT_JIT
+ *((size_t *)where) =
+ (extra_data != NULL &&
+ (extra_data->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
+ extra_data->executable_jit != NULL)?
+ PRIV(jit_get_size)(extra_data->executable_jit) : 0;
+#else
+ *((size_t *)where) = 0;
+#endif
+ break;
+
+ case PCRE_INFO_CAPTURECOUNT:
+ *((int *)where) = re->top_bracket;
+ break;
+
+ case PCRE_INFO_BACKREFMAX:
+ *((int *)where) = re->top_backref;
+ break;
+
+ case PCRE_INFO_FIRSTBYTE:
+ *((int *)where) =
+ ((re->flags & PCRE_FIRSTSET) != 0)? (int)re->first_char :
+ ((re->flags & PCRE_STARTLINE) != 0)? -1 : -2;
+ break;
+
+ case PCRE_INFO_FIRSTCHARACTER:
+ *((pcre_uint32 *)where) =
+ (re->flags & PCRE_FIRSTSET) != 0 ? re->first_char : 0;
+ break;
+
+ case PCRE_INFO_FIRSTCHARACTERFLAGS:
+ *((int *)where) =
+ ((re->flags & PCRE_FIRSTSET) != 0) ? 1 :
+ ((re->flags & PCRE_STARTLINE) != 0) ? 2 : 0;
+ break;
+
+ /* Make sure we pass back the pointer to the bit vector in the external
+ block, not the internal copy (with flipped integer fields). */
+
+ case PCRE_INFO_FIRSTTABLE:
+ *((const pcre_uint8 **)where) =
+ (study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)?
+ ((const pcre_study_data *)extra_data->study_data)->start_bits : NULL;
+ break;
+
+ case PCRE_INFO_MINLENGTH:
+ *((int *)where) =
+ (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0)?
+ (int)(study->minlength) : -1;
+ break;
+
+ case PCRE_INFO_JIT:
+ *((int *)where) = extra_data != NULL &&
+ (extra_data->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
+ extra_data->executable_jit != NULL;
+ break;
+
+ case PCRE_INFO_LASTLITERAL:
+ *((int *)where) =
+ ((re->flags & PCRE_REQCHSET) != 0)? (int)re->req_char : -1;
+ break;
+
+ case PCRE_INFO_REQUIREDCHAR:
+ *((pcre_uint32 *)where) =
+ ((re->flags & PCRE_REQCHSET) != 0) ? re->req_char : 0;
+ break;
+
+ case PCRE_INFO_REQUIREDCHARFLAGS:
+ *((int *)where) =
+ ((re->flags & PCRE_REQCHSET) != 0);
+ break;
+
+ case PCRE_INFO_NAMEENTRYSIZE:
+ *((int *)where) = re->name_entry_size;
+ break;
+
+ case PCRE_INFO_NAMECOUNT:
+ *((int *)where) = re->name_count;
+ break;
+
+ case PCRE_INFO_NAMETABLE:
+ *((const pcre_uchar **)where) = (const pcre_uchar *)re + re->name_table_offset;
+ break;
+
+ case PCRE_INFO_DEFAULT_TABLES:
+ *((const pcre_uint8 **)where) = (const pcre_uint8 *)(PRIV(default_tables));
+ break;
+
+ /* From release 8.00 this will always return TRUE because NOPARTIAL is
+ no longer ever set (the restrictions have been removed). */
+
+ case PCRE_INFO_OKPARTIAL:
+ *((int *)where) = (re->flags & PCRE_NOPARTIAL) == 0;
+ break;
+
+ case PCRE_INFO_JCHANGED:
+ *((int *)where) = (re->flags & PCRE_JCHANGED) != 0;
+ break;
+
+ case PCRE_INFO_HASCRORLF:
+ *((int *)where) = (re->flags & PCRE_HASCRORLF) != 0;
+ break;
+
+ case PCRE_INFO_MAXLOOKBEHIND:
+ *((int *)where) = re->max_lookbehind;
+ break;
+
+ case PCRE_INFO_MATCHLIMIT:
+ if ((re->flags & PCRE_MLSET) == 0) return PCRE_ERROR_UNSET;
+ *((pcre_uint32 *)where) = re->limit_match;
+ break;
+
+ case PCRE_INFO_RECURSIONLIMIT:
+ if ((re->flags & PCRE_RLSET) == 0) return PCRE_ERROR_UNSET;
+ *((pcre_uint32 *)where) = re->limit_recursion;
+ break;
+
+ case PCRE_INFO_MATCH_EMPTY:
+ *((int *)where) = (re->flags & PCRE_MATCH_EMPTY) != 0;
+ break;
+
+ default: return PCRE_ERROR_BADOPTION;
+ }
+
+return 0;
+}
+
+/* End of pcre_fullinfo.c */
diff --git a/plugins/Pcre16/src/pcre_get.c b/plugins/Pcre16/src/pcre_get.c
new file mode 100644
index 0000000000..8094b34bbf
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_get.c
@@ -0,0 +1,662 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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 some convenience functions for extracting substrings
+from the subject string after a regex match has succeeded. The original idea
+for these functions came from Scott Wimer. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+
+/*************************************************
+* Find number for named string *
+*************************************************/
+
+/* This function is used by the get_first_set() function below, as well
+as being generally available. It assumes that names are unique.
+
+Arguments:
+ code the compiled regex
+ stringname the name whose number is required
+
+Returns: the number of the named parentheses, or a negative number
+ (PCRE_ERROR_NOSUBSTRING) if not found
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_get_stringnumber(const pcre *code, const char *stringname)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_get_stringnumber(const pcre16 *code, PCRE_SPTR16 stringname)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre32_get_stringnumber(const pcre32 *code, PCRE_SPTR32 stringname)
+#endif
+{
+int rc;
+int entrysize;
+int top, bot;
+pcre_uchar *nametable;
+
+#ifdef COMPILE_PCRE8
+if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
+ return rc;
+if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
+
+if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
+ return rc;
+if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
+ return rc;
+#endif
+#ifdef COMPILE_PCRE16
+if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
+ return rc;
+if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
+
+if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
+ return rc;
+if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
+ return rc;
+#endif
+#ifdef COMPILE_PCRE32
+if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
+ return rc;
+if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
+
+if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
+ return rc;
+if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
+ return rc;
+#endif
+
+bot = 0;
+while (top > bot)
+ {
+ int mid = (top + bot) / 2;
+ pcre_uchar *entry = nametable + entrysize*mid;
+ int c = STRCMP_UC_UC((pcre_uchar *)stringname,
+ (pcre_uchar *)(entry + IMM2_SIZE));
+ if (c == 0) return GET2(entry, 0);
+ if (c > 0) bot = mid + 1; else top = mid;
+ }
+
+return PCRE_ERROR_NOSUBSTRING;
+}
+
+
+
+/*************************************************
+* Find (multiple) entries for named string *
+*************************************************/
+
+/* This is used by the get_first_set() function below, as well as being
+generally available. It is used when duplicated names are permitted.
+
+Arguments:
+ code the compiled regex
+ stringname the name whose entries required
+ firstptr where to put the pointer to the first entry
+ lastptr where to put the pointer to the last entry
+
+Returns: the length of each entry, or a negative number
+ (PCRE_ERROR_NOSUBSTRING) if not found
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_get_stringtable_entries(const pcre *code, const char *stringname,
+ char **firstptr, char **lastptr)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_get_stringtable_entries(const pcre16 *code, PCRE_SPTR16 stringname,
+ PCRE_UCHAR16 **firstptr, PCRE_UCHAR16 **lastptr)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre32_get_stringtable_entries(const pcre32 *code, PCRE_SPTR32 stringname,
+ PCRE_UCHAR32 **firstptr, PCRE_UCHAR32 **lastptr)
+#endif
+{
+int rc;
+int entrysize;
+int top, bot;
+pcre_uchar *nametable, *lastentry;
+
+#ifdef COMPILE_PCRE8
+if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
+ return rc;
+if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
+
+if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
+ return rc;
+if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
+ return rc;
+#endif
+#ifdef COMPILE_PCRE16
+if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
+ return rc;
+if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
+
+if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
+ return rc;
+if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
+ return rc;
+#endif
+#ifdef COMPILE_PCRE32
+if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
+ return rc;
+if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
+
+if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
+ return rc;
+if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
+ return rc;
+#endif
+
+lastentry = nametable + entrysize * (top - 1);
+bot = 0;
+while (top > bot)
+ {
+ int mid = (top + bot) / 2;
+ pcre_uchar *entry = nametable + entrysize*mid;
+ int c = STRCMP_UC_UC((pcre_uchar *)stringname,
+ (pcre_uchar *)(entry + IMM2_SIZE));
+ if (c == 0)
+ {
+ pcre_uchar *first = entry;
+ pcre_uchar *last = entry;
+ while (first > nametable)
+ {
+ if (STRCMP_UC_UC((pcre_uchar *)stringname,
+ (pcre_uchar *)(first - entrysize + IMM2_SIZE)) != 0) break;
+ first -= entrysize;
+ }
+ while (last < lastentry)
+ {
+ if (STRCMP_UC_UC((pcre_uchar *)stringname,
+ (pcre_uchar *)(last + entrysize + IMM2_SIZE)) != 0) break;
+ last += entrysize;
+ }
+#if defined COMPILE_PCRE8
+ *firstptr = (char *)first;
+ *lastptr = (char *)last;
+#elif defined COMPILE_PCRE16
+ *firstptr = (PCRE_UCHAR16 *)first;
+ *lastptr = (PCRE_UCHAR16 *)last;
+#elif defined COMPILE_PCRE32
+ *firstptr = (PCRE_UCHAR32 *)first;
+ *lastptr = (PCRE_UCHAR32 *)last;
+#endif
+ return entrysize;
+ }
+ if (c > 0) bot = mid + 1; else top = mid;
+ }
+
+return PCRE_ERROR_NOSUBSTRING;
+}
+
+
+
+/*************************************************
+* Find first set of multiple named strings *
+*************************************************/
+
+/* This function allows for duplicate names in the table of named substrings.
+It returns the number of the first one that was set in a pattern match.
+
+Arguments:
+ code the compiled regex
+ stringname the name of the capturing substring
+ ovector the vector of matched substrings
+
+Returns: the number of the first that is set,
+ or the number of the last one if none are set,
+ or a negative number on error
+*/
+
+#if defined COMPILE_PCRE8
+static int
+get_first_set(const pcre *code, const char *stringname, int *ovector)
+#elif defined COMPILE_PCRE16
+static int
+get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector)
+#elif defined COMPILE_PCRE32
+static int
+get_first_set(const pcre32 *code, PCRE_SPTR32 stringname, int *ovector)
+#endif
+{
+const REAL_PCRE *re = (const REAL_PCRE *)code;
+int entrysize;
+pcre_uchar *entry;
+#if defined COMPILE_PCRE8
+char *first, *last;
+#elif defined COMPILE_PCRE16
+PCRE_UCHAR16 *first, *last;
+#elif defined COMPILE_PCRE32
+PCRE_UCHAR32 *first, *last;
+#endif
+
+#if defined COMPILE_PCRE8
+if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0)
+ return pcre_get_stringnumber(code, stringname);
+entrysize = pcre_get_stringtable_entries(code, stringname, &first, &last);
+#elif defined COMPILE_PCRE16
+if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0)
+ return pcre16_get_stringnumber(code, stringname);
+entrysize = pcre16_get_stringtable_entries(code, stringname, &first, &last);
+#elif defined COMPILE_PCRE32
+if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0)
+ return pcre32_get_stringnumber(code, stringname);
+entrysize = pcre32_get_stringtable_entries(code, stringname, &first, &last);
+#endif
+if (entrysize <= 0) return entrysize;
+for (entry = (pcre_uchar *)first; entry <= (pcre_uchar *)last; entry += entrysize)
+ {
+ int n = GET2(entry, 0);
+ if (ovector[n*2] >= 0) return n;
+ }
+return GET2(entry, 0);
+}
+
+
+
+
+/*************************************************
+* Copy captured string to given buffer *
+*************************************************/
+
+/* This function copies a single captured substring into a given buffer.
+Note that we use memcpy() rather than strncpy() in case there are binary zeros
+in the string.
+
+Arguments:
+ subject the subject string that was matched
+ ovector pointer to the offsets table
+ stringcount the number of substrings that were captured
+ (i.e. the yield of the pcre_exec call, unless
+ that was zero, in which case it should be 1/3
+ of the offset table size)
+ stringnumber the number of the required substring
+ buffer where to put the substring
+ size the size of the buffer
+
+Returns: if successful:
+ the length of the copied string, not including the zero
+ that is put on the end; can be zero
+ if not successful:
+ PCRE_ERROR_NOMEMORY (-6) buffer too small
+ PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_copy_substring(const char *subject, int *ovector, int stringcount,
+ int stringnumber, char *buffer, int size)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_copy_substring(PCRE_SPTR16 subject, int *ovector, int stringcount,
+ int stringnumber, PCRE_UCHAR16 *buffer, int size)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre32_copy_substring(PCRE_SPTR32 subject, int *ovector, int stringcount,
+ int stringnumber, PCRE_UCHAR32 *buffer, int size)
+#endif
+{
+int yield;
+if (stringnumber < 0 || stringnumber >= stringcount)
+ return PCRE_ERROR_NOSUBSTRING;
+stringnumber *= 2;
+yield = ovector[stringnumber+1] - ovector[stringnumber];
+if (size < yield + 1) return PCRE_ERROR_NOMEMORY;
+memcpy(buffer, subject + ovector[stringnumber], IN_UCHARS(yield));
+buffer[yield] = 0;
+return yield;
+}
+
+
+
+/*************************************************
+* Copy named captured string to given buffer *
+*************************************************/
+
+/* This function copies a single captured substring into a given buffer,
+identifying it by name. If the regex permits duplicate names, the first
+substring that is set is chosen.
+
+Arguments:
+ code the compiled regex
+ subject the subject string that was matched
+ ovector pointer to the offsets table
+ stringcount the number of substrings that were captured
+ (i.e. the yield of the pcre_exec call, unless
+ that was zero, in which case it should be 1/3
+ of the offset table size)
+ stringname the name of the required substring
+ buffer where to put the substring
+ size the size of the buffer
+
+Returns: if successful:
+ the length of the copied string, not including the zero
+ that is put on the end; can be zero
+ if not successful:
+ PCRE_ERROR_NOMEMORY (-6) buffer too small
+ PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_copy_named_substring(const pcre *code, const char *subject,
+ int *ovector, int stringcount, const char *stringname,
+ char *buffer, int size)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_copy_named_substring(const pcre16 *code, PCRE_SPTR16 subject,
+ int *ovector, int stringcount, PCRE_SPTR16 stringname,
+ PCRE_UCHAR16 *buffer, int size)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre32_copy_named_substring(const pcre32 *code, PCRE_SPTR32 subject,
+ int *ovector, int stringcount, PCRE_SPTR32 stringname,
+ PCRE_UCHAR32 *buffer, int size)
+#endif
+{
+int n = get_first_set(code, stringname, ovector);
+if (n <= 0) return n;
+#if defined COMPILE_PCRE8
+return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
+#elif defined COMPILE_PCRE16
+return pcre16_copy_substring(subject, ovector, stringcount, n, buffer, size);
+#elif defined COMPILE_PCRE32
+return pcre32_copy_substring(subject, ovector, stringcount, n, buffer, size);
+#endif
+}
+
+
+
+/*************************************************
+* Copy all captured strings to new store *
+*************************************************/
+
+/* This function gets one chunk of store and builds a list of pointers and all
+of the captured substrings in it. A NULL pointer is put on the end of the list.
+
+Arguments:
+ subject the subject string that was matched
+ ovector pointer to the offsets table
+ stringcount the number of substrings that were captured
+ (i.e. the yield of the pcre_exec call, unless
+ that was zero, in which case it should be 1/3
+ of the offset table size)
+ listptr set to point to the list of pointers
+
+Returns: if successful: 0
+ if not successful:
+ PCRE_ERROR_NOMEMORY (-6) failed to get store
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_get_substring_list(const char *subject, int *ovector, int stringcount,
+ const char ***listptr)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_get_substring_list(PCRE_SPTR16 subject, int *ovector, int stringcount,
+ PCRE_SPTR16 **listptr)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre32_get_substring_list(PCRE_SPTR32 subject, int *ovector, int stringcount,
+ PCRE_SPTR32 **listptr)
+#endif
+{
+int i;
+int size = sizeof(pcre_uchar *);
+int double_count = stringcount * 2;
+pcre_uchar **stringlist;
+pcre_uchar *p;
+
+for (i = 0; i < double_count; i += 2)
+ size += sizeof(pcre_uchar *) + IN_UCHARS(ovector[i+1] - ovector[i] + 1);
+
+stringlist = (pcre_uchar **)(PUBL(malloc))(size);
+if (stringlist == NULL) return PCRE_ERROR_NOMEMORY;
+
+#if defined COMPILE_PCRE8
+*listptr = (const char **)stringlist;
+#elif defined COMPILE_PCRE16
+*listptr = (PCRE_SPTR16 *)stringlist;
+#elif defined COMPILE_PCRE32
+*listptr = (PCRE_SPTR32 *)stringlist;
+#endif
+p = (pcre_uchar *)(stringlist + stringcount + 1);
+
+for (i = 0; i < double_count; i += 2)
+ {
+ int len = ovector[i+1] - ovector[i];
+ memcpy(p, subject + ovector[i], IN_UCHARS(len));
+ *stringlist++ = p;
+ p += len;
+ *p++ = 0;
+ }
+
+*stringlist = NULL;
+return 0;
+}
+
+
+
+/*************************************************
+* Free store obtained by get_substring_list *
+*************************************************/
+
+/* This function exists for the benefit of people calling PCRE from non-C
+programs that can call its functions, but not free() or (PUBL(free))()
+directly.
+
+Argument: the result of a previous pcre_get_substring_list()
+Returns: nothing
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
+pcre_free_substring_list(const char **pointer)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
+pcre16_free_substring_list(PCRE_SPTR16 *pointer)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
+pcre32_free_substring_list(PCRE_SPTR32 *pointer)
+#endif
+{
+(PUBL(free))((void *)pointer);
+}
+
+
+
+/*************************************************
+* Copy captured string to new store *
+*************************************************/
+
+/* This function copies a single captured substring into a piece of new
+store
+
+Arguments:
+ subject the subject string that was matched
+ ovector pointer to the offsets table
+ stringcount the number of substrings that were captured
+ (i.e. the yield of the pcre_exec call, unless
+ that was zero, in which case it should be 1/3
+ of the offset table size)
+ stringnumber the number of the required substring
+ stringptr where to put a pointer to the substring
+
+Returns: if successful:
+ the length of the string, not including the zero that
+ is put on the end; can be zero
+ if not successful:
+ PCRE_ERROR_NOMEMORY (-6) failed to get store
+ PCRE_ERROR_NOSUBSTRING (-7) substring not present
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_get_substring(const char *subject, int *ovector, int stringcount,
+ int stringnumber, const char **stringptr)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_get_substring(PCRE_SPTR16 subject, int *ovector, int stringcount,
+ int stringnumber, PCRE_SPTR16 *stringptr)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre32_get_substring(PCRE_SPTR32 subject, int *ovector, int stringcount,
+ int stringnumber, PCRE_SPTR32 *stringptr)
+#endif
+{
+int yield;
+pcre_uchar *substring;
+if (stringnumber < 0 || stringnumber >= stringcount)
+ return PCRE_ERROR_NOSUBSTRING;
+stringnumber *= 2;
+yield = ovector[stringnumber+1] - ovector[stringnumber];
+substring = (pcre_uchar *)(PUBL(malloc))(IN_UCHARS(yield + 1));
+if (substring == NULL) return PCRE_ERROR_NOMEMORY;
+memcpy(substring, subject + ovector[stringnumber], IN_UCHARS(yield));
+substring[yield] = 0;
+#if defined COMPILE_PCRE8
+*stringptr = (const char *)substring;
+#elif defined COMPILE_PCRE16
+*stringptr = (PCRE_SPTR16)substring;
+#elif defined COMPILE_PCRE32
+*stringptr = (PCRE_SPTR32)substring;
+#endif
+return yield;
+}
+
+
+
+/*************************************************
+* Copy named captured string to new store *
+*************************************************/
+
+/* This function copies a single captured substring, identified by name, into
+new store. If the regex permits duplicate names, the first substring that is
+set is chosen.
+
+Arguments:
+ code the compiled regex
+ subject the subject string that was matched
+ ovector pointer to the offsets table
+ stringcount the number of substrings that were captured
+ (i.e. the yield of the pcre_exec call, unless
+ that was zero, in which case it should be 1/3
+ of the offset table size)
+ stringname the name of the required substring
+ stringptr where to put the pointer
+
+Returns: if successful:
+ the length of the copied string, not including the zero
+ that is put on the end; can be zero
+ if not successful:
+ PCRE_ERROR_NOMEMORY (-6) couldn't get memory
+ PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_get_named_substring(const pcre *code, const char *subject,
+ int *ovector, int stringcount, const char *stringname,
+ const char **stringptr)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_get_named_substring(const pcre16 *code, PCRE_SPTR16 subject,
+ int *ovector, int stringcount, PCRE_SPTR16 stringname,
+ PCRE_SPTR16 *stringptr)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre32_get_named_substring(const pcre32 *code, PCRE_SPTR32 subject,
+ int *ovector, int stringcount, PCRE_SPTR32 stringname,
+ PCRE_SPTR32 *stringptr)
+#endif
+{
+int n = get_first_set(code, stringname, ovector);
+if (n <= 0) return n;
+#if defined COMPILE_PCRE8
+return pcre_get_substring(subject, ovector, stringcount, n, stringptr);
+#elif defined COMPILE_PCRE16
+return pcre16_get_substring(subject, ovector, stringcount, n, stringptr);
+#elif defined COMPILE_PCRE32
+return pcre32_get_substring(subject, ovector, stringcount, n, stringptr);
+#endif
+}
+
+
+
+
+/*************************************************
+* Free store obtained by get_substring *
+*************************************************/
+
+/* This function exists for the benefit of people calling PCRE from non-C
+programs that can call its functions, but not free() or (PUBL(free))()
+directly.
+
+Argument: the result of a previous pcre_get_substring()
+Returns: nothing
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
+pcre_free_substring(const char *pointer)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
+pcre16_free_substring(PCRE_SPTR16 pointer)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
+pcre32_free_substring(PCRE_SPTR32 pointer)
+#endif
+{
+(PUBL(free))((void *)pointer);
+}
+
+/* End of pcre_get.c */
diff --git a/plugins/Pcre16/src/pcre_globals.c b/plugins/Pcre16/src/pcre_globals.c
new file mode 100644
index 0000000000..0f106aa901
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_globals.c
@@ -0,0 +1,86 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2014 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 global variables that are exported by the PCRE library.
+PCRE is thread-clean and doesn't use any global variables in the normal sense.
+However, it calls memory allocation and freeing functions via the four
+indirections below, and it can optionally do callouts, using the fifth
+indirection. These values can be changed by the caller, but are shared between
+all threads.
+
+For MS Visual Studio and Symbian OS, there are problems in initializing these
+variables to non-local functions. In these cases, therefore, an indirection via
+a local function is used.
+
+Also, when compiling for Virtual Pascal, things are done differently, and
+global variables are not used. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+#if defined _MSC_VER || defined __SYMBIAN32__
+static void* LocalPcreMalloc(size_t aSize)
+ {
+ return malloc(aSize);
+ }
+static void LocalPcreFree(void* aPtr)
+ {
+ free(aPtr);
+ }
+PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = LocalPcreMalloc;
+PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = LocalPcreFree;
+PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = LocalPcreMalloc;
+PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = LocalPcreFree;
+PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL;
+PCRE_EXP_DATA_DEFN int (*PUBL(stack_guard))(void) = NULL;
+
+#elif !defined VPCOMPAT
+PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = malloc;
+PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = free;
+PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = malloc;
+PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = free;
+PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL;
+PCRE_EXP_DATA_DEFN int (*PUBL(stack_guard))(void) = NULL;
+#endif
+
+/* End of pcre_globals.c */
diff --git a/plugins/Pcre16/src/pcre_internal.h b/plugins/Pcre16/src/pcre_internal.h
new file mode 100644
index 0000000000..6e915a0e45
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_internal.h
@@ -0,0 +1,2781 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2014 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 header contains definitions that are shared between the different
+modules, but which are not relevant to the exported API. This includes some
+functions whose names all begin with "_pcre_", "_pcre16_" or "_pcre32_"
+depending on the PRIV macro. */
+
+#ifndef PCRE_INTERNAL_H
+#define PCRE_INTERNAL_H
+
+/* Define PCRE_DEBUG to get debugging output on stdout. */
+
+#if 0
+#define PCRE_DEBUG
+#endif
+
+/* PCRE is compiled as an 8 bit library if it is not requested otherwise. */
+
+#if !defined COMPILE_PCRE16 && !defined COMPILE_PCRE32
+#define COMPILE_PCRE8
+#endif
+
+/* If SUPPORT_UCP is defined, SUPPORT_UTF must also be defined. The
+"configure" script ensures this, but not everybody uses "configure". */
+
+#if defined SUPPORT_UCP && !(defined SUPPORT_UTF)
+#define SUPPORT_UTF 1
+#endif
+
+/* We define SUPPORT_UTF if SUPPORT_UTF8 is enabled for compatibility
+reasons with existing code. */
+
+#if defined SUPPORT_UTF8 && !(defined SUPPORT_UTF)
+#define SUPPORT_UTF 1
+#endif
+
+/* Fixme: SUPPORT_UTF8 should be eventually disappear from the code.
+Until then we define it if SUPPORT_UTF is defined. */
+
+#if defined SUPPORT_UTF && !(defined SUPPORT_UTF8)
+#define SUPPORT_UTF8 1
+#endif
+
+/* We do not support both EBCDIC and UTF-8/16/32 at the same time. The "configure"
+script prevents both being selected, but not everybody uses "configure". */
+
+#if defined EBCDIC && defined SUPPORT_UTF
+#error The use of both EBCDIC and SUPPORT_UTF is not supported.
+#endif
+
+/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef
+inline, and there are *still* stupid compilers about that don't like indented
+pre-processor statements, or at least there were when I first wrote this. After
+all, it had only been about 10 years then...
+
+It turns out that the Mac Debugging.h header also defines the macro DPRINTF, so
+be absolutely sure we get our version. */
+
+#undef DPRINTF
+#ifdef PCRE_DEBUG
+#define DPRINTF(p) printf p
+#else
+#define DPRINTF(p) /* Nothing */
+#endif
+
+
+/* Standard C headers plus the external interface definition. The only time
+setjmp and stdarg are used is when NO_RECURSE is set. */
+
+#include <ctype.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Valgrind (memcheck) support */
+
+#ifdef SUPPORT_VALGRIND
+#include <valgrind/memcheck.h>
+#endif
+
+/* When compiling a DLL for Windows, the exported symbols have to be declared
+using some MS magic. I found some useful information on this web page:
+http://msdn2.microsoft.com/en-us/library/y4h7bcy6(VS.80).aspx. According to the
+information there, using __declspec(dllexport) without "extern" we have a
+definition; with "extern" we have a declaration. The settings here override the
+setting in pcre.h (which is included below); it defines only PCRE_EXP_DECL,
+which is all that is needed for applications (they just import the symbols). We
+use:
+
+ PCRE_EXP_DECL for declarations
+ PCRE_EXP_DEFN for definitions of exported functions
+ PCRE_EXP_DATA_DEFN for definitions of exported variables
+
+The reason for the two DEFN macros is that in non-Windows environments, one
+does not want to have "extern" before variable definitions because it leads to
+compiler warnings. So we distinguish between functions and variables. In
+Windows, the two should always be the same.
+
+The reason for wrapping this in #ifndef PCRE_EXP_DECL is so that pcretest,
+which is an application, but needs to import this file in order to "peek" at
+internals, can #include pcre.h first to get an application's-eye view.
+
+In principle, people compiling for non-Windows, non-Unix-like (i.e. uncommon,
+special-purpose environments) might want to stick other stuff in front of
+exported symbols. That's why, in the non-Windows case, we set PCRE_EXP_DEFN and
+PCRE_EXP_DATA_DEFN only if they are not already set. */
+
+#ifndef PCRE_EXP_DECL
+# ifdef _WIN32
+# ifndef PCRE_STATIC
+# define PCRE_EXP_DECL extern __declspec(dllexport)
+# define PCRE_EXP_DEFN __declspec(dllexport)
+# define PCRE_EXP_DATA_DEFN __declspec(dllexport)
+# else
+# define PCRE_EXP_DECL extern
+# define PCRE_EXP_DEFN
+# define PCRE_EXP_DATA_DEFN
+# endif
+# else
+# ifdef __cplusplus
+# define PCRE_EXP_DECL extern "C"
+# else
+# define PCRE_EXP_DECL extern
+# endif
+# ifndef PCRE_EXP_DEFN
+# define PCRE_EXP_DEFN PCRE_EXP_DECL
+# endif
+# ifndef PCRE_EXP_DATA_DEFN
+# define PCRE_EXP_DATA_DEFN
+# endif
+# endif
+#endif
+
+/* When compiling with the MSVC compiler, it is sometimes necessary to include
+a "calling convention" before exported function names. (This is secondhand
+information; I know nothing about MSVC myself). For example, something like
+
+ void __cdecl function(....)
+
+might be needed. In order so make this easy, all the exported functions have
+PCRE_CALL_CONVENTION just before their names. It is rarely needed; if not
+set, we ensure here that it has no effect. */
+
+#ifndef PCRE_CALL_CONVENTION
+#define PCRE_CALL_CONVENTION
+#endif
+
+/* We need to have types that specify unsigned 8, 16 and 32-bit integers. We
+cannot determine these outside the compilation (e.g. by running a program as
+part of "configure") because PCRE is often cross-compiled for use on other
+systems. Instead we make use of the maximum sizes that are available at
+preprocessor time in standard C environments. */
+
+typedef unsigned char pcre_uint8;
+
+#if USHRT_MAX == 65535
+typedef unsigned short pcre_uint16;
+typedef short pcre_int16;
+#define PCRE_UINT16_MAX USHRT_MAX
+#define PCRE_INT16_MAX SHRT_MAX
+#elif UINT_MAX == 65535
+typedef unsigned int pcre_uint16;
+typedef int pcre_int16;
+#define PCRE_UINT16_MAX UINT_MAX
+#define PCRE_INT16_MAX INT_MAX
+#else
+#error Cannot determine a type for 16-bit integers
+#endif
+
+#if UINT_MAX == 4294967295U
+typedef unsigned int pcre_uint32;
+typedef int pcre_int32;
+#define PCRE_UINT32_MAX UINT_MAX
+#define PCRE_INT32_MAX INT_MAX
+#elif ULONG_MAX == 4294967295UL
+typedef unsigned long int pcre_uint32;
+typedef long int pcre_int32;
+#define PCRE_UINT32_MAX ULONG_MAX
+#define PCRE_INT32_MAX LONG_MAX
+#else
+#error Cannot determine a type for 32-bit integers
+#endif
+
+/* When checking for integer overflow in pcre_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 <stdint.h>
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#if defined INT64_MAX || defined int64_t
+#define INT64_OR_DOUBLE int64_t
+#else
+#define INT64_OR_DOUBLE double
+#endif
+
+/* All character handling must be done as unsigned characters. Otherwise there
+are problems with top-bit-set characters and functions such as isspace().
+However, we leave the interface to the outside world as char * or short *,
+because that should make things easier for callers. This character type is
+called pcre_uchar.
+
+The IN_UCHARS macro multiply its argument with the byte size of the current
+pcre_uchar type. Useful for memcpy and such operations, whose require the
+byte size of their input/output buffers.
+
+The MAX_255 macro checks whether its pcre_uchar input is less than 256.
+
+The TABLE_GET macro is designed for accessing elements of tables whose contain
+exactly 256 items. When the character is able to contain more than 256
+items, some check is needed before accessing these tables.
+*/
+
+#if defined COMPILE_PCRE8
+
+typedef unsigned char pcre_uchar;
+#define IN_UCHARS(x) (x)
+#define MAX_255(c) 1
+#define TABLE_GET(c, table, default) ((table)[c])
+
+#elif defined COMPILE_PCRE16
+
+#if USHRT_MAX != 65535
+/* This is a warning message. Change PCRE_UCHAR16 to a 16 bit data type in
+pcre.h(.in) and disable (comment out) this message. */
+#error Warning: PCRE_UCHAR16 is not a 16 bit data type.
+#endif
+
+typedef pcre_uint16 pcre_uchar;
+#define UCHAR_SHIFT (1)
+#define IN_UCHARS(x) ((x) << UCHAR_SHIFT)
+#define MAX_255(c) ((c) <= 255u)
+#define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default))
+
+#elif defined COMPILE_PCRE32
+
+typedef pcre_uint32 pcre_uchar;
+#define UCHAR_SHIFT (2)
+#define IN_UCHARS(x) ((x) << UCHAR_SHIFT)
+#define MAX_255(c) ((c) <= 255u)
+#define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default))
+
+#else
+#error Unsupported compiling mode
+#endif /* COMPILE_PCRE[8|16|32] */
+
+/* This is an unsigned int value that no character can ever have. UTF-8
+characters only go up to 0x7fffffff (though Unicode doesn't go beyond
+0x0010ffff). */
+
+#define NOTACHAR 0xffffffff
+
+/* PCRE is able to support several different kinds of newline (CR, LF, CRLF,
+"any" and "anycrlf" at present). The following macros are used to package up
+testing for newlines. NLBLOCK, PSSTART, and PSEND are defined in the various
+modules to indicate in which datablock the parameters exist, and what the
+start/end of string field names are. */
+
+#define NLTYPE_FIXED 0 /* Newline is a fixed length string */
+#define NLTYPE_ANY 1 /* Newline is any Unicode line ending */
+#define NLTYPE_ANYCRLF 2 /* Newline is CR, LF, or CRLF */
+
+/* This macro checks for a newline at the given position */
+
+#define IS_NEWLINE(p) \
+ ((NLBLOCK->nltype != NLTYPE_FIXED)? \
+ ((p) < NLBLOCK->PSEND && \
+ PRIV(is_newline)((p), NLBLOCK->nltype, NLBLOCK->PSEND, \
+ &(NLBLOCK->nllen), utf)) \
+ : \
+ ((p) <= NLBLOCK->PSEND - NLBLOCK->nllen && \
+ UCHAR21TEST(p) == NLBLOCK->nl[0] && \
+ (NLBLOCK->nllen == 1 || UCHAR21TEST(p+1) == NLBLOCK->nl[1]) \
+ ) \
+ )
+
+/* This macro checks for a newline immediately preceding the given position */
+
+#define WAS_NEWLINE(p) \
+ ((NLBLOCK->nltype != NLTYPE_FIXED)? \
+ ((p) > NLBLOCK->PSSTART && \
+ PRIV(was_newline)((p), NLBLOCK->nltype, NLBLOCK->PSSTART, \
+ &(NLBLOCK->nllen), utf)) \
+ : \
+ ((p) >= NLBLOCK->PSSTART + NLBLOCK->nllen && \
+ UCHAR21TEST(p - NLBLOCK->nllen) == NLBLOCK->nl[0] && \
+ (NLBLOCK->nllen == 1 || UCHAR21TEST(p - NLBLOCK->nllen + 1) == NLBLOCK->nl[1]) \
+ ) \
+ )
+
+/* When PCRE is compiled as a C++ library, the subject pointer can be replaced
+with a custom type. This makes it possible, for example, to allow pcre_exec()
+to process subject strings that are discontinuous by using a smart pointer
+class. It must always be possible to inspect all of the subject string in
+pcre_exec() because of the way it backtracks. Two macros are required in the
+normal case, for sign-unspecified and unsigned char pointers. The former is
+used for the external interface and appears in pcre.h, which is why its name
+must begin with PCRE_. */
+
+#ifdef CUSTOM_SUBJECT_PTR
+#define PCRE_PUCHAR CUSTOM_SUBJECT_PTR
+#else
+#define PCRE_PUCHAR const pcre_uchar *
+#endif
+
+/* Include the public PCRE header and the definitions of UCP character property
+values. */
+
+#include "pcre.h"
+#include "ucp.h"
+
+#ifdef COMPILE_PCRE32
+/* Assert that the public PCRE_UCHAR32 is a 32-bit type */
+typedef int __assert_pcre_uchar32_size[sizeof(PCRE_UCHAR32) == 4 ? 1 : -1];
+#endif
+
+/* When compiling for use with the Virtual Pascal compiler, these functions
+need to have their names changed. PCRE must be compiled with the -DVPCOMPAT
+option on the command line. */
+
+#ifdef VPCOMPAT
+#define strlen(s) _strlen(s)
+#define strncmp(s1,s2,m) _strncmp(s1,s2,m)
+#define memcmp(s,c,n) _memcmp(s,c,n)
+#define memcpy(d,s,n) _memcpy(d,s,n)
+#define memmove(d,s,n) _memmove(d,s,n)
+#define memset(s,c,n) _memset(s,c,n)
+#else /* VPCOMPAT */
+
+/* To cope with SunOS4 and other systems that lack memmove() but have bcopy(),
+define a macro for memmove() if HAVE_MEMMOVE is false, provided that HAVE_BCOPY
+is set. Otherwise, include an emulating function for those systems that have
+neither (there some non-Unix environments where this is the case). */
+
+#ifndef HAVE_MEMMOVE
+#undef memmove /* some systems may have a macro */
+#ifdef HAVE_BCOPY
+#define memmove(a, b, c) bcopy(b, a, c)
+#else /* HAVE_BCOPY */
+static void *
+pcre_memmove(void *d, const void *s, size_t n)
+{
+size_t i;
+unsigned char *dest = (unsigned char *)d;
+const unsigned char *src = (const unsigned char *)s;
+if (dest > src)
+ {
+ dest += n;
+ src += n;
+ for (i = 0; i < n; ++i) *(--dest) = *(--src);
+ return (void *)dest;
+ }
+else
+ {
+ for (i = 0; i < n; ++i) *dest++ = *src++;
+ return (void *)(dest - n);
+ }
+}
+#define memmove(a, b, c) pcre_memmove(a, b, c)
+#endif /* not HAVE_BCOPY */
+#endif /* not HAVE_MEMMOVE */
+#endif /* not VPCOMPAT */
+
+
+/* PCRE keeps offsets in its compiled code as 2-byte quantities (always stored
+in big-endian order) by default. These are used, for example, to link from the
+start of a subpattern to its alternatives and its end. The use of 2 bytes per
+offset limits the size of the compiled regex to around 64K, which is big enough
+for almost everybody. However, I received a request for an even bigger limit.
+For this reason, and also to make the code easier to maintain, the storing and
+loading of offsets from the byte string is now handled by the macros that are
+defined here.
+
+The macros are controlled by the value of LINK_SIZE. This defaults to 2 in
+the config.h file, but can be overridden by using -D on the command line. This
+is automated on Unix systems via the "configure" command. */
+
+#if defined COMPILE_PCRE8
+
+#if LINK_SIZE == 2
+
+#define PUT(a,n,d) \
+ (a[n] = (d) >> 8), \
+ (a[(n)+1] = (d) & 255)
+
+#define GET(a,n) \
+ (((a)[n] << 8) | (a)[(n)+1])
+
+#define MAX_PATTERN_SIZE (1 << 16)
+
+
+#elif LINK_SIZE == 3
+
+#define PUT(a,n,d) \
+ (a[n] = (d) >> 16), \
+ (a[(n)+1] = (d) >> 8), \
+ (a[(n)+2] = (d) & 255)
+
+#define GET(a,n) \
+ (((a)[n] << 16) | ((a)[(n)+1] << 8) | (a)[(n)+2])
+
+#define MAX_PATTERN_SIZE (1 << 24)
+
+
+#elif LINK_SIZE == 4
+
+#define PUT(a,n,d) \
+ (a[n] = (d) >> 24), \
+ (a[(n)+1] = (d) >> 16), \
+ (a[(n)+2] = (d) >> 8), \
+ (a[(n)+3] = (d) & 255)
+
+#define GET(a,n) \
+ (((a)[n] << 24) | ((a)[(n)+1] << 16) | ((a)[(n)+2] << 8) | (a)[(n)+3])
+
+/* Keep it positive */
+#define MAX_PATTERN_SIZE (1 << 30)
+
+#else
+#error LINK_SIZE must be either 2, 3, or 4
+#endif
+
+#elif defined COMPILE_PCRE16
+
+#if LINK_SIZE == 2
+
+/* Redefine LINK_SIZE as a multiple of sizeof(pcre_uchar) */
+#undef LINK_SIZE
+#define LINK_SIZE 1
+
+#define PUT(a,n,d) \
+ (a[n] = (d))
+
+#define GET(a,n) \
+ (a[n])
+
+#define MAX_PATTERN_SIZE (1 << 16)
+
+#elif LINK_SIZE == 3 || LINK_SIZE == 4
+
+/* Redefine LINK_SIZE as a multiple of sizeof(pcre_uchar) */
+#undef LINK_SIZE
+#define LINK_SIZE 2
+
+#define PUT(a,n,d) \
+ (a[n] = (d) >> 16), \
+ (a[(n)+1] = (d) & 65535)
+
+#define GET(a,n) \
+ (((a)[n] << 16) | (a)[(n)+1])
+
+/* Keep it positive */
+#define MAX_PATTERN_SIZE (1 << 30)
+
+#else
+#error LINK_SIZE must be either 2, 3, or 4
+#endif
+
+#elif defined COMPILE_PCRE32
+
+/* Only supported LINK_SIZE is 4 */
+/* Redefine LINK_SIZE as a multiple of sizeof(pcre_uchar) */
+#undef LINK_SIZE
+#define LINK_SIZE 1
+
+#define PUT(a,n,d) \
+ (a[n] = (d))
+
+#define GET(a,n) \
+ (a[n])
+
+/* Keep it positive */
+#define MAX_PATTERN_SIZE (1 << 30)
+
+#else
+#error Unsupported compiling mode
+#endif /* COMPILE_PCRE[8|16|32] */
+
+/* Convenience macro defined in terms of the others */
+
+#define PUTINC(a,n,d) PUT(a,n,d), a += LINK_SIZE
+
+
+/* PCRE uses some other 2-byte quantities that do not change when the size of
+offsets changes. There are used for repeat counts and for other things such as
+capturing parenthesis numbers in back references. */
+
+#if defined COMPILE_PCRE8
+
+#define IMM2_SIZE 2
+
+#define PUT2(a,n,d) \
+ a[n] = (d) >> 8; \
+ a[(n)+1] = (d) & 255
+
+/* For reasons that I do not understand, the expression in this GET2 macro is
+treated by gcc as a signed expression, even when a is declared as unsigned. It
+seems that any kind of arithmetic results in a signed value. */
+
+#define GET2(a,n) \
+ (unsigned int)(((a)[n] << 8) | (a)[(n)+1])
+
+#elif defined COMPILE_PCRE16
+
+#define IMM2_SIZE 1
+
+#define PUT2(a,n,d) \
+ a[n] = d
+
+#define GET2(a,n) \
+ a[n]
+
+#elif defined COMPILE_PCRE32
+
+#define IMM2_SIZE 1
+
+#define PUT2(a,n,d) \
+ a[n] = d
+
+#define GET2(a,n) \
+ a[n]
+
+#else
+#error Unsupported compiling mode
+#endif /* COMPILE_PCRE[8|16|32] */
+
+#define PUT2INC(a,n,d) PUT2(a,n,d), a += IMM2_SIZE
+
+/* The maximum length of a MARK name is currently one data unit; it may be
+changed in future to be a fixed number of bytes or to depend on LINK_SIZE. */
+
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#define MAX_MARK ((1u << 16) - 1)
+#else
+#define MAX_MARK ((1u << 8) - 1)
+#endif
+
+/* There is a proposed future special "UTF-21" mode, in which only the lowest
+21 bits of a 32-bit character are interpreted as UTF, with the remaining 11
+high-order bits available to the application for other uses. In preparation for
+the future implementation of this mode, there are macros that load a data item
+and, if in this special mode, mask it to 21 bits. These macros all have names
+starting with UCHAR21. In all other modes, including the normal 32-bit
+library, the macros all have the same simple definitions. When the new mode is
+implemented, it is expected that these definitions will be varied appropriately
+using #ifdef when compiling the library that supports the special mode. */
+
+#define UCHAR21(eptr) (*(eptr))
+#define UCHAR21TEST(eptr) (*(eptr))
+#define UCHAR21INC(eptr) (*(eptr)++)
+#define UCHAR21INCTEST(eptr) (*(eptr)++)
+
+/* When UTF encoding is being used, a character is no longer just a single
+byte in 8-bit mode or a single short in 16-bit mode. The macros for character
+handling generate simple sequences when used in the basic mode, and more
+complicated ones for UTF characters. GETCHARLENTEST and other macros are not
+used when UTF is not supported. To make sure they can never even appear when
+UTF support is omitted, we don't even define them. */
+
+#ifndef SUPPORT_UTF
+
+/* #define MAX_VALUE_FOR_SINGLE_CHAR */
+/* #define HAS_EXTRALEN(c) */
+/* #define GET_EXTRALEN(c) */
+/* #define NOT_FIRSTCHAR(c) */
+#define GETCHAR(c, eptr) c = *eptr;
+#define GETCHARTEST(c, eptr) c = *eptr;
+#define GETCHARINC(c, eptr) c = *eptr++;
+#define GETCHARINCTEST(c, eptr) c = *eptr++;
+#define GETCHARLEN(c, eptr, len) c = *eptr;
+/* #define GETCHARLENTEST(c, eptr, len) */
+/* #define BACKCHAR(eptr) */
+/* #define FORWARDCHAR(eptr) */
+/* #define ACROSSCHAR(condition, eptr, action) */
+
+#else /* SUPPORT_UTF */
+
+/* Tests whether the code point needs extra characters to decode. */
+
+#define HASUTF8EXTRALEN(c) ((c) >= 0xc0)
+
+/* Base macro to pick up the remaining bytes of a UTF-8 character, not
+advancing the pointer. */
+
+#define GETUTF8(c, eptr) \
+ { \
+ if ((c & 0x20) == 0) \
+ c = ((c & 0x1f) << 6) | (eptr[1] & 0x3f); \
+ else if ((c & 0x10) == 0) \
+ c = ((c & 0x0f) << 12) | ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \
+ else if ((c & 0x08) == 0) \
+ c = ((c & 0x07) << 18) | ((eptr[1] & 0x3f) << 12) | \
+ ((eptr[2] & 0x3f) << 6) | (eptr[3] & 0x3f); \
+ else if ((c & 0x04) == 0) \
+ c = ((c & 0x03) << 24) | ((eptr[1] & 0x3f) << 18) | \
+ ((eptr[2] & 0x3f) << 12) | ((eptr[3] & 0x3f) << 6) | \
+ (eptr[4] & 0x3f); \
+ else \
+ c = ((c & 0x01) << 30) | ((eptr[1] & 0x3f) << 24) | \
+ ((eptr[2] & 0x3f) << 18) | ((eptr[3] & 0x3f) << 12) | \
+ ((eptr[4] & 0x3f) << 6) | (eptr[5] & 0x3f); \
+ }
+
+/* Base macro to pick up the remaining bytes of a UTF-8 character, advancing
+the pointer. */
+
+#define GETUTF8INC(c, eptr) \
+ { \
+ if ((c & 0x20) == 0) \
+ c = ((c & 0x1f) << 6) | (*eptr++ & 0x3f); \
+ else if ((c & 0x10) == 0) \
+ { \
+ c = ((c & 0x0f) << 12) | ((*eptr & 0x3f) << 6) | (eptr[1] & 0x3f); \
+ eptr += 2; \
+ } \
+ else if ((c & 0x08) == 0) \
+ { \
+ c = ((c & 0x07) << 18) | ((*eptr & 0x3f) << 12) | \
+ ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \
+ eptr += 3; \
+ } \
+ else if ((c & 0x04) == 0) \
+ { \
+ c = ((c & 0x03) << 24) | ((*eptr & 0x3f) << 18) | \
+ ((eptr[1] & 0x3f) << 12) | ((eptr[2] & 0x3f) << 6) | \
+ (eptr[3] & 0x3f); \
+ eptr += 4; \
+ } \
+ else \
+ { \
+ c = ((c & 0x01) << 30) | ((*eptr & 0x3f) << 24) | \
+ ((eptr[1] & 0x3f) << 18) | ((eptr[2] & 0x3f) << 12) | \
+ ((eptr[3] & 0x3f) << 6) | (eptr[4] & 0x3f); \
+ eptr += 5; \
+ } \
+ }
+
+#if defined COMPILE_PCRE8
+
+/* These macros were originally written in the form of loops that used data
+from the tables whose names start with PRIV(utf8_table). They were rewritten by
+a user so as not to use loops, because in some environments this gives a
+significant performance advantage, and it seems never to do any harm. */
+
+/* Tells the biggest code point which can be encoded as a single character. */
+
+#define MAX_VALUE_FOR_SINGLE_CHAR 127
+
+/* Tests whether the code point needs extra characters to decode. */
+
+#define HAS_EXTRALEN(c) ((c) >= 0xc0)
+
+/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE.
+Otherwise it has an undefined behaviour. */
+
+#define GET_EXTRALEN(c) (PRIV(utf8_table4)[(c) & 0x3f])
+
+/* Returns TRUE, if the given character is not the first character
+of a UTF sequence. */
+
+#define NOT_FIRSTCHAR(c) (((c) & 0xc0) == 0x80)
+
+/* Get the next UTF-8 character, not advancing the pointer. This is called when
+we know we are in UTF-8 mode. */
+
+#define GETCHAR(c, eptr) \
+ c = *eptr; \
+ if (c >= 0xc0) GETUTF8(c, eptr);
+
+/* Get the next UTF-8 character, testing for UTF-8 mode, and not advancing the
+pointer. */
+
+#define GETCHARTEST(c, eptr) \
+ c = *eptr; \
+ if (utf && c >= 0xc0) GETUTF8(c, eptr);
+
+/* Get the next UTF-8 character, advancing the pointer. This is called when we
+know we are in UTF-8 mode. */
+
+#define GETCHARINC(c, eptr) \
+ c = *eptr++; \
+ if (c >= 0xc0) GETUTF8INC(c, eptr);
+
+/* Get the next character, testing for UTF-8 mode, and advancing the pointer.
+This is called when we don't know if we are in UTF-8 mode. */
+
+#define GETCHARINCTEST(c, eptr) \
+ c = *eptr++; \
+ if (utf && c >= 0xc0) GETUTF8INC(c, eptr);
+
+/* Base macro to pick up the remaining bytes of a UTF-8 character, not
+advancing the pointer, incrementing the length. */
+
+#define GETUTF8LEN(c, eptr, len) \
+ { \
+ if ((c & 0x20) == 0) \
+ { \
+ c = ((c & 0x1f) << 6) | (eptr[1] & 0x3f); \
+ len++; \
+ } \
+ else if ((c & 0x10) == 0) \
+ { \
+ c = ((c & 0x0f) << 12) | ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \
+ len += 2; \
+ } \
+ else if ((c & 0x08) == 0) \
+ {\
+ c = ((c & 0x07) << 18) | ((eptr[1] & 0x3f) << 12) | \
+ ((eptr[2] & 0x3f) << 6) | (eptr[3] & 0x3f); \
+ len += 3; \
+ } \
+ else if ((c & 0x04) == 0) \
+ { \
+ c = ((c & 0x03) << 24) | ((eptr[1] & 0x3f) << 18) | \
+ ((eptr[2] & 0x3f) << 12) | ((eptr[3] & 0x3f) << 6) | \
+ (eptr[4] & 0x3f); \
+ len += 4; \
+ } \
+ else \
+ {\
+ c = ((c & 0x01) << 30) | ((eptr[1] & 0x3f) << 24) | \
+ ((eptr[2] & 0x3f) << 18) | ((eptr[3] & 0x3f) << 12) | \
+ ((eptr[4] & 0x3f) << 6) | (eptr[5] & 0x3f); \
+ len += 5; \
+ } \
+ }
+
+/* Get the next UTF-8 character, not advancing the pointer, incrementing length
+if there are extra bytes. This is called when we know we are in UTF-8 mode. */
+
+#define GETCHARLEN(c, eptr, len) \
+ c = *eptr; \
+ if (c >= 0xc0) GETUTF8LEN(c, eptr, len);
+
+/* Get the next UTF-8 character, testing for UTF-8 mode, not advancing the
+pointer, incrementing length if there are extra bytes. This is called when we
+do not know if we are in UTF-8 mode. */
+
+#define GETCHARLENTEST(c, eptr, len) \
+ c = *eptr; \
+ if (utf && c >= 0xc0) GETUTF8LEN(c, eptr, len);
+
+/* If the pointer is not at the start of a character, move it back until
+it is. This is called only in UTF-8 mode - we don't put a test within the macro
+because almost all calls are already within a block of UTF-8 only code. */
+
+#define BACKCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr--
+
+/* Same as above, just in the other direction. */
+#define FORWARDCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr++
+
+/* Same as above, but it allows a fully customizable form. */
+#define ACROSSCHAR(condition, eptr, action) \
+ while((condition) && ((eptr) & 0xc0) == 0x80) action
+
+#elif defined COMPILE_PCRE16
+
+/* Tells the biggest code point which can be encoded as a single character. */
+
+#define MAX_VALUE_FOR_SINGLE_CHAR 65535
+
+/* Tests whether the code point needs extra characters to decode. */
+
+#define HAS_EXTRALEN(c) (((c) & 0xfc00) == 0xd800)
+
+/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE.
+Otherwise it has an undefined behaviour. */
+
+#define GET_EXTRALEN(c) 1
+
+/* Returns TRUE, if the given character is not the first character
+of a UTF sequence. */
+
+#define NOT_FIRSTCHAR(c) (((c) & 0xfc00) == 0xdc00)
+
+/* Base macro to pick up the low surrogate of a UTF-16 character, not
+advancing the pointer. */
+
+#define GETUTF16(c, eptr) \
+ { c = (((c & 0x3ff) << 10) | (eptr[1] & 0x3ff)) + 0x10000; }
+
+/* Get the next UTF-16 character, not advancing the pointer. This is called when
+we know we are in UTF-16 mode. */
+
+#define GETCHAR(c, eptr) \
+ c = *eptr; \
+ if ((c & 0xfc00) == 0xd800) GETUTF16(c, eptr);
+
+/* Get the next UTF-16 character, testing for UTF-16 mode, and not advancing the
+pointer. */
+
+#define GETCHARTEST(c, eptr) \
+ c = *eptr; \
+ if (utf && (c & 0xfc00) == 0xd800) GETUTF16(c, eptr);
+
+/* Base macro to pick up the low surrogate of a UTF-16 character, advancing
+the pointer. */
+
+#define GETUTF16INC(c, eptr) \
+ { c = (((c & 0x3ff) << 10) | (*eptr++ & 0x3ff)) + 0x10000; }
+
+/* Get the next UTF-16 character, advancing the pointer. This is called when we
+know we are in UTF-16 mode. */
+
+#define GETCHARINC(c, eptr) \
+ c = *eptr++; \
+ if ((c & 0xfc00) == 0xd800) GETUTF16INC(c, eptr);
+
+/* Get the next character, testing for UTF-16 mode, and advancing the pointer.
+This is called when we don't know if we are in UTF-16 mode. */
+
+#define GETCHARINCTEST(c, eptr) \
+ c = *eptr++; \
+ if (utf && (c & 0xfc00) == 0xd800) GETUTF16INC(c, eptr);
+
+/* Base macro to pick up the low surrogate of a UTF-16 character, not
+advancing the pointer, incrementing the length. */
+
+#define GETUTF16LEN(c, eptr, len) \
+ { c = (((c & 0x3ff) << 10) | (eptr[1] & 0x3ff)) + 0x10000; len++; }
+
+/* Get the next UTF-16 character, not advancing the pointer, incrementing
+length if there is a low surrogate. This is called when we know we are in
+UTF-16 mode. */
+
+#define GETCHARLEN(c, eptr, len) \
+ c = *eptr; \
+ if ((c & 0xfc00) == 0xd800) GETUTF16LEN(c, eptr, len);
+
+/* Get the next UTF-816character, testing for UTF-16 mode, not advancing the
+pointer, incrementing length if there is a low surrogate. This is called when
+we do not know if we are in UTF-16 mode. */
+
+#define GETCHARLENTEST(c, eptr, len) \
+ c = *eptr; \
+ if (utf && (c & 0xfc00) == 0xd800) GETUTF16LEN(c, eptr, len);
+
+/* If the pointer is not at the start of a character, move it back until
+it is. This is called only in UTF-16 mode - we don't put a test within the
+macro because almost all calls are already within a block of UTF-16 only
+code. */
+
+#define BACKCHAR(eptr) if ((*eptr & 0xfc00) == 0xdc00) eptr--
+
+/* Same as above, just in the other direction. */
+#define FORWARDCHAR(eptr) if ((*eptr & 0xfc00) == 0xdc00) eptr++
+
+/* Same as above, but it allows a fully customizable form. */
+#define ACROSSCHAR(condition, eptr, action) \
+ if ((condition) && ((eptr) & 0xfc00) == 0xdc00) action
+
+#elif defined COMPILE_PCRE32
+
+/* These are trivial for the 32-bit library, since all UTF-32 characters fit
+into one pcre_uchar unit. */
+#define MAX_VALUE_FOR_SINGLE_CHAR (0x10ffffu)
+#define HAS_EXTRALEN(c) (0)
+#define GET_EXTRALEN(c) (0)
+#define NOT_FIRSTCHAR(c) (0)
+
+/* Get the next UTF-32 character, not advancing the pointer. This is called when
+we know we are in UTF-32 mode. */
+
+#define GETCHAR(c, eptr) \
+ c = *(eptr);
+
+/* Get the next UTF-32 character, testing for UTF-32 mode, and not advancing the
+pointer. */
+
+#define GETCHARTEST(c, eptr) \
+ c = *(eptr);
+
+/* Get the next UTF-32 character, advancing the pointer. This is called when we
+know we are in UTF-32 mode. */
+
+#define GETCHARINC(c, eptr) \
+ c = *((eptr)++);
+
+/* Get the next character, testing for UTF-32 mode, and advancing the pointer.
+This is called when we don't know if we are in UTF-32 mode. */
+
+#define GETCHARINCTEST(c, eptr) \
+ c = *((eptr)++);
+
+/* Get the next UTF-32 character, not advancing the pointer, not incrementing
+length (since all UTF-32 is of length 1). This is called when we know we are in
+UTF-32 mode. */
+
+#define GETCHARLEN(c, eptr, len) \
+ GETCHAR(c, eptr)
+
+/* Get the next UTF-32character, testing for UTF-32 mode, not advancing the
+pointer, not incrementing the length (since all UTF-32 is of length 1).
+This is called when we do not know if we are in UTF-32 mode. */
+
+#define GETCHARLENTEST(c, eptr, len) \
+ GETCHARTEST(c, eptr)
+
+/* If the pointer is not at the start of a character, move it back until
+it is. This is called only in UTF-32 mode - we don't put a test within the
+macro because almost all calls are already within a block of UTF-32 only
+code.
+These are all no-ops since all UTF-32 characters fit into one pcre_uchar. */
+
+#define BACKCHAR(eptr) do { } while (0)
+
+/* Same as above, just in the other direction. */
+#define FORWARDCHAR(eptr) do { } while (0)
+
+/* Same as above, but it allows a fully customizable form. */
+#define ACROSSCHAR(condition, eptr, action) do { } while (0)
+
+#else
+#error Unsupported compiling mode
+#endif /* COMPILE_PCRE[8|16|32] */
+
+#endif /* SUPPORT_UTF */
+
+/* Tests for Unicode horizontal and vertical whitespace characters must check a
+number of different values. Using a switch statement for this generates the
+fastest code (no loop, no memory access), and there are several places in the
+interpreter code where this happens. In order to ensure that all the case lists
+remain in step, we use macros so that there is only one place where the lists
+are defined.
+
+These values are also required as lists in pcre_compile.c when processing \h,
+\H, \v and \V in a character class. The lists are defined in pcre_tables.c, but
+macros that define the values are here so that all the definitions are
+together. The lists must be in ascending character order, terminated by
+NOTACHAR (which is 0xffffffff).
+
+Any changes should ensure that the various macros are kept in step with each
+other. NOTE: The values also appear in pcre_jit_compile.c. */
+
+/* ------ ASCII/Unicode environments ------ */
+
+#ifndef EBCDIC
+
+#define HSPACE_LIST \
+ CHAR_HT, CHAR_SPACE, 0xa0, \
+ 0x1680, 0x180e, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, \
+ 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202f, 0x205f, 0x3000, \
+ NOTACHAR
+
+#define HSPACE_MULTIBYTE_CASES \
+ case 0x1680: /* OGHAM SPACE MARK */ \
+ case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ \
+ case 0x2000: /* EN QUAD */ \
+ case 0x2001: /* EM QUAD */ \
+ case 0x2002: /* EN SPACE */ \
+ case 0x2003: /* EM SPACE */ \
+ case 0x2004: /* THREE-PER-EM SPACE */ \
+ case 0x2005: /* FOUR-PER-EM SPACE */ \
+ case 0x2006: /* SIX-PER-EM SPACE */ \
+ case 0x2007: /* FIGURE SPACE */ \
+ case 0x2008: /* PUNCTUATION SPACE */ \
+ case 0x2009: /* THIN SPACE */ \
+ case 0x200A: /* HAIR SPACE */ \
+ case 0x202f: /* NARROW NO-BREAK SPACE */ \
+ case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ \
+ case 0x3000 /* IDEOGRAPHIC SPACE */
+
+#define HSPACE_BYTE_CASES \
+ case CHAR_HT: \
+ case CHAR_SPACE: \
+ case 0xa0 /* NBSP */
+
+#define HSPACE_CASES \
+ HSPACE_BYTE_CASES: \
+ HSPACE_MULTIBYTE_CASES
+
+#define VSPACE_LIST \
+ CHAR_LF, CHAR_VT, CHAR_FF, CHAR_CR, CHAR_NEL, 0x2028, 0x2029, NOTACHAR
+
+#define VSPACE_MULTIBYTE_CASES \
+ case 0x2028: /* LINE SEPARATOR */ \
+ case 0x2029 /* PARAGRAPH SEPARATOR */
+
+#define VSPACE_BYTE_CASES \
+ case CHAR_LF: \
+ case CHAR_VT: \
+ case CHAR_FF: \
+ case CHAR_CR: \
+ case CHAR_NEL
+
+#define VSPACE_CASES \
+ VSPACE_BYTE_CASES: \
+ VSPACE_MULTIBYTE_CASES
+
+/* ------ EBCDIC environments ------ */
+
+#else
+#define HSPACE_LIST CHAR_HT, CHAR_SPACE
+
+#define HSPACE_BYTE_CASES \
+ case CHAR_HT: \
+ case CHAR_SPACE
+
+#define HSPACE_CASES HSPACE_BYTE_CASES
+
+#ifdef EBCDIC_NL25
+#define VSPACE_LIST \
+ CHAR_VT, CHAR_FF, CHAR_CR, CHAR_NEL, CHAR_LF, NOTACHAR
+#else
+#define VSPACE_LIST \
+ CHAR_VT, CHAR_FF, CHAR_CR, CHAR_LF, CHAR_NEL, NOTACHAR
+#endif
+
+#define VSPACE_BYTE_CASES \
+ case CHAR_LF: \
+ case CHAR_VT: \
+ case CHAR_FF: \
+ case CHAR_CR: \
+ case CHAR_NEL
+
+#define VSPACE_CASES VSPACE_BYTE_CASES
+#endif /* EBCDIC */
+
+/* ------ End of whitespace macros ------ */
+
+
+
+/* Private flags containing information about the compiled regex. They used to
+live at the top end of the options word, but that got almost full, so they were
+moved to a 16-bit flags word - which got almost full, so now they are in a
+32-bit flags word. From release 8.00, PCRE_NOPARTIAL is unused, as the
+restrictions on partial matching have been lifted. It remains for backwards
+compatibility. */
+
+#define PCRE_MODE8 0x00000001 /* compiled in 8 bit mode */
+#define PCRE_MODE16 0x00000002 /* compiled in 16 bit mode */
+#define PCRE_MODE32 0x00000004 /* compiled in 32 bit mode */
+#define PCRE_FIRSTSET 0x00000010 /* first_char is set */
+#define PCRE_FCH_CASELESS 0x00000020 /* caseless first char */
+#define PCRE_REQCHSET 0x00000040 /* req_byte is set */
+#define PCRE_RCH_CASELESS 0x00000080 /* caseless requested char */
+#define PCRE_STARTLINE 0x00000100 /* start after \n for multiline */
+#define PCRE_NOPARTIAL 0x00000200 /* can't use partial with this regex */
+#define PCRE_JCHANGED 0x00000400 /* j option used in regex */
+#define PCRE_HASCRORLF 0x00000800 /* explicit \r or \n in pattern */
+#define PCRE_HASTHEN 0x00001000 /* pattern contains (*THEN) */
+#define PCRE_MLSET 0x00002000 /* match limit set by regex */
+#define PCRE_RLSET 0x00004000 /* recursion limit set by regex */
+#define PCRE_MATCH_EMPTY 0x00008000 /* pattern can match empty string */
+
+#if defined COMPILE_PCRE8
+#define PCRE_MODE PCRE_MODE8
+#elif defined COMPILE_PCRE16
+#define PCRE_MODE PCRE_MODE16
+#elif defined COMPILE_PCRE32
+#define PCRE_MODE PCRE_MODE32
+#endif
+#define PCRE_MODE_MASK (PCRE_MODE8 | PCRE_MODE16 | PCRE_MODE32)
+
+/* Flags for the "extra" block produced by pcre_study(). */
+
+#define PCRE_STUDY_MAPPED 0x0001 /* a map of starting chars exists */
+#define PCRE_STUDY_MINLEN 0x0002 /* a minimum length field exists */
+
+/* Masks for identifying the public options that are permitted at compile
+time, run time, or study time, respectively. */
+
+#define PCRE_NEWLINE_BITS (PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|PCRE_NEWLINE_ANY| \
+ PCRE_NEWLINE_ANYCRLF)
+
+#define PUBLIC_COMPILE_OPTIONS \
+ (PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \
+ PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8| \
+ PCRE_NO_AUTO_CAPTURE|PCRE_NO_AUTO_POSSESS| \
+ PCRE_NO_UTF8_CHECK|PCRE_AUTO_CALLOUT|PCRE_FIRSTLINE| \
+ PCRE_DUPNAMES|PCRE_NEWLINE_BITS|PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE| \
+ PCRE_JAVASCRIPT_COMPAT|PCRE_UCP|PCRE_NO_START_OPTIMIZE|PCRE_NEVER_UTF)
+
+#define PUBLIC_EXEC_OPTIONS \
+ (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NOTEMPTY_ATSTART| \
+ PCRE_NO_UTF8_CHECK|PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT|PCRE_NEWLINE_BITS| \
+ PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE|PCRE_NO_START_OPTIMIZE)
+
+#define PUBLIC_DFA_EXEC_OPTIONS \
+ (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NOTEMPTY_ATSTART| \
+ PCRE_NO_UTF8_CHECK|PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT|PCRE_DFA_SHORTEST| \
+ PCRE_DFA_RESTART|PCRE_NEWLINE_BITS|PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE| \
+ PCRE_NO_START_OPTIMIZE)
+
+#define PUBLIC_STUDY_OPTIONS \
+ (PCRE_STUDY_JIT_COMPILE|PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE| \
+ PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE|PCRE_STUDY_EXTRA_NEEDED)
+
+#define PUBLIC_JIT_EXEC_OPTIONS \
+ (PCRE_NO_UTF8_CHECK|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|\
+ PCRE_NOTEMPTY_ATSTART|PCRE_PARTIAL_SOFT|PCRE_PARTIAL_HARD)
+
+/* Magic number to provide a small check against being handed junk. */
+
+#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */
+
+/* This variable is used to detect a loaded regular expression
+in different endianness. */
+
+#define REVERSED_MAGIC_NUMBER 0x45524350UL /* 'ERCP' */
+
+/* The maximum remaining length of subject we are prepared to search for a
+req_byte match. */
+
+#define REQ_BYTE_MAX 1000
+
+/* Miscellaneous definitions. The #ifndef is to pacify compiler warnings in
+environments where these macros are defined elsewhere. Unfortunately, there
+is no way to do the same for the typedef. */
+
+typedef int BOOL;
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+/* If PCRE is to support UTF-8 on EBCDIC platforms, we cannot use normal
+character constants like '*' because the compiler would emit their EBCDIC code,
+which is different from their ASCII/UTF-8 code. Instead we define macros for
+the characters so that they always use the ASCII/UTF-8 code when UTF-8 support
+is enabled. When UTF-8 support is not enabled, the definitions use character
+literals. Both character and string versions of each character are needed, and
+there are some longer strings as well.
+
+This means that, on EBCDIC platforms, the PCRE library can handle either
+EBCDIC, or UTF-8, but not both. To support both in the same compiled library
+would need different lookups depending on whether PCRE_UTF8 was set or not.
+This would make it impossible to use characters in switch/case statements,
+which would reduce performance. For a theoretical use (which nobody has asked
+for) in a minority area (EBCDIC platforms), this is not sensible. Any
+application that did need both could compile two versions of the library, using
+macros to give the functions distinct names. */
+
+#ifndef SUPPORT_UTF
+
+/* UTF-8 support is not enabled; use the platform-dependent character literals
+so that PCRE works in both ASCII and EBCDIC environments, but only in non-UTF
+mode. Newline characters are problematic in EBCDIC. Though it has CR and LF
+characters, a common practice has been to use its NL (0x15) character as the
+line terminator in C-like processing environments. However, sometimes the LF
+(0x25) character is used instead, according to this Unicode document:
+
+http://unicode.org/standard/reports/tr13/tr13-5.html
+
+PCRE defaults EBCDIC NL to 0x15, but has a build-time option to select 0x25
+instead. Whichever is *not* chosen is defined as NEL.
+
+In both ASCII and EBCDIC environments, CHAR_NL and CHAR_LF are synonyms for the
+same code point. */
+
+#ifdef EBCDIC
+
+#ifndef EBCDIC_NL25
+#define CHAR_NL '\x15'
+#define CHAR_NEL '\x25'
+#define STR_NL "\x15"
+#define STR_NEL "\x25"
+#else
+#define CHAR_NL '\x25'
+#define CHAR_NEL '\x15'
+#define STR_NL "\x25"
+#define STR_NEL "\x15"
+#endif
+
+#define CHAR_LF CHAR_NL
+#define STR_LF STR_NL
+
+#define CHAR_ESC '\047'
+#define CHAR_DEL '\007'
+#define STR_ESC "\047"
+#define STR_DEL "\007"
+
+#else /* Not EBCDIC */
+
+/* In ASCII/Unicode, linefeed is '\n' and we equate this to NL for
+compatibility. NEL is the Unicode newline character; make sure it is
+a positive value. */
+
+#define CHAR_LF '\n'
+#define CHAR_NL CHAR_LF
+#define CHAR_NEL ((unsigned char)'\x85')
+#define CHAR_ESC '\033'
+#define CHAR_DEL '\177'
+
+#define STR_LF "\n"
+#define STR_NL STR_LF
+#define STR_NEL "\x85"
+#define STR_ESC "\033"
+#define STR_DEL "\177"
+
+#endif /* EBCDIC */
+
+/* The remaining definitions work in both environments. */
+
+#define CHAR_NULL '\0'
+#define CHAR_HT '\t'
+#define CHAR_VT '\v'
+#define CHAR_FF '\f'
+#define CHAR_CR '\r'
+#define CHAR_BS '\b'
+#define CHAR_BEL '\a'
+
+#define CHAR_SPACE ' '
+#define CHAR_EXCLAMATION_MARK '!'
+#define CHAR_QUOTATION_MARK '"'
+#define CHAR_NUMBER_SIGN '#'
+#define CHAR_DOLLAR_SIGN '$'
+#define CHAR_PERCENT_SIGN '%'
+#define CHAR_AMPERSAND '&'
+#define CHAR_APOSTROPHE '\''
+#define CHAR_LEFT_PARENTHESIS '('
+#define CHAR_RIGHT_PARENTHESIS ')'
+#define CHAR_ASTERISK '*'
+#define CHAR_PLUS '+'
+#define CHAR_COMMA ','
+#define CHAR_MINUS '-'
+#define CHAR_DOT '.'
+#define CHAR_SLASH '/'
+#define CHAR_0 '0'
+#define CHAR_1 '1'
+#define CHAR_2 '2'
+#define CHAR_3 '3'
+#define CHAR_4 '4'
+#define CHAR_5 '5'
+#define CHAR_6 '6'
+#define CHAR_7 '7'
+#define CHAR_8 '8'
+#define CHAR_9 '9'
+#define CHAR_COLON ':'
+#define CHAR_SEMICOLON ';'
+#define CHAR_LESS_THAN_SIGN '<'
+#define CHAR_EQUALS_SIGN '='
+#define CHAR_GREATER_THAN_SIGN '>'
+#define CHAR_QUESTION_MARK '?'
+#define CHAR_COMMERCIAL_AT '@'
+#define CHAR_A 'A'
+#define CHAR_B 'B'
+#define CHAR_C 'C'
+#define CHAR_D 'D'
+#define CHAR_E 'E'
+#define CHAR_F 'F'
+#define CHAR_G 'G'
+#define CHAR_H 'H'
+#define CHAR_I 'I'
+#define CHAR_J 'J'
+#define CHAR_K 'K'
+#define CHAR_L 'L'
+#define CHAR_M 'M'
+#define CHAR_N 'N'
+#define CHAR_O 'O'
+#define CHAR_P 'P'
+#define CHAR_Q 'Q'
+#define CHAR_R 'R'
+#define CHAR_S 'S'
+#define CHAR_T 'T'
+#define CHAR_U 'U'
+#define CHAR_V 'V'
+#define CHAR_W 'W'
+#define CHAR_X 'X'
+#define CHAR_Y 'Y'
+#define CHAR_Z 'Z'
+#define CHAR_LEFT_SQUARE_BRACKET '['
+#define CHAR_BACKSLASH '\\'
+#define CHAR_RIGHT_SQUARE_BRACKET ']'
+#define CHAR_CIRCUMFLEX_ACCENT '^'
+#define CHAR_UNDERSCORE '_'
+#define CHAR_GRAVE_ACCENT '`'
+#define CHAR_a 'a'
+#define CHAR_b 'b'
+#define CHAR_c 'c'
+#define CHAR_d 'd'
+#define CHAR_e 'e'
+#define CHAR_f 'f'
+#define CHAR_g 'g'
+#define CHAR_h 'h'
+#define CHAR_i 'i'
+#define CHAR_j 'j'
+#define CHAR_k 'k'
+#define CHAR_l 'l'
+#define CHAR_m 'm'
+#define CHAR_n 'n'
+#define CHAR_o 'o'
+#define CHAR_p 'p'
+#define CHAR_q 'q'
+#define CHAR_r 'r'
+#define CHAR_s 's'
+#define CHAR_t 't'
+#define CHAR_u 'u'
+#define CHAR_v 'v'
+#define CHAR_w 'w'
+#define CHAR_x 'x'
+#define CHAR_y 'y'
+#define CHAR_z 'z'
+#define CHAR_LEFT_CURLY_BRACKET '{'
+#define CHAR_VERTICAL_LINE '|'
+#define CHAR_RIGHT_CURLY_BRACKET '}'
+#define CHAR_TILDE '~'
+
+#define STR_HT "\t"
+#define STR_VT "\v"
+#define STR_FF "\f"
+#define STR_CR "\r"
+#define STR_BS "\b"
+#define STR_BEL "\a"
+
+#define STR_SPACE " "
+#define STR_EXCLAMATION_MARK "!"
+#define STR_QUOTATION_MARK "\""
+#define STR_NUMBER_SIGN "#"
+#define STR_DOLLAR_SIGN "$"
+#define STR_PERCENT_SIGN "%"
+#define STR_AMPERSAND "&"
+#define STR_APOSTROPHE "'"
+#define STR_LEFT_PARENTHESIS "("
+#define STR_RIGHT_PARENTHESIS ")"
+#define STR_ASTERISK "*"
+#define STR_PLUS "+"
+#define STR_COMMA ","
+#define STR_MINUS "-"
+#define STR_DOT "."
+#define STR_SLASH "/"
+#define STR_0 "0"
+#define STR_1 "1"
+#define STR_2 "2"
+#define STR_3 "3"
+#define STR_4 "4"
+#define STR_5 "5"
+#define STR_6 "6"
+#define STR_7 "7"
+#define STR_8 "8"
+#define STR_9 "9"
+#define STR_COLON ":"
+#define STR_SEMICOLON ";"
+#define STR_LESS_THAN_SIGN "<"
+#define STR_EQUALS_SIGN "="
+#define STR_GREATER_THAN_SIGN ">"
+#define STR_QUESTION_MARK "?"
+#define STR_COMMERCIAL_AT "@"
+#define STR_A "A"
+#define STR_B "B"
+#define STR_C "C"
+#define STR_D "D"
+#define STR_E "E"
+#define STR_F "F"
+#define STR_G "G"
+#define STR_H "H"
+#define STR_I "I"
+#define STR_J "J"
+#define STR_K "K"
+#define STR_L "L"
+#define STR_M "M"
+#define STR_N "N"
+#define STR_O "O"
+#define STR_P "P"
+#define STR_Q "Q"
+#define STR_R "R"
+#define STR_S "S"
+#define STR_T "T"
+#define STR_U "U"
+#define STR_V "V"
+#define STR_W "W"
+#define STR_X "X"
+#define STR_Y "Y"
+#define STR_Z "Z"
+#define STR_LEFT_SQUARE_BRACKET "["
+#define STR_BACKSLASH "\\"
+#define STR_RIGHT_SQUARE_BRACKET "]"
+#define STR_CIRCUMFLEX_ACCENT "^"
+#define STR_UNDERSCORE "_"
+#define STR_GRAVE_ACCENT "`"
+#define STR_a "a"
+#define STR_b "b"
+#define STR_c "c"
+#define STR_d "d"
+#define STR_e "e"
+#define STR_f "f"
+#define STR_g "g"
+#define STR_h "h"
+#define STR_i "i"
+#define STR_j "j"
+#define STR_k "k"
+#define STR_l "l"
+#define STR_m "m"
+#define STR_n "n"
+#define STR_o "o"
+#define STR_p "p"
+#define STR_q "q"
+#define STR_r "r"
+#define STR_s "s"
+#define STR_t "t"
+#define STR_u "u"
+#define STR_v "v"
+#define STR_w "w"
+#define STR_x "x"
+#define STR_y "y"
+#define STR_z "z"
+#define STR_LEFT_CURLY_BRACKET "{"
+#define STR_VERTICAL_LINE "|"
+#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_WEIRD_STARTWORD "[:<:]]"
+#define STRING_WEIRD_ENDWORD "[:>:]]"
+
+#define STRING_CR_RIGHTPAR "CR)"
+#define STRING_LF_RIGHTPAR "LF)"
+#define STRING_CRLF_RIGHTPAR "CRLF)"
+#define STRING_ANY_RIGHTPAR "ANY)"
+#define STRING_ANYCRLF_RIGHTPAR "ANYCRLF)"
+#define STRING_BSR_ANYCRLF_RIGHTPAR "BSR_ANYCRLF)"
+#define STRING_BSR_UNICODE_RIGHTPAR "BSR_UNICODE)"
+#define STRING_UTF8_RIGHTPAR "UTF8)"
+#define STRING_UTF16_RIGHTPAR "UTF16)"
+#define STRING_UTF32_RIGHTPAR "UTF32)"
+#define STRING_UTF_RIGHTPAR "UTF)"
+#define STRING_UCP_RIGHTPAR "UCP)"
+#define STRING_NO_AUTO_POSSESS_RIGHTPAR "NO_AUTO_POSSESS)"
+#define STRING_NO_START_OPT_RIGHTPAR "NO_START_OPT)"
+#define STRING_LIMIT_MATCH_EQ "LIMIT_MATCH="
+#define STRING_LIMIT_RECURSION_EQ "LIMIT_RECURSION="
+
+#else /* SUPPORT_UTF */
+
+/* UTF-8 support is enabled; always use UTF-8 (=ASCII) character codes. This
+works in both modes non-EBCDIC platforms, and on EBCDIC platforms in UTF-8 mode
+only. */
+
+#define CHAR_HT '\011'
+#define CHAR_VT '\013'
+#define CHAR_FF '\014'
+#define CHAR_CR '\015'
+#define CHAR_LF '\012'
+#define CHAR_NL CHAR_LF
+#define CHAR_NEL ((unsigned char)'\x85')
+#define CHAR_BS '\010'
+#define CHAR_BEL '\007'
+#define CHAR_ESC '\033'
+#define CHAR_DEL '\177'
+
+#define CHAR_NULL '\0'
+#define CHAR_SPACE '\040'
+#define CHAR_EXCLAMATION_MARK '\041'
+#define CHAR_QUOTATION_MARK '\042'
+#define CHAR_NUMBER_SIGN '\043'
+#define CHAR_DOLLAR_SIGN '\044'
+#define CHAR_PERCENT_SIGN '\045'
+#define CHAR_AMPERSAND '\046'
+#define CHAR_APOSTROPHE '\047'
+#define CHAR_LEFT_PARENTHESIS '\050'
+#define CHAR_RIGHT_PARENTHESIS '\051'
+#define CHAR_ASTERISK '\052'
+#define CHAR_PLUS '\053'
+#define CHAR_COMMA '\054'
+#define CHAR_MINUS '\055'
+#define CHAR_DOT '\056'
+#define CHAR_SLASH '\057'
+#define CHAR_0 '\060'
+#define CHAR_1 '\061'
+#define CHAR_2 '\062'
+#define CHAR_3 '\063'
+#define CHAR_4 '\064'
+#define CHAR_5 '\065'
+#define CHAR_6 '\066'
+#define CHAR_7 '\067'
+#define CHAR_8 '\070'
+#define CHAR_9 '\071'
+#define CHAR_COLON '\072'
+#define CHAR_SEMICOLON '\073'
+#define CHAR_LESS_THAN_SIGN '\074'
+#define CHAR_EQUALS_SIGN '\075'
+#define CHAR_GREATER_THAN_SIGN '\076'
+#define CHAR_QUESTION_MARK '\077'
+#define CHAR_COMMERCIAL_AT '\100'
+#define CHAR_A '\101'
+#define CHAR_B '\102'
+#define CHAR_C '\103'
+#define CHAR_D '\104'
+#define CHAR_E '\105'
+#define CHAR_F '\106'
+#define CHAR_G '\107'
+#define CHAR_H '\110'
+#define CHAR_I '\111'
+#define CHAR_J '\112'
+#define CHAR_K '\113'
+#define CHAR_L '\114'
+#define CHAR_M '\115'
+#define CHAR_N '\116'
+#define CHAR_O '\117'
+#define CHAR_P '\120'
+#define CHAR_Q '\121'
+#define CHAR_R '\122'
+#define CHAR_S '\123'
+#define CHAR_T '\124'
+#define CHAR_U '\125'
+#define CHAR_V '\126'
+#define CHAR_W '\127'
+#define CHAR_X '\130'
+#define CHAR_Y '\131'
+#define CHAR_Z '\132'
+#define CHAR_LEFT_SQUARE_BRACKET '\133'
+#define CHAR_BACKSLASH '\134'
+#define CHAR_RIGHT_SQUARE_BRACKET '\135'
+#define CHAR_CIRCUMFLEX_ACCENT '\136'
+#define CHAR_UNDERSCORE '\137'
+#define CHAR_GRAVE_ACCENT '\140'
+#define CHAR_a '\141'
+#define CHAR_b '\142'
+#define CHAR_c '\143'
+#define CHAR_d '\144'
+#define CHAR_e '\145'
+#define CHAR_f '\146'
+#define CHAR_g '\147'
+#define CHAR_h '\150'
+#define CHAR_i '\151'
+#define CHAR_j '\152'
+#define CHAR_k '\153'
+#define CHAR_l '\154'
+#define CHAR_m '\155'
+#define CHAR_n '\156'
+#define CHAR_o '\157'
+#define CHAR_p '\160'
+#define CHAR_q '\161'
+#define CHAR_r '\162'
+#define CHAR_s '\163'
+#define CHAR_t '\164'
+#define CHAR_u '\165'
+#define CHAR_v '\166'
+#define CHAR_w '\167'
+#define CHAR_x '\170'
+#define CHAR_y '\171'
+#define CHAR_z '\172'
+#define CHAR_LEFT_CURLY_BRACKET '\173'
+#define CHAR_VERTICAL_LINE '\174'
+#define CHAR_RIGHT_CURLY_BRACKET '\175'
+#define CHAR_TILDE '\176'
+
+#define STR_HT "\011"
+#define STR_VT "\013"
+#define STR_FF "\014"
+#define STR_CR "\015"
+#define STR_NL "\012"
+#define STR_BS "\010"
+#define STR_BEL "\007"
+#define STR_ESC "\033"
+#define STR_DEL "\177"
+
+#define STR_SPACE "\040"
+#define STR_EXCLAMATION_MARK "\041"
+#define STR_QUOTATION_MARK "\042"
+#define STR_NUMBER_SIGN "\043"
+#define STR_DOLLAR_SIGN "\044"
+#define STR_PERCENT_SIGN "\045"
+#define STR_AMPERSAND "\046"
+#define STR_APOSTROPHE "\047"
+#define STR_LEFT_PARENTHESIS "\050"
+#define STR_RIGHT_PARENTHESIS "\051"
+#define STR_ASTERISK "\052"
+#define STR_PLUS "\053"
+#define STR_COMMA "\054"
+#define STR_MINUS "\055"
+#define STR_DOT "\056"
+#define STR_SLASH "\057"
+#define STR_0 "\060"
+#define STR_1 "\061"
+#define STR_2 "\062"
+#define STR_3 "\063"
+#define STR_4 "\064"
+#define STR_5 "\065"
+#define STR_6 "\066"
+#define STR_7 "\067"
+#define STR_8 "\070"
+#define STR_9 "\071"
+#define STR_COLON "\072"
+#define STR_SEMICOLON "\073"
+#define STR_LESS_THAN_SIGN "\074"
+#define STR_EQUALS_SIGN "\075"
+#define STR_GREATER_THAN_SIGN "\076"
+#define STR_QUESTION_MARK "\077"
+#define STR_COMMERCIAL_AT "\100"
+#define STR_A "\101"
+#define STR_B "\102"
+#define STR_C "\103"
+#define STR_D "\104"
+#define STR_E "\105"
+#define STR_F "\106"
+#define STR_G "\107"
+#define STR_H "\110"
+#define STR_I "\111"
+#define STR_J "\112"
+#define STR_K "\113"
+#define STR_L "\114"
+#define STR_M "\115"
+#define STR_N "\116"
+#define STR_O "\117"
+#define STR_P "\120"
+#define STR_Q "\121"
+#define STR_R "\122"
+#define STR_S "\123"
+#define STR_T "\124"
+#define STR_U "\125"
+#define STR_V "\126"
+#define STR_W "\127"
+#define STR_X "\130"
+#define STR_Y "\131"
+#define STR_Z "\132"
+#define STR_LEFT_SQUARE_BRACKET "\133"
+#define STR_BACKSLASH "\134"
+#define STR_RIGHT_SQUARE_BRACKET "\135"
+#define STR_CIRCUMFLEX_ACCENT "\136"
+#define STR_UNDERSCORE "\137"
+#define STR_GRAVE_ACCENT "\140"
+#define STR_a "\141"
+#define STR_b "\142"
+#define STR_c "\143"
+#define STR_d "\144"
+#define STR_e "\145"
+#define STR_f "\146"
+#define STR_g "\147"
+#define STR_h "\150"
+#define STR_i "\151"
+#define STR_j "\152"
+#define STR_k "\153"
+#define STR_l "\154"
+#define STR_m "\155"
+#define STR_n "\156"
+#define STR_o "\157"
+#define STR_p "\160"
+#define STR_q "\161"
+#define STR_r "\162"
+#define STR_s "\163"
+#define STR_t "\164"
+#define STR_u "\165"
+#define STR_v "\166"
+#define STR_w "\167"
+#define STR_x "\170"
+#define STR_y "\171"
+#define STR_z "\172"
+#define STR_LEFT_CURLY_BRACKET "\173"
+#define STR_VERTICAL_LINE "\174"
+#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_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
+#define STRING_CRLF_RIGHTPAR STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS
+#define STRING_ANY_RIGHTPAR STR_A STR_N STR_Y STR_RIGHT_PARENTHESIS
+#define STRING_ANYCRLF_RIGHTPAR STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS
+#define STRING_BSR_ANYCRLF_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS
+#define STRING_BSR_UNICODE_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_U STR_N STR_I STR_C STR_O STR_D STR_E STR_RIGHT_PARENTHESIS
+#define STRING_UTF8_RIGHTPAR STR_U STR_T STR_F STR_8 STR_RIGHT_PARENTHESIS
+#define STRING_UTF16_RIGHTPAR STR_U STR_T STR_F STR_1 STR_6 STR_RIGHT_PARENTHESIS
+#define STRING_UTF32_RIGHTPAR STR_U STR_T STR_F STR_3 STR_2 STR_RIGHT_PARENTHESIS
+#define STRING_UTF_RIGHTPAR STR_U STR_T STR_F STR_RIGHT_PARENTHESIS
+#define STRING_UCP_RIGHTPAR STR_U STR_C STR_P STR_RIGHT_PARENTHESIS
+#define STRING_NO_AUTO_POSSESS_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_A STR_U STR_T STR_O STR_UNDERSCORE STR_P STR_O STR_S STR_S STR_E STR_S STR_S STR_RIGHT_PARENTHESIS
+#define STRING_NO_START_OPT_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_S STR_T STR_A STR_R STR_T STR_UNDERSCORE STR_O STR_P STR_T STR_RIGHT_PARENTHESIS
+#define STRING_LIMIT_MATCH_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_M STR_A STR_T STR_C STR_H STR_EQUALS_SIGN
+#define STRING_LIMIT_RECURSION_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_R STR_E STR_C STR_U STR_R STR_S STR_I STR_O STR_N STR_EQUALS_SIGN
+
+#endif /* SUPPORT_UTF */
+
+/* Escape items that are just an encoding of a particular data value. */
+
+#ifndef ESC_e
+#define ESC_e CHAR_ESC
+#endif
+
+#ifndef ESC_f
+#define ESC_f CHAR_FF
+#endif
+
+#ifndef ESC_n
+#define ESC_n CHAR_LF
+#endif
+
+#ifndef ESC_r
+#define ESC_r CHAR_CR
+#endif
+
+/* We can't officially use ESC_t because it is a POSIX reserved identifier
+(presumably because of all the others like size_t). */
+
+#ifndef ESC_tee
+#define ESC_tee CHAR_HT
+#endif
+
+/* Codes for different types of Unicode property */
+
+#define PT_ANY 0 /* Any property - matches all chars */
+#define PT_LAMP 1 /* L& - the union of Lu, Ll, Lt */
+#define PT_GC 2 /* Specified general characteristic (e.g. L) */
+#define PT_PC 3 /* Specified particular characteristic (e.g. Lu) */
+#define PT_SC 4 /* Script (e.g. Han) */
+#define PT_ALNUM 5 /* Alphanumeric - the union of L and N */
+#define PT_SPACE 6 /* Perl space - Z plus 9,10,12,13 */
+#define PT_PXSPACE 7 /* POSIX space - Z plus 9,10,11,12,13 */
+#define PT_WORD 8 /* Word - L plus N plus underscore */
+#define PT_CLIST 9 /* Pseudo-property: match character list */
+#define PT_UCNC 10 /* Universal Character nameable character */
+#define PT_TABSIZE 11 /* Size of square table for autopossessify tests */
+
+/* The following special properties are used only in XCLASS items, when POSIX
+classes are specified and PCRE_UCP is set - in other words, for Unicode
+handling of these classes. They are not available via the \p or \P escapes like
+those in the above list, and so they do not take part in the autopossessifying
+table. */
+
+#define PT_PXGRAPH 11 /* [:graph:] - characters that mark the paper */
+#define PT_PXPRINT 12 /* [:print:] - [:graph:] plus non-control spaces */
+#define PT_PXPUNCT 13 /* [:punct:] - punctuation characters */
+
+/* Flag bits and data types for the extended class (OP_XCLASS) for classes that
+contain characters with values greater than 255. */
+
+#define XCL_NOT 0x01 /* Flag: this is a negative class */
+#define XCL_MAP 0x02 /* Flag: a 32-byte map is present */
+#define XCL_HASPROP 0x04 /* Flag: property checks are present. */
+
+#define XCL_END 0 /* Marks end of individual items */
+#define XCL_SINGLE 1 /* Single item (one multibyte char) follows */
+#define XCL_RANGE 2 /* A range (two multibyte chars) follows */
+#define XCL_PROP 3 /* Unicode property (2-byte property code follows) */
+#define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */
+
+/* These are escaped items that aren't just an encoding of a particular data
+value such as \n. They must have non-zero values, as check_escape() returns 0
+for a data character. Also, they must appear in the same order as in the
+opcode definitions below, up to ESC_z. There's a dummy for OP_ALLANY because it
+corresponds to "." in DOTALL mode rather than an escape sequence. It is also
+used for [^] in JavaScript compatibility mode, and for \C in non-utf mode. In
+non-DOTALL mode, "." behaves like \N.
+
+The special values ESC_DU, ESC_du, etc. are used instead of ESC_D, ESC_d, etc.
+when PCRE_UCP is set and replacement of \d etc by \p sequences is required.
+They must be contiguous, and remain in order so that the replacements can be
+looked up from a table.
+
+Negative numbers are used to encode a backreference (\1, \2, \3, etc.) in
+check_escape(). There are two tests in the code for an escape
+greater than ESC_b and less than ESC_Z to detect the types that may be
+repeated. These are the types that consume characters. If any new escapes are
+put in between that don't consume a character, that code will have to change.
+*/
+
+enum { ESC_A = 1, ESC_G, ESC_K, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s,
+ ESC_W, ESC_w, ESC_N, ESC_dum, ESC_C, ESC_P, ESC_p, ESC_R, ESC_H,
+ ESC_h, ESC_V, ESC_v, ESC_X, ESC_Z, ESC_z,
+ ESC_E, ESC_Q, ESC_g, ESC_k,
+ ESC_DU, ESC_du, ESC_SU, ESC_su, ESC_WU, ESC_wu };
+
+
+/********************** Opcode definitions ******************/
+
+/****** NOTE NOTE NOTE ******
+
+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
+pcre_compile.c
+
+Whenever this list is updated, the two macro definitions that follow must be
+updated to match. The possessification table called "opcode_possessify" in
+pcre_compile.c must also be updated, and also the tables called "coptable"
+and "poptable" in pcre_dfa_exec.c.
+
+****** NOTE NOTE NOTE ******/
+
+
+/* The values between FIRST_AUTOTAB_OP and LAST_AUTOTAB_RIGHT_OP, inclusive,
+are used in a table for deciding whether a repeated character type can be
+auto-possessified. */
+
+#define FIRST_AUTOTAB_OP OP_NOT_DIGIT
+#define LAST_AUTOTAB_LEFT_OP OP_EXTUNI
+#define LAST_AUTOTAB_RIGHT_OP OP_DOLLM
+
+enum {
+ OP_END, /* 0 End of pattern */
+
+ /* Values corresponding to backslashed metacharacters */
+
+ OP_SOD, /* 1 Start of data: \A */
+ OP_SOM, /* 2 Start of match (subject + offset): \G */
+ OP_SET_SOM, /* 3 Set start of match (\K) */
+ OP_NOT_WORD_BOUNDARY, /* 4 \B */
+ OP_WORD_BOUNDARY, /* 5 \b */
+ OP_NOT_DIGIT, /* 6 \D */
+ OP_DIGIT, /* 7 \d */
+ OP_NOT_WHITESPACE, /* 8 \S */
+ OP_WHITESPACE, /* 9 \s */
+ OP_NOT_WORDCHAR, /* 10 \W */
+ OP_WORDCHAR, /* 11 \w */
+
+ OP_ANY, /* 12 Match any character except newline (\N) */
+ OP_ALLANY, /* 13 Match any character */
+ OP_ANYBYTE, /* 14 Match any byte (\C); different to OP_ANY for UTF-8 */
+ OP_NOTPROP, /* 15 \P (not Unicode property) */
+ OP_PROP, /* 16 \p (Unicode property) */
+ OP_ANYNL, /* 17 \R (any newline sequence) */
+ OP_NOT_HSPACE, /* 18 \H (not horizontal whitespace) */
+ OP_HSPACE, /* 19 \h (horizontal whitespace) */
+ OP_NOT_VSPACE, /* 20 \V (not vertical whitespace) */
+ OP_VSPACE, /* 21 \v (vertical whitespace) */
+ OP_EXTUNI, /* 22 \X (extended Unicode sequence */
+ OP_EODN, /* 23 End of data or \n at end of data (\Z) */
+ OP_EOD, /* 24 End of data (\z) */
+
+ /* Line end assertions */
+
+ OP_DOLL, /* 25 End of line - not multiline */
+ OP_DOLLM, /* 26 End of line - multiline */
+ OP_CIRC, /* 27 Start of line - not multiline */
+ OP_CIRCM, /* 28 Start of line - multiline */
+
+ /* Single characters; caseful must precede the caseless ones */
+
+ OP_CHAR, /* 29 Match one character, casefully */
+ OP_CHARI, /* 30 Match one character, caselessly */
+ OP_NOT, /* 31 Match one character, not the given one, casefully */
+ OP_NOTI, /* 32 Match one character, not the given one, caselessly */
+
+ /* The following sets of 13 opcodes must always be kept in step because
+ the offset from the first one is used to generate the others. */
+
+ /* Repeated characters; caseful must precede the caseless ones */
+
+ OP_STAR, /* 33 The maximizing and minimizing versions of */
+ OP_MINSTAR, /* 34 these six opcodes must come in pairs, with */
+ OP_PLUS, /* 35 the minimizing one second. */
+ OP_MINPLUS, /* 36 */
+ OP_QUERY, /* 37 */
+ OP_MINQUERY, /* 38 */
+
+ OP_UPTO, /* 39 From 0 to n matches of one character, caseful*/
+ OP_MINUPTO, /* 40 */
+ OP_EXACT, /* 41 Exactly n matches */
+
+ OP_POSSTAR, /* 42 Possessified star, caseful */
+ OP_POSPLUS, /* 43 Possessified plus, caseful */
+ OP_POSQUERY, /* 44 Posesssified query, caseful */
+ OP_POSUPTO, /* 45 Possessified upto, caseful */
+
+ /* Repeated characters; caseless must follow the caseful ones */
+
+ OP_STARI, /* 46 */
+ OP_MINSTARI, /* 47 */
+ OP_PLUSI, /* 48 */
+ OP_MINPLUSI, /* 49 */
+ OP_QUERYI, /* 50 */
+ OP_MINQUERYI, /* 51 */
+
+ OP_UPTOI, /* 52 From 0 to n matches of one character, caseless */
+ OP_MINUPTOI, /* 53 */
+ OP_EXACTI, /* 54 */
+
+ OP_POSSTARI, /* 55 Possessified star, caseless */
+ OP_POSPLUSI, /* 56 Possessified plus, caseless */
+ OP_POSQUERYI, /* 57 Posesssified query, caseless */
+ OP_POSUPTOI, /* 58 Possessified upto, caseless */
+
+ /* The negated ones must follow the non-negated ones, and match them */
+ /* Negated repeated character, caseful; must precede the caseless ones */
+
+ OP_NOTSTAR, /* 59 The maximizing and minimizing versions of */
+ OP_NOTMINSTAR, /* 60 these six opcodes must come in pairs, with */
+ OP_NOTPLUS, /* 61 the minimizing one second. They must be in */
+ OP_NOTMINPLUS, /* 62 exactly the same order as those above. */
+ OP_NOTQUERY, /* 63 */
+ OP_NOTMINQUERY, /* 64 */
+
+ OP_NOTUPTO, /* 65 From 0 to n matches, caseful */
+ OP_NOTMINUPTO, /* 66 */
+ OP_NOTEXACT, /* 67 Exactly n matches */
+
+ OP_NOTPOSSTAR, /* 68 Possessified versions, caseful */
+ OP_NOTPOSPLUS, /* 69 */
+ OP_NOTPOSQUERY, /* 70 */
+ OP_NOTPOSUPTO, /* 71 */
+
+ /* Negated repeated character, caseless; must follow the caseful ones */
+
+ OP_NOTSTARI, /* 72 */
+ OP_NOTMINSTARI, /* 73 */
+ OP_NOTPLUSI, /* 74 */
+ OP_NOTMINPLUSI, /* 75 */
+ OP_NOTQUERYI, /* 76 */
+ OP_NOTMINQUERYI, /* 77 */
+
+ OP_NOTUPTOI, /* 78 From 0 to n matches, caseless */
+ OP_NOTMINUPTOI, /* 79 */
+ OP_NOTEXACTI, /* 80 Exactly n matches */
+
+ OP_NOTPOSSTARI, /* 81 Possessified versions, caseless */
+ OP_NOTPOSPLUSI, /* 82 */
+ OP_NOTPOSQUERYI, /* 83 */
+ OP_NOTPOSUPTOI, /* 84 */
+
+ /* Character types */
+
+ OP_TYPESTAR, /* 85 The maximizing and minimizing versions of */
+ OP_TYPEMINSTAR, /* 86 these six opcodes must come in pairs, with */
+ OP_TYPEPLUS, /* 87 the minimizing one second. These codes must */
+ OP_TYPEMINPLUS, /* 88 be in exactly the same order as those above. */
+ OP_TYPEQUERY, /* 89 */
+ OP_TYPEMINQUERY, /* 90 */
+
+ OP_TYPEUPTO, /* 91 From 0 to n matches */
+ OP_TYPEMINUPTO, /* 92 */
+ OP_TYPEEXACT, /* 93 Exactly n matches */
+
+ OP_TYPEPOSSTAR, /* 94 Possessified versions */
+ OP_TYPEPOSPLUS, /* 95 */
+ OP_TYPEPOSQUERY, /* 96 */
+ OP_TYPEPOSUPTO, /* 97 */
+
+ /* These are used for character classes and back references; only the
+ first six are the same as the sets above. */
+
+ OP_CRSTAR, /* 98 The maximizing and minimizing versions of */
+ OP_CRMINSTAR, /* 99 all these opcodes must come in pairs, with */
+ OP_CRPLUS, /* 100 the minimizing one second. These codes must */
+ OP_CRMINPLUS, /* 101 be in exactly the same order as those above. */
+ OP_CRQUERY, /* 102 */
+ OP_CRMINQUERY, /* 103 */
+
+ OP_CRRANGE, /* 104 These are different to the three sets above. */
+ OP_CRMINRANGE, /* 105 */
+
+ OP_CRPOSSTAR, /* 106 Possessified versions */
+ OP_CRPOSPLUS, /* 107 */
+ OP_CRPOSQUERY, /* 108 */
+ OP_CRPOSRANGE, /* 109 */
+
+ /* End of quantifier opcodes */
+
+ OP_CLASS, /* 110 Match a character class, chars < 256 only */
+ OP_NCLASS, /* 111 Same, but the bitmap was created from a negative
+ class - the difference is relevant only when a
+ character > 255 is encountered. */
+ OP_XCLASS, /* 112 Extended class for handling > 255 chars within the
+ class. This does both positive and negative. */
+ OP_REF, /* 113 Match a back reference, casefully */
+ OP_REFI, /* 114 Match a back reference, caselessly */
+ OP_DNREF, /* 115 Match a duplicate name backref, casefully */
+ OP_DNREFI, /* 116 Match a duplicate name backref, caselessly */
+ OP_RECURSE, /* 117 Match a numbered subpattern (possibly recursive) */
+ OP_CALLOUT, /* 118 Call out to external function if provided */
+
+ OP_ALT, /* 119 Start of alternation */
+ OP_KET, /* 120 End of group that doesn't have an unbounded repeat */
+ OP_KETRMAX, /* 121 These two must remain together and in this */
+ OP_KETRMIN, /* 122 order. They are for groups the repeat for ever. */
+ OP_KETRPOS, /* 123 Possessive unlimited repeat. */
+
+ /* The assertions must come before BRA, CBRA, ONCE, and COND, and the four
+ asserts must remain in order. */
+
+ OP_REVERSE, /* 124 Move pointer back - used in lookbehind assertions */
+ OP_ASSERT, /* 125 Positive lookahead */
+ OP_ASSERT_NOT, /* 126 Negative lookahead */
+ OP_ASSERTBACK, /* 127 Positive lookbehind */
+ OP_ASSERTBACK_NOT, /* 128 Negative lookbehind */
+
+ /* ONCE, ONCE_NC, 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, /* 129 Atomic group, contains captures */
+ OP_ONCE_NC, /* 130 Atomic group containing no 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 */
+
+ /* 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 */
+
+ /* 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_DEF, /* 145 The DEFINE condition */
+
+ OP_BRAZERO, /* 146 These two must remain together and in this */
+ OP_BRAMINZERO, /* 147 order. */
+ OP_BRAPOSZERO, /* 148 */
+
+ /* These are backtracking control verbs */
+
+ OP_MARK, /* 149 always has an argument */
+ OP_PRUNE, /* 150 */
+ OP_PRUNE_ARG, /* 151 same, but with argument */
+ OP_SKIP, /* 152 */
+ OP_SKIP_ARG, /* 153 same, but with argument */
+ OP_THEN, /* 154 */
+ OP_THEN_ARG, /* 155 same, but with argument */
+ OP_COMMIT, /* 156 */
+
+ /* These are forced failure and success verbs */
+
+ OP_FAIL, /* 157 */
+ OP_ACCEPT, /* 158 */
+ OP_ASSERT_ACCEPT, /* 159 Used inside assertions */
+ OP_CLOSE, /* 160 Used before OP_ACCEPT to close open captures */
+
+ /* This is used to skip a subpattern with a {0} quantifier */
+
+ OP_SKIPZERO, /* 161 */
+
+ /* 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
+ some in the past. */
+
+ OP_TABLE_LENGTH
+};
+
+/* *** 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 pcre_compile.c and "coptable" and "poptable" in
+pcre_dfa_exec.c that must be updated. */
+
+
+/* This macro defines textual names for all the opcodes. These are used only
+for debugging, and some of them are only partial names. The macro is referenced
+only in pcre_printint.c, which fills out the full names in many cases (and in
+some cases doesn't actually use these names at all). */
+
+#define OP_NAME_LIST \
+ "End", "\\A", "\\G", "\\K", "\\B", "\\b", "\\D", "\\d", \
+ "\\S", "\\s", "\\W", "\\w", "Any", "AllAny", "Anybyte", \
+ "notprop", "prop", "\\R", "\\H", "\\h", "\\V", "\\v", \
+ "extuni", "\\Z", "\\z", \
+ "$", "$", "^", "^", "char", "chari", "not", "noti", \
+ "*", "*?", "+", "+?", "?", "??", \
+ "{", "{", "{", \
+ "*+","++", "?+", "{", \
+ "*", "*?", "+", "+?", "?", "??", \
+ "{", "{", "{", \
+ "*+","++", "?+", "{", \
+ "*", "*?", "+", "+?", "?", "??", \
+ "{", "{", "{", \
+ "*+","++", "?+", "{", \
+ "*", "*?", "+", "+?", "?", "??", \
+ "{", "{", "{", \
+ "*+","++", "?+", "{", \
+ "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \
+ "*+","++", "?+", "{", \
+ "*", "*?", "+", "+?", "?", "??", "{", "{", \
+ "*+","++", "?+", "{", \
+ "class", "nclass", "xclass", "Ref", "Refi", "DnRef", "DnRefi", \
+ "Recurse", "Callout", \
+ "Alt", "Ket", "KetRmax", "KetRmin", "KetRpos", \
+ "Reverse", "Assert", "Assert not", "AssertB", "AssertB not", \
+ "Once", "Once_NC", \
+ "Bra", "BraPos", "CBra", "CBraPos", \
+ "Cond", \
+ "SBra", "SBraPos", "SCBra", "SCBraPos", \
+ "SCond", \
+ "Cond ref", "Cond dnref", "Cond rec", "Cond dnrec", "Cond def", \
+ "Brazero", "Braminzero", "Braposzero", \
+ "*MARK", "*PRUNE", "*PRUNE", "*SKIP", "*SKIP", \
+ "*THEN", "*THEN", "*COMMIT", "*FAIL", \
+ "*ACCEPT", "*ASSERT_ACCEPT", \
+ "Close", "Skip zero"
+
+
+/* This macro defines the length of fixed length operations in the compiled
+regex. The lengths are used when searching for specific things, and also in the
+debugging printing of a compiled regex. We use a macro so that it can be
+defined close to the definitions of the opcodes themselves.
+
+As things have been extended, some of these are no longer fixed lenths, but are
+minima instead. For example, the length of a single-character repeat may vary
+in UTF-8 mode. The code that uses this table must know about such things. */
+
+#define OP_LENGTHS \
+ 1, /* End */ \
+ 1, 1, 1, 1, 1, /* \A, \G, \K, \B, \b */ \
+ 1, 1, 1, 1, 1, 1, /* \D, \d, \S, \s, \W, \w */ \
+ 1, 1, 1, /* Any, AllAny, Anybyte */ \
+ 3, 3, /* \P, \p */ \
+ 1, 1, 1, 1, 1, /* \R, \H, \h, \V, \v */ \
+ 1, /* \X */ \
+ 1, 1, 1, 1, 1, 1, /* \Z, \z, $, $M ^, ^M */ \
+ 2, /* Char - the minimum length */ \
+ 2, /* Chari - the minimum length */ \
+ 2, /* not */ \
+ 2, /* noti */ \
+ /* Positive single-char repeats ** These are */ \
+ 2, 2, 2, 2, 2, 2, /* *, *?, +, +?, ?, ?? ** minima in */ \
+ 2+IMM2_SIZE, 2+IMM2_SIZE, /* upto, minupto ** mode */ \
+ 2+IMM2_SIZE, /* exact */ \
+ 2, 2, 2, 2+IMM2_SIZE, /* *+, ++, ?+, upto+ */ \
+ 2, 2, 2, 2, 2, 2, /* *I, *?I, +I, +?I, ?I, ??I ** UTF-8 */ \
+ 2+IMM2_SIZE, 2+IMM2_SIZE, /* upto I, minupto I */ \
+ 2+IMM2_SIZE, /* exact I */ \
+ 2, 2, 2, 2+IMM2_SIZE, /* *+I, ++I, ?+I, upto+I */ \
+ /* Negative single-char repeats - only for chars < 256 */ \
+ 2, 2, 2, 2, 2, 2, /* NOT *, *?, +, +?, ?, ?? */ \
+ 2+IMM2_SIZE, 2+IMM2_SIZE, /* NOT upto, minupto */ \
+ 2+IMM2_SIZE, /* NOT exact */ \
+ 2, 2, 2, 2+IMM2_SIZE, /* Possessive NOT *, +, ?, upto */ \
+ 2, 2, 2, 2, 2, 2, /* NOT *I, *?I, +I, +?I, ?I, ??I */ \
+ 2+IMM2_SIZE, 2+IMM2_SIZE, /* NOT upto I, minupto I */ \
+ 2+IMM2_SIZE, /* NOT exact I */ \
+ 2, 2, 2, 2+IMM2_SIZE, /* Possessive NOT *I, +I, ?I, upto I */ \
+ /* Positive type repeats */ \
+ 2, 2, 2, 2, 2, 2, /* Type *, *?, +, +?, ?, ?? */ \
+ 2+IMM2_SIZE, 2+IMM2_SIZE, /* Type upto, minupto */ \
+ 2+IMM2_SIZE, /* Type exact */ \
+ 2, 2, 2, 2+IMM2_SIZE, /* Possessive *+, ++, ?+, upto+ */ \
+ /* Character class & ref repeats */ \
+ 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ \
+ 1+2*IMM2_SIZE, 1+2*IMM2_SIZE, /* CRRANGE, CRMINRANGE */ \
+ 1, 1, 1, 1+2*IMM2_SIZE, /* Possessive *+, ++, ?+, CRPOSRANGE */ \
+ 1+(32/sizeof(pcre_uchar)), /* CLASS */ \
+ 1+(32/sizeof(pcre_uchar)), /* NCLASS */ \
+ 0, /* XCLASS - variable length */ \
+ 1+IMM2_SIZE, /* REF */ \
+ 1+IMM2_SIZE, /* REFI */ \
+ 1+2*IMM2_SIZE, /* DNREF */ \
+ 1+2*IMM2_SIZE, /* DNREFI */ \
+ 1+LINK_SIZE, /* RECURSE */ \
+ 2+2*LINK_SIZE, /* CALLOUT */ \
+ 1+LINK_SIZE, /* Alt */ \
+ 1+LINK_SIZE, /* Ket */ \
+ 1+LINK_SIZE, /* KetRmax */ \
+ 1+LINK_SIZE, /* KetRmin */ \
+ 1+LINK_SIZE, /* KetRpos */ \
+ 1+LINK_SIZE, /* Reverse */ \
+ 1+LINK_SIZE, /* Assert */ \
+ 1+LINK_SIZE, /* Assert not */ \
+ 1+LINK_SIZE, /* Assert behind */ \
+ 1+LINK_SIZE, /* Assert behind not */ \
+ 1+LINK_SIZE, /* ONCE */ \
+ 1+LINK_SIZE, /* ONCE_NC */ \
+ 1+LINK_SIZE, /* BRA */ \
+ 1+LINK_SIZE, /* BRAPOS */ \
+ 1+LINK_SIZE+IMM2_SIZE, /* CBRA */ \
+ 1+LINK_SIZE+IMM2_SIZE, /* CBRAPOS */ \
+ 1+LINK_SIZE, /* COND */ \
+ 1+LINK_SIZE, /* SBRA */ \
+ 1+LINK_SIZE, /* SBRAPOS */ \
+ 1+LINK_SIZE+IMM2_SIZE, /* SCBRA */ \
+ 1+LINK_SIZE+IMM2_SIZE, /* SCBRAPOS */ \
+ 1+LINK_SIZE, /* SCOND */ \
+ 1+IMM2_SIZE, 1+2*IMM2_SIZE, /* CREF, DNCREF */ \
+ 1+IMM2_SIZE, 1+2*IMM2_SIZE, /* RREF, DNRREF */ \
+ 1, /* DEF */ \
+ 1, 1, 1, /* BRAZERO, BRAMINZERO, BRAPOSZERO */ \
+ 3, 1, 3, /* MARK, PRUNE, PRUNE_ARG */ \
+ 1, 3, /* SKIP, SKIP_ARG */ \
+ 1, 3, /* THEN, THEN_ARG */ \
+ 1, 1, 1, 1, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */ \
+ 1+IMM2_SIZE, 1 /* CLOSE, SKIPZERO */
+
+/* A magic value for OP_RREF to indicate the "any recursion" condition. */
+
+#define RREF_ANY 0xffff
+
+/* Compile time error code numbers. They are given names so that they can more
+easily be tracked. When a new number is added, the table called eint in
+pcreposix.c must be updated. */
+
+enum { ERR0, ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9,
+ ERR10, ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19,
+ ERR20, ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29,
+ ERR30, ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39,
+ ERR40, ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49,
+ ERR50, ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59,
+ ERR60, ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69,
+ ERR70, ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79,
+ ERR80, ERR81, ERR82, ERR83, ERR84, ERR85, ERRCOUNT };
+
+/* JIT compiling modes. The function list is indexed by them. */
+
+enum { JIT_COMPILE, JIT_PARTIAL_SOFT_COMPILE, JIT_PARTIAL_HARD_COMPILE,
+ JIT_NUMBER_OF_COMPILE_MODES };
+
+/* The real format of the start of the pcre block; the index of names and the
+code vector run on as long as necessary after the end. We store an explicit
+offset to the name table so that if a regex is compiled on one host, saved, and
+then run on another where the size of pointers is different, all might still
+be well.
+
+The size of the structure must be a multiple of 8 bytes. For the case of
+compiled-on-4 and run-on-8, we include an extra pointer that is always NULL so
+that there are an even number of pointers which therefore are a multiple of 8
+bytes.
+
+It is necessary to fork the struct for the 32 bit library, since it needs to
+use pcre_uint32 for first_char and req_char. We can't put an ifdef inside the
+typedef because pcretest needs access to the struct of the 8-, 16- and 32-bit
+variants.
+
+*** WARNING ***
+When new fields are added to these structures, remember to adjust the code in
+pcre_byte_order.c that is concerned with swapping the byte order of the fields
+when a compiled regex is reloaded on a host with different endianness.
+*** WARNING ***
+There is also similar byte-flipping code in pcretest.c, which is used for
+testing the byte-flipping features. It must also be kept in step.
+*** WARNING ***
+*/
+
+typedef struct real_pcre8_or_16 {
+ pcre_uint32 magic_number;
+ pcre_uint32 size; /* Total that was malloced */
+ pcre_uint32 options; /* Public options */
+ pcre_uint32 flags; /* Private flags */
+ pcre_uint32 limit_match; /* Limit set from regex */
+ pcre_uint32 limit_recursion; /* Limit set from regex */
+ pcre_uint16 first_char; /* Starting character */
+ pcre_uint16 req_char; /* This character must be seen */
+ pcre_uint16 max_lookbehind; /* Longest lookbehind (characters) */
+ pcre_uint16 top_bracket; /* Highest numbered group */
+ pcre_uint16 top_backref; /* Highest numbered back reference */
+ pcre_uint16 name_table_offset; /* Offset to name table that follows */
+ pcre_uint16 name_entry_size; /* Size of any name items */
+ pcre_uint16 name_count; /* Number of name items */
+ pcre_uint16 ref_count; /* Reference count */
+ pcre_uint16 dummy1; /* To ensure size is a multiple of 8 */
+ pcre_uint16 dummy2; /* To ensure size is a multiple of 8 */
+ pcre_uint16 dummy3; /* To ensure size is a multiple of 8 */
+ const pcre_uint8 *tables; /* Pointer to tables or NULL for std */
+ void *nullpad; /* NULL padding */
+} real_pcre8_or_16;
+
+typedef struct real_pcre8_or_16 real_pcre;
+typedef struct real_pcre8_or_16 real_pcre16;
+
+typedef struct real_pcre32 {
+ pcre_uint32 magic_number;
+ pcre_uint32 size; /* Total that was malloced */
+ pcre_uint32 options; /* Public options */
+ pcre_uint32 flags; /* Private flags */
+ pcre_uint32 limit_match; /* Limit set from regex */
+ pcre_uint32 limit_recursion; /* Limit set from regex */
+ pcre_uint32 first_char; /* Starting character */
+ pcre_uint32 req_char; /* This character must be seen */
+ pcre_uint16 max_lookbehind; /* Longest lookbehind (characters) */
+ pcre_uint16 top_bracket; /* Highest numbered group */
+ pcre_uint16 top_backref; /* Highest numbered back reference */
+ pcre_uint16 name_table_offset; /* Offset to name table that follows */
+ pcre_uint16 name_entry_size; /* Size of any name items */
+ pcre_uint16 name_count; /* Number of name items */
+ pcre_uint16 ref_count; /* Reference count */
+ pcre_uint16 dummy; /* To ensure size is a multiple of 8 */
+ const pcre_uint8 *tables; /* Pointer to tables or NULL for std */
+ void *nullpad; /* NULL padding */
+} real_pcre32;
+
+#if defined COMPILE_PCRE8
+#define REAL_PCRE real_pcre
+#elif defined COMPILE_PCRE16
+#define REAL_PCRE real_pcre16
+#elif defined COMPILE_PCRE32
+#define REAL_PCRE real_pcre32
+#endif
+
+/* Assert that the size of REAL_PCRE is divisible by 8 */
+typedef int __assert_real_pcre_size_divisible_8[(sizeof(REAL_PCRE) % 8) == 0 ? 1 : -1];
+
+/* Needed in pcretest to access some fields in the real_pcre* structures
+ * directly. They're unified for 8/16/32 bits since the structs only differ
+ * after these fields; if that ever changes, need to fork those defines into
+ * 8/16 and 32 bit versions. */
+#define REAL_PCRE_MAGIC(re) (((REAL_PCRE*)re)->magic_number)
+#define REAL_PCRE_SIZE(re) (((REAL_PCRE*)re)->size)
+#define REAL_PCRE_OPTIONS(re) (((REAL_PCRE*)re)->options)
+#define REAL_PCRE_FLAGS(re) (((REAL_PCRE*)re)->flags)
+
+/* The format of the block used to store data from pcre_study(). The same
+remark (see NOTE above) about extending this structure applies. */
+
+typedef struct pcre_study_data {
+ pcre_uint32 size; /* Total that was malloced */
+ pcre_uint32 flags; /* Private flags */
+ pcre_uint8 start_bits[32]; /* Starting char bits */
+ pcre_uint32 minlength; /* Minimum subject length */
+} pcre_study_data;
+
+/* Structure for building a chain of open capturing subpatterns during
+compiling, so that instructions to close them can be compiled when (*ACCEPT) is
+encountered. This is also used to identify subpatterns that contain recursive
+back references to themselves, so that they can be made atomic. */
+
+typedef struct open_capitem {
+ struct open_capitem *next; /* Chain link */
+ pcre_uint16 number; /* Capture number */
+ pcre_uint16 flag; /* Set TRUE if recursive back ref */
+} open_capitem;
+
+/* Structure for building a list of named groups during the first pass of
+compiling. */
+
+typedef struct named_group {
+ const pcre_uchar *name; /* Points to the name in the pattern */
+ int length; /* Length of the name */
+ pcre_uint32 number; /* Group number */
+} named_group;
+
+/* Structure for passing "static" information around between the functions
+doing the compiling, so that they are thread-safe. */
+
+typedef struct compile_data {
+ const pcre_uint8 *lcc; /* Points to lower casing table */
+ const pcre_uint8 *fcc; /* Points to case-flipping table */
+ const pcre_uint8 *cbits; /* Points to character type table */
+ const pcre_uint8 *ctypes; /* Points to table of type maps */
+ const pcre_uchar *start_workspace;/* The start of working space */
+ const pcre_uchar *start_code; /* The start of the compiled code */
+ const pcre_uchar *start_pattern; /* The start of the pattern */
+ const pcre_uchar *end_pattern; /* The end of the pattern */
+ pcre_uchar *hwm; /* High watermark of workspace */
+ open_capitem *open_caps; /* Chain of open capture items */
+ named_group *named_groups; /* Points to vector in pre-compile */
+ pcre_uchar *name_table; /* The name/number table */
+ int names_found; /* Number of entries so far */
+ int name_entry_size; /* Size of each entry */
+ int named_group_list_size; /* Number of entries in the list */
+ int workspace_size; /* Size of workspace */
+ unsigned int bracount; /* Count of capturing parens as we compile */
+ int final_bracount; /* Saved value after first pass */
+ int max_lookbehind; /* Maximum lookbehind (characters) */
+ int top_backref; /* Maximum back reference */
+ unsigned int backref_map; /* Bitmap of low back refs */
+ unsigned int namedrefcount; /* Number of backreferences by name */
+ int parens_depth; /* Depth of nested parentheses */
+ int assert_depth; /* Depth of nested assertions */
+ pcre_uint32 external_options; /* External (initial) options */
+ pcre_uint32 external_flags; /* External flag bits to be set */
+ int req_varyopt; /* "After variable item" flag for reqbyte */
+ BOOL had_accept; /* (*ACCEPT) encountered */
+ BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */
+ BOOL check_lookbehind; /* Lookbehinds need later checking */
+ BOOL dupnames; /* Duplicate names exist */
+ int nltype; /* Newline type */
+ int nllen; /* Newline string length */
+ pcre_uchar nl[4]; /* Newline string when fixed length */
+} compile_data;
+
+/* Structure for maintaining a chain of pointers to the currently incomplete
+branches, for testing for left recursion while compiling. */
+
+typedef struct branch_chain {
+ struct branch_chain *outer;
+ pcre_uchar *current_branch;
+} branch_chain;
+
+/* Structure for items in a linked list that represents an explicit recursive
+call within the pattern; used by pcre_exec(). */
+
+typedef struct recursion_info {
+ struct recursion_info *prevrec; /* Previous recursion record (or NULL) */
+ unsigned int group_num; /* Number of group that was called */
+ int *offset_save; /* Pointer to start of saved offsets */
+ int saved_max; /* Number of saved offsets */
+ int saved_capture_last; /* Last capture number */
+ PCRE_PUCHAR subject_position; /* Position at start of recursion */
+} recursion_info;
+
+/* A similar structure for pcre_dfa_exec(). */
+
+typedef struct dfa_recursion_info {
+ struct dfa_recursion_info *prevrec;
+ int group_num;
+ PCRE_PUCHAR subject_position;
+} dfa_recursion_info;
+
+/* Structure for building a chain of data for holding the values of the subject
+pointer at the start of each subpattern, so as to detect when an empty string
+has been matched by a subpattern - to break infinite loops; used by
+pcre_exec(). */
+
+typedef struct eptrblock {
+ struct eptrblock *epb_prev;
+ PCRE_PUCHAR epb_saved_eptr;
+} eptrblock;
+
+
+/* Structure for passing "static" information around between the functions
+doing traditional NFA matching, so that they are thread-safe. */
+
+typedef struct match_data {
+ unsigned long int match_call_count; /* As it says */
+ unsigned long int match_limit; /* As it says */
+ unsigned long int match_limit_recursion; /* As it says */
+ int *offset_vector; /* Offset vector */
+ int offset_end; /* One past the end */
+ int offset_max; /* The maximum usable for return data */
+ int nltype; /* Newline type */
+ int nllen; /* Newline string length */
+ int name_count; /* Number of names in name table */
+ int name_entry_size; /* Size of entry in names table */
+ unsigned int skip_arg_count; /* For counting SKIP_ARGs */
+ unsigned int ignore_skip_arg; /* For re-run when SKIP arg name not found */
+ pcre_uchar *name_table; /* Table of names */
+ pcre_uchar nl[4]; /* Newline string when fixed */
+ const pcre_uint8 *lcc; /* Points to lower casing table */
+ const pcre_uint8 *fcc; /* Points to case-flipping table */
+ const pcre_uint8 *ctypes; /* Points to table of type maps */
+ BOOL notbol; /* NOTBOL flag */
+ BOOL noteol; /* NOTEOL flag */
+ BOOL utf; /* UTF-8 / UTF-16 flag */
+ BOOL jscript_compat; /* JAVASCRIPT_COMPAT flag */
+ BOOL use_ucp; /* PCRE_UCP flag */
+ BOOL endonly; /* Dollar not before final \n */
+ BOOL notempty; /* Empty string match not wanted */
+ BOOL notempty_atstart; /* Empty string match at start not wanted */
+ BOOL hitend; /* Hit the end of the subject at some point */
+ BOOL bsr_anycrlf; /* \R is just any CRLF, not full Unicode */
+ BOOL hasthen; /* Pattern contains (*THEN) */
+ const pcre_uchar *start_code; /* For use when recursing */
+ PCRE_PUCHAR start_subject; /* Start of the subject string */
+ PCRE_PUCHAR end_subject; /* End of the subject string */
+ PCRE_PUCHAR start_match_ptr; /* Start of matched string */
+ PCRE_PUCHAR end_match_ptr; /* Subject position at end match */
+ PCRE_PUCHAR start_used_ptr; /* Earliest consulted character */
+ int partial; /* PARTIAL options */
+ int end_offset_top; /* Highwater mark at end of match */
+ pcre_int32 capture_last; /* Most recent capture number + overflow flag */
+ int start_offset; /* The start offset value */
+ int match_function_type; /* Set for certain special calls of MATCH() */
+ eptrblock *eptrchain; /* Chain of eptrblocks for tail recursions */
+ int eptrn; /* Next free eptrblock */
+ recursion_info *recursive; /* Linked list of recursion data */
+ void *callout_data; /* To pass back to callouts */
+ const pcre_uchar *mark; /* Mark pointer to pass back on success */
+ const pcre_uchar *nomatch_mark;/* Mark pointer to pass back on failure */
+ const pcre_uchar *once_target; /* Where to back up to for atomic groups */
+#ifdef NO_RECURSE
+ void *match_frames_base; /* For remembering malloc'd frames */
+#endif
+} match_data;
+
+/* A similar structure is used for the same purpose by the DFA matching
+functions. */
+
+typedef struct dfa_match_data {
+ const pcre_uchar *start_code; /* Start of the compiled pattern */
+ const pcre_uchar *start_subject ; /* Start of the subject string */
+ const pcre_uchar *end_subject; /* End of subject string */
+ const pcre_uchar *start_used_ptr; /* Earliest consulted character */
+ const pcre_uint8 *tables; /* Character tables */
+ int start_offset; /* The start offset value */
+ int moptions; /* Match options */
+ int poptions; /* Pattern options */
+ int nltype; /* Newline type */
+ int nllen; /* Newline string length */
+ pcre_uchar nl[4]; /* Newline string when fixed */
+ void *callout_data; /* To pass back to callouts */
+ dfa_recursion_info *recursive; /* Linked list of recursion data */
+} dfa_match_data;
+
+/* Bit definitions for entries in the pcre_ctypes table. */
+
+#define ctype_space 0x01
+#define ctype_letter 0x02
+#define ctype_digit 0x04
+#define ctype_xdigit 0x08
+#define ctype_word 0x10 /* alphanumeric or '_' */
+#define ctype_meta 0x80 /* regexp meta char or zero (end pattern) */
+
+/* Offsets for the bitmap tables in pcre_cbits. Each table contains a set
+of bits for a class map. Some classes are built by combining these tables. */
+
+#define cbit_space 0 /* [:space:] or \s */
+#define cbit_xdigit 32 /* [:xdigit:] */
+#define cbit_digit 64 /* [:digit:] or \d */
+#define cbit_upper 96 /* [:upper:] */
+#define cbit_lower 128 /* [:lower:] */
+#define cbit_word 160 /* [:word:] or \w */
+#define cbit_graph 192 /* [:graph:] */
+#define cbit_print 224 /* [:print:] */
+#define cbit_punct 256 /* [:punct:] */
+#define cbit_cntrl 288 /* [:cntrl:] */
+#define cbit_length 320 /* Length of the cbits table */
+
+/* Offsets of the various tables from the base tables pointer, and
+total length. */
+
+#define lcc_offset 0
+#define fcc_offset 256
+#define cbits_offset 512
+#define ctypes_offset (cbits_offset + cbit_length)
+#define tables_length (ctypes_offset + 256)
+
+/* Internal function and data prefixes. */
+
+#if defined COMPILE_PCRE8
+#ifndef PUBL
+#define PUBL(name) pcre_##name
+#endif
+#ifndef PRIV
+#define PRIV(name) _pcre_##name
+#endif
+#elif defined COMPILE_PCRE16
+#ifndef PUBL
+#define PUBL(name) pcre16_##name
+#endif
+#ifndef PRIV
+#define PRIV(name) _pcre16_##name
+#endif
+#elif defined COMPILE_PCRE32
+#ifndef PUBL
+#define PUBL(name) pcre32_##name
+#endif
+#ifndef PRIV
+#define PRIV(name) _pcre32_##name
+#endif
+#else
+#error Unsupported compiling mode
+#endif /* COMPILE_PCRE[8|16|32] */
+
+/* Layout of the UCP type table that translates property names into types and
+codes. Each entry used to point directly to a name, but to reduce the number of
+relocations in shared libraries, it now has an offset into a single string
+instead. */
+
+typedef struct {
+ pcre_uint16 name_offset;
+ pcre_uint16 type;
+ pcre_uint16 value;
+} ucp_type_table;
+
+
+/* Internal shared data tables. These are tables that are used by more than one
+of the exported public functions. They have to be "external" in the C sense,
+but are not part of the PCRE public API. The data for these tables is in the
+pcre_tables.c module. */
+
+#ifdef COMPILE_PCRE8
+extern const int PRIV(utf8_table1)[];
+extern const int PRIV(utf8_table1_size);
+extern const int PRIV(utf8_table2)[];
+extern const int PRIV(utf8_table3)[];
+extern const pcre_uint8 PRIV(utf8_table4)[];
+#endif /* COMPILE_PCRE8 */
+
+extern const char PRIV(utt_names)[];
+extern const ucp_type_table PRIV(utt)[];
+extern const int PRIV(utt_size);
+
+extern const pcre_uint8 PRIV(OP_lengths)[];
+extern const pcre_uint8 PRIV(default_tables)[];
+
+extern const pcre_uint32 PRIV(hspace_list)[];
+extern const pcre_uint32 PRIV(vspace_list)[];
+
+
+/* Internal shared functions. These are functions that are used by more than
+one of the exported public functions. They have to be "external" in the C
+sense, but are not part of the PCRE public API. */
+
+/* String comparison functions. */
+#if defined COMPILE_PCRE8
+
+#define STRCMP_UC_UC(str1, str2) \
+ strcmp((char *)(str1), (char *)(str2))
+#define STRCMP_UC_C8(str1, str2) \
+ strcmp((char *)(str1), (str2))
+#define STRNCMP_UC_UC(str1, str2, num) \
+ strncmp((char *)(str1), (char *)(str2), (num))
+#define STRNCMP_UC_C8(str1, str2, num) \
+ strncmp((char *)(str1), (str2), (num))
+#define STRLEN_UC(str) strlen((const char *)str)
+
+#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+
+extern int PRIV(strcmp_uc_uc)(const pcre_uchar *,
+ const pcre_uchar *);
+extern int PRIV(strcmp_uc_c8)(const pcre_uchar *,
+ const char *);
+extern int PRIV(strncmp_uc_uc)(const pcre_uchar *,
+ const pcre_uchar *, unsigned int num);
+extern int PRIV(strncmp_uc_c8)(const pcre_uchar *,
+ const char *, unsigned int num);
+extern unsigned int PRIV(strlen_uc)(const pcre_uchar *str);
+
+#define STRCMP_UC_UC(str1, str2) \
+ PRIV(strcmp_uc_uc)((str1), (str2))
+#define STRCMP_UC_C8(str1, str2) \
+ PRIV(strcmp_uc_c8)((str1), (str2))
+#define STRNCMP_UC_UC(str1, str2, num) \
+ PRIV(strncmp_uc_uc)((str1), (str2), (num))
+#define STRNCMP_UC_C8(str1, str2, num) \
+ PRIV(strncmp_uc_c8)((str1), (str2), (num))
+#define STRLEN_UC(str) PRIV(strlen_uc)(str)
+
+#endif /* COMPILE_PCRE[8|16|32] */
+
+#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
+
+#define STRCMP_UC_UC_TEST(str1, str2) STRCMP_UC_UC(str1, str2)
+#define STRCMP_UC_C8_TEST(str1, str2) STRCMP_UC_C8(str1, str2)
+
+#elif defined COMPILE_PCRE32
+
+extern int PRIV(strcmp_uc_uc_utf)(const pcre_uchar *,
+ const pcre_uchar *);
+extern int PRIV(strcmp_uc_c8_utf)(const pcre_uchar *,
+ const char *);
+
+#define STRCMP_UC_UC_TEST(str1, str2) \
+ (utf ? PRIV(strcmp_uc_uc_utf)((str1), (str2)) : PRIV(strcmp_uc_uc)((str1), (str2)))
+#define STRCMP_UC_C8_TEST(str1, str2) \
+ (utf ? PRIV(strcmp_uc_c8_utf)((str1), (str2)) : PRIV(strcmp_uc_c8)((str1), (str2)))
+
+#endif /* COMPILE_PCRE[8|16|32] */
+
+extern const pcre_uchar *PRIV(find_bracket)(const pcre_uchar *, BOOL, int);
+extern BOOL PRIV(is_newline)(PCRE_PUCHAR, int, PCRE_PUCHAR,
+ int *, BOOL);
+extern unsigned int PRIV(ord2utf)(pcre_uint32, pcre_uchar *);
+extern int PRIV(valid_utf)(PCRE_PUCHAR, int, int *);
+extern BOOL PRIV(was_newline)(PCRE_PUCHAR, int, PCRE_PUCHAR,
+ int *, BOOL);
+extern BOOL PRIV(xclass)(pcre_uint32, const pcre_uchar *, BOOL);
+
+#ifdef SUPPORT_JIT
+extern void PRIV(jit_compile)(const REAL_PCRE *,
+ PUBL(extra) *, int);
+extern int PRIV(jit_exec)(const PUBL(extra) *,
+ const pcre_uchar *, int, int, int, int *, int);
+extern void PRIV(jit_free)(void *);
+extern int PRIV(jit_get_size)(void *);
+extern const char* PRIV(jit_get_target)(void);
+#endif
+
+/* Unicode character database (UCD) */
+
+typedef struct {
+ pcre_uint8 script; /* ucp_Arabic, etc. */
+ pcre_uint8 chartype; /* ucp_Cc, etc. (general categories) */
+ pcre_uint8 gbprop; /* ucp_gbControl, etc. (grapheme break property) */
+ pcre_uint8 caseset; /* offset to multichar other cases or zero */
+ pcre_int32 other_case; /* offset to other case, or zero if none */
+} ucd_record;
+
+extern const pcre_uint32 PRIV(ucd_caseless_sets)[];
+extern const ucd_record PRIV(ucd_records)[];
+extern const pcre_uint8 PRIV(ucd_stage1)[];
+extern const pcre_uint16 PRIV(ucd_stage2)[];
+extern const pcre_uint32 PRIV(ucp_gentype)[];
+extern const pcre_uint32 PRIV(ucp_gbtable)[];
+#ifdef SUPPORT_JIT
+extern const int PRIV(ucp_typerange)[];
+#endif
+
+#ifdef SUPPORT_UCP
+/* UCD access macros */
+
+#define UCD_BLOCK_SIZE 128
+#define GET_UCD(ch) (PRIV(ucd_records) + \
+ PRIV(ucd_stage2)[PRIV(ucd_stage1)[(int)(ch) / UCD_BLOCK_SIZE] * \
+ UCD_BLOCK_SIZE + (int)(ch) % UCD_BLOCK_SIZE])
+
+#define UCD_CHARTYPE(ch) GET_UCD(ch)->chartype
+#define UCD_SCRIPT(ch) GET_UCD(ch)->script
+#define UCD_CATEGORY(ch) PRIV(ucp_gentype)[UCD_CHARTYPE(ch)]
+#define UCD_GRAPHBREAK(ch) GET_UCD(ch)->gbprop
+#define UCD_CASESET(ch) GET_UCD(ch)->caseset
+#define UCD_OTHERCASE(ch) ((pcre_uint32)((int)ch + (int)(GET_UCD(ch)->other_case)))
+
+#endif /* SUPPORT_UCP */
+
+#endif
+
+/* End of pcre_internal.h */
diff --git a/plugins/Pcre16/src/pcre_jit_compile.c b/plugins/Pcre16/src/pcre_jit_compile.c
new file mode 100644
index 0000000000..e67071ef79
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_jit_compile.c
@@ -0,0 +1,10701 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2013 University of Cambridge
+
+ The machine code generator part (this module) was written by Zoltan Herczeg
+ Copyright (c) 2010-2013
+
+-----------------------------------------------------------------------------
+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.
+-----------------------------------------------------------------------------
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+#if defined SUPPORT_JIT
+
+/* All-in-one: Since we use the JIT compiler only from here,
+we just include it. This way we don't need to touch the build
+system files. */
+
+#define SLJIT_MALLOC(size) (PUBL(malloc))(size)
+#define SLJIT_FREE(ptr) (PUBL(free))(ptr)
+#define SLJIT_CONFIG_AUTO 1
+#define SLJIT_CONFIG_STATIC 1
+#define SLJIT_VERBOSE 0
+#define SLJIT_DEBUG 0
+
+#include "sljit/sljitLir.c"
+
+#if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED
+#error Unsupported architecture
+#endif
+
+/* Defines for debugging purposes. */
+
+/* 1 - Use unoptimized capturing brackets.
+ 2 - Enable capture_last_ptr (includes option 1). */
+/* #define DEBUG_FORCE_UNOPTIMIZED_CBRAS 2 */
+
+/* 1 - Always have a control head. */
+/* #define DEBUG_FORCE_CONTROL_HEAD 1 */
+
+/* Allocate memory for the regex stack on the real machine stack.
+Fast, but limited size. */
+#define MACHINE_STACK_SIZE 32768
+
+/* Growth rate for stack allocated by the OS. Should be the multiply
+of page size. */
+#define STACK_GROWTH_RATE 8192
+
+/* Enable to check that the allocation could destroy temporaries. */
+#if defined SLJIT_DEBUG && SLJIT_DEBUG
+#define DESTROY_REGISTERS 1
+#endif
+
+/*
+Short summary about the backtracking mechanism empolyed by the jit code generator:
+
+The code generator follows the recursive nature of the PERL compatible regular
+expressions. The basic blocks of regular expressions are condition checkers
+whose execute different commands depending on the result of the condition check.
+The relationship between the operators can be horizontal (concatenation) and
+vertical (sub-expression) (See struct backtrack_common for more details).
+
+ 'ab' - 'a' and 'b' regexps are concatenated
+ 'a+' - 'a' is the sub-expression of the '+' operator
+
+The condition checkers are boolean (true/false) checkers. Machine code is generated
+for the checker itself and for the actions depending on the result of the checker.
+The 'true' case is called as the matching path (expected path), and the other is called as
+the 'backtrack' path. Branch instructions are expesive for all CPUs, so we avoid taken
+branches on the matching path.
+
+ Greedy star operator (*) :
+ Matching path: match happens.
+ Backtrack path: match failed.
+ Non-greedy star operator (*?) :
+ Matching path: no need to perform a match.
+ Backtrack path: match is required.
+
+The following example shows how the code generated for a capturing bracket
+with two alternatives. Let A, B, C, D are arbirary regular expressions, and
+we have the following regular expression:
+
+ A(B|C)D
+
+The generated code will be the following:
+
+ A matching path
+ '(' matching path (pushing arguments to the stack)
+ B matching path
+ ')' matching path (pushing arguments to the stack)
+ D matching path
+ return with successful match
+
+ D backtrack path
+ ')' backtrack path (If we arrived from "C" jump to the backtrack of "C")
+ B backtrack path
+ C expected path
+ jump to D matching path
+ C backtrack path
+ A backtrack path
+
+ Notice, that the order of backtrack code paths are the opposite of the fast
+ code paths. In this way the topmost value on the stack is always belong
+ to the current backtrack code path. The backtrack path must check
+ whether there is a next alternative. If so, it needs to jump back to
+ the matching path eventually. Otherwise it needs to clear out its own stack
+ frame and continue the execution on the backtrack code paths.
+*/
+
+/*
+Saved stack frames:
+
+Atomic blocks and asserts require reloading the values of private data
+when the backtrack mechanism performed. Because of OP_RECURSE, the data
+are not necessarly known in compile time, thus we need a dynamic restore
+mechanism.
+
+The stack frames are stored in a chain list, and have the following format:
+([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ]
+
+Thus we can restore the private data to a particular point in the stack.
+*/
+
+typedef struct jit_arguments {
+ /* Pointers first. */
+ struct sljit_stack *stack;
+ const pcre_uchar *str;
+ const pcre_uchar *begin;
+ const pcre_uchar *end;
+ int *offsets;
+ pcre_uchar *uchar_ptr;
+ pcre_uchar *mark_ptr;
+ void *callout_data;
+ /* Everything else after. */
+ pcre_uint32 limit_match;
+ int real_offset_count;
+ int offset_count;
+ pcre_uint8 notbol;
+ pcre_uint8 noteol;
+ pcre_uint8 notempty;
+ pcre_uint8 notempty_atstart;
+} jit_arguments;
+
+typedef struct executable_functions {
+ void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES];
+ sljit_uw *read_only_data[JIT_NUMBER_OF_COMPILE_MODES];
+ sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES];
+ PUBL(jit_callback) callback;
+ void *userdata;
+ pcre_uint32 top_bracket;
+ pcre_uint32 limit_match;
+} executable_functions;
+
+typedef struct jump_list {
+ struct sljit_jump *jump;
+ struct jump_list *next;
+} jump_list;
+
+typedef struct stub_list {
+ struct sljit_jump *start;
+ struct sljit_label *quit;
+ struct stub_list *next;
+} stub_list;
+
+typedef struct label_addr_list {
+ struct sljit_label *label;
+ sljit_uw *addr;
+ struct label_addr_list *next;
+} label_addr_list;
+
+enum frame_types {
+ no_frame = -1,
+ no_stack = -2
+};
+
+enum control_types {
+ type_mark = 0,
+ type_then_trap = 1
+};
+
+typedef int (SLJIT_CALL *jit_function)(jit_arguments *args);
+
+/* The following structure is the key data type for the recursive
+code generator. It is allocated by compile_matchingpath, and contains
+the arguments for compile_backtrackingpath. Must be the first member
+of its descendants. */
+typedef struct backtrack_common {
+ /* Concatenation stack. */
+ struct backtrack_common *prev;
+ jump_list *nextbacktracks;
+ /* Internal stack (for component operators). */
+ struct backtrack_common *top;
+ jump_list *topbacktracks;
+ /* Opcode pointer. */
+ pcre_uchar *cc;
+} backtrack_common;
+
+typedef struct assert_backtrack {
+ backtrack_common common;
+ jump_list *condfailed;
+ /* Less than 0 if a frame is not needed. */
+ int framesize;
+ /* Points to our private memory word on the stack. */
+ int private_data_ptr;
+ /* For iterators. */
+ struct sljit_label *matchingpath;
+} assert_backtrack;
+
+typedef struct bracket_backtrack {
+ backtrack_common common;
+ /* Where to coninue if an alternative is successfully matched. */
+ struct sljit_label *alternative_matchingpath;
+ /* For rmin and rmax iterators. */
+ struct sljit_label *recursive_matchingpath;
+ /* For greedy ? operator. */
+ struct sljit_label *zero_matchingpath;
+ /* Contains the branches of a failed condition. */
+ union {
+ /* Both for OP_COND, OP_SCOND. */
+ jump_list *condfailed;
+ assert_backtrack *assert;
+ /* For OP_ONCE. Less than 0 if not needed. */
+ int framesize;
+ } u;
+ /* Points to our private memory word on the stack. */
+ int private_data_ptr;
+} bracket_backtrack;
+
+typedef struct bracketpos_backtrack {
+ backtrack_common common;
+ /* Points to our private memory word on the stack. */
+ int private_data_ptr;
+ /* Reverting stack is needed. */
+ int framesize;
+ /* Allocated stack size. */
+ int stacksize;
+} bracketpos_backtrack;
+
+typedef struct braminzero_backtrack {
+ backtrack_common common;
+ struct sljit_label *matchingpath;
+} braminzero_backtrack;
+
+typedef struct iterator_backtrack {
+ backtrack_common common;
+ /* Next iteration. */
+ struct sljit_label *matchingpath;
+} iterator_backtrack;
+
+typedef struct recurse_entry {
+ struct recurse_entry *next;
+ /* Contains the function entry. */
+ struct sljit_label *entry;
+ /* Collects the calls until the function is not created. */
+ jump_list *calls;
+ /* Points to the starting opcode. */
+ sljit_sw start;
+} recurse_entry;
+
+typedef struct recurse_backtrack {
+ backtrack_common common;
+ BOOL inlined_pattern;
+} recurse_backtrack;
+
+#define OP_THEN_TRAP OP_TABLE_LENGTH
+
+typedef struct then_trap_backtrack {
+ backtrack_common common;
+ /* If then_trap is not NULL, this structure contains the real
+ then_trap for the backtracking path. */
+ struct then_trap_backtrack *then_trap;
+ /* Points to the starting opcode. */
+ sljit_sw start;
+ /* Exit point for the then opcodes of this alternative. */
+ jump_list *quit;
+ /* Frame size of the current alternative. */
+ int framesize;
+} then_trap_backtrack;
+
+#define MAX_RANGE_SIZE 4
+
+typedef struct compiler_common {
+ /* The sljit ceneric compiler. */
+ struct sljit_compiler *compiler;
+ /* First byte code. */
+ pcre_uchar *start;
+ /* Maps private data offset to each opcode. */
+ sljit_si *private_data_ptrs;
+ /* This read-only data is available during runtime. */
+ sljit_uw *read_only_data;
+ /* The total size of the read-only data. */
+ sljit_uw read_only_data_size;
+ /* The next free entry of the read_only_data. */
+ sljit_uw *read_only_data_ptr;
+ /* Tells whether the capturing bracket is optimized. */
+ pcre_uint8 *optimized_cbracket;
+ /* Tells whether the starting offset is a target of then. */
+ pcre_uint8 *then_offsets;
+ /* Current position where a THEN must jump. */
+ then_trap_backtrack *then_trap;
+ /* Starting offset of private data for capturing brackets. */
+ int cbra_ptr;
+ /* Output vector starting point. Must be divisible by 2. */
+ int ovector_start;
+ /* Last known position of the requested byte. */
+ int req_char_ptr;
+ /* Head of the last recursion. */
+ int recursive_head_ptr;
+ /* First inspected character for partial matching. */
+ int start_used_ptr;
+ /* Starting pointer for partial soft matches. */
+ int hit_start;
+ /* End pointer of the first line. */
+ int first_line_end;
+ /* Points to the marked string. */
+ int mark_ptr;
+ /* Recursive control verb management chain. */
+ int control_head_ptr;
+ /* Points to the last matched capture block index. */
+ int capture_last_ptr;
+ /* Points to the starting position of the current match. */
+ int start_ptr;
+
+ /* Flipped and lower case tables. */
+ const pcre_uint8 *fcc;
+ sljit_sw lcc;
+ /* Mode can be PCRE_STUDY_JIT_COMPILE and others. */
+ int mode;
+ /* TRUE, when minlength is greater than 0. */
+ BOOL might_be_empty;
+ /* \K is found in the pattern. */
+ BOOL has_set_som;
+ /* (*SKIP:arg) is found in the pattern. */
+ BOOL has_skip_arg;
+ /* (*THEN) is found in the pattern. */
+ BOOL has_then;
+ /* Needs to know the start position anytime. */
+ BOOL needs_start_ptr;
+ /* Currently in recurse or negative assert. */
+ BOOL local_exit;
+ /* Currently in a positive assert. */
+ BOOL positive_assert;
+ /* Newline control. */
+ int nltype;
+ pcre_uint32 nlmax;
+ pcre_uint32 nlmin;
+ int newline;
+ int bsr_nltype;
+ pcre_uint32 bsr_nlmax;
+ pcre_uint32 bsr_nlmin;
+ /* Dollar endonly. */
+ int endonly;
+ /* Tables. */
+ sljit_sw ctypes;
+ /* Named capturing brackets. */
+ pcre_uchar *name_table;
+ sljit_sw name_count;
+ sljit_sw name_entry_size;
+
+ /* Labels and jump lists. */
+ struct sljit_label *partialmatchlabel;
+ struct sljit_label *quit_label;
+ struct sljit_label *forced_quit_label;
+ 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;
+ jump_list *quit;
+ jump_list *positive_assert_quit;
+ jump_list *forced_quit;
+ jump_list *accept;
+ jump_list *calllimit;
+ jump_list *stackalloc;
+ jump_list *revertframes;
+ jump_list *wordboundary;
+ jump_list *anynewline;
+ jump_list *hspace;
+ jump_list *vspace;
+ jump_list *casefulcmp;
+ jump_list *caselesscmp;
+ jump_list *reset_match;
+ BOOL jscript_compat;
+#ifdef SUPPORT_UTF
+ BOOL utf;
+#ifdef SUPPORT_UCP
+ BOOL use_ucp;
+#endif
+#ifdef COMPILE_PCRE8
+ jump_list *utfreadchar;
+ jump_list *utfreadchar16;
+ jump_list *utfreadtype8;
+#endif
+#endif /* SUPPORT_UTF */
+#ifdef SUPPORT_UCP
+ jump_list *getucd;
+#endif
+} compiler_common;
+
+/* For byte_sequence_compare. */
+
+typedef struct compare_context {
+ int length;
+ int sourcereg;
+#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
+ int ucharptr;
+ union {
+ sljit_si asint;
+ sljit_uh asushort;
+#if defined COMPILE_PCRE8
+ sljit_ub asbyte;
+ sljit_ub asuchars[4];
+#elif defined COMPILE_PCRE16
+ sljit_uh asuchars[2];
+#elif defined COMPILE_PCRE32
+ sljit_ui asuchars[1];
+#endif
+ } c;
+ union {
+ sljit_si asint;
+ sljit_uh asushort;
+#if defined COMPILE_PCRE8
+ sljit_ub asbyte;
+ sljit_ub asuchars[4];
+#elif defined COMPILE_PCRE16
+ sljit_uh asuchars[2];
+#elif defined COMPILE_PCRE32
+ sljit_ui asuchars[1];
+#endif
+ } oc;
+#endif
+} compare_context;
+
+/* Undefine sljit macros. */
+#undef CMP
+
+/* Used for accessing the elements of the stack. */
+#define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_sw))
+
+#define TMP1 SLJIT_SCRATCH_REG1
+#define TMP2 SLJIT_SCRATCH_REG3
+#define TMP3 SLJIT_TEMPORARY_EREG2
+#define STR_PTR SLJIT_SAVED_REG1
+#define STR_END SLJIT_SAVED_REG2
+#define STACK_TOP SLJIT_SCRATCH_REG2
+#define STACK_LIMIT SLJIT_SAVED_REG3
+#define ARGUMENTS SLJIT_SAVED_EREG1
+#define COUNT_MATCH SLJIT_SAVED_EREG2
+#define RETURN_ADDR SLJIT_TEMPORARY_EREG1
+
+/* Local space layout. */
+/* These two locals can be used by the current opcode. */
+#define LOCALS0 (0 * sizeof(sljit_sw))
+#define LOCALS1 (1 * sizeof(sljit_sw))
+/* Two local variables for possessive quantifiers (char1 cannot use them). */
+#define POSSESSIVE0 (2 * sizeof(sljit_sw))
+#define POSSESSIVE1 (3 * sizeof(sljit_sw))
+/* Max limit of recursions. */
+#define LIMIT_MATCH (4 * sizeof(sljit_sw))
+/* The output vector is stored on the stack, and contains pointers
+to characters. The vector data is divided into two groups: the first
+group contains the start / end character pointers, and the second is
+the start pointers when the end of the capturing group has not yet reached. */
+#define OVECTOR_START (common->ovector_start)
+#define OVECTOR(i) (OVECTOR_START + (i) * (sljit_sw)sizeof(sljit_sw))
+#define OVECTOR_PRIV(i) (common->cbra_ptr + (i) * (sljit_sw)sizeof(sljit_sw))
+#define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start])
+
+#if defined COMPILE_PCRE8
+#define MOV_UCHAR SLJIT_MOV_UB
+#define MOVU_UCHAR SLJIT_MOVU_UB
+#elif defined COMPILE_PCRE16
+#define MOV_UCHAR SLJIT_MOV_UH
+#define MOVU_UCHAR SLJIT_MOVU_UH
+#elif defined COMPILE_PCRE32
+#define MOV_UCHAR SLJIT_MOV_UI
+#define MOVU_UCHAR SLJIT_MOVU_UI
+#else
+#error Unsupported compiling mode
+#endif
+
+/* Shortcuts. */
+#define DEFINE_COMPILER \
+ struct sljit_compiler *compiler = common->compiler
+#define OP1(op, dst, dstw, src, srcw) \
+ sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw))
+#define OP2(op, dst, dstw, src1, src1w, src2, src2w) \
+ sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w))
+#define LABEL() \
+ sljit_emit_label(compiler)
+#define JUMP(type) \
+ sljit_emit_jump(compiler, (type))
+#define JUMPTO(type, label) \
+ sljit_set_label(sljit_emit_jump(compiler, (type)), (label))
+#define JUMPHERE(jump) \
+ sljit_set_label((jump), sljit_emit_label(compiler))
+#define SET_LABEL(jump, label) \
+ sljit_set_label((jump), (label))
+#define CMP(type, src1, src1w, src2, src2w) \
+ sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w))
+#define CMPTO(type, src1, src1w, src2, src2w, label) \
+ sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))
+#define OP_FLAGS(op, dst, dstw, src, srcw, type) \
+ sljit_emit_op_flags(compiler, (op), (dst), (dstw), (src), (srcw), (type))
+#define GET_LOCAL_BASE(dst, dstw, offset) \
+ sljit_get_local_base(compiler, (dst), (dstw), (offset))
+
+#define READ_CHAR_MAX 0x7fffffff
+
+static pcre_uchar* bracketend(pcre_uchar* cc)
+{
+SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND));
+do cc += GET(cc, 1); while (*cc == OP_ALT);
+SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);
+cc += 1 + LINK_SIZE;
+return cc;
+}
+
+static int no_alternatives(pcre_uchar* cc)
+{
+int count = 0;
+SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND));
+do
+ {
+ cc += GET(cc, 1);
+ count++;
+ }
+while (*cc == OP_ALT);
+SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);
+return count;
+}
+
+static int ones_in_half_byte[16] = {
+ /* 0 */ 0, 1, 1, 2, /* 4 */ 1, 2, 2, 3,
+ /* 8 */ 1, 2, 2, 3, /* 12 */ 2, 3, 3, 4
+};
+
+/* Functions whose might need modification for all new supported opcodes:
+ next_opcode
+ check_opcode_types
+ set_private_data_ptrs
+ get_framesize
+ init_frame
+ get_private_data_copy_length
+ copy_private_data
+ compile_matchingpath
+ compile_backtrackingpath
+*/
+
+static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc)
+{
+SLJIT_UNUSED_ARG(common);
+switch(*cc)
+ {
+ case OP_SOD:
+ case OP_SOM:
+ case OP_SET_SOM:
+ case OP_NOT_WORD_BOUNDARY:
+ case OP_WORD_BOUNDARY:
+ case OP_NOT_DIGIT:
+ case OP_DIGIT:
+ case OP_NOT_WHITESPACE:
+ case OP_WHITESPACE:
+ case OP_NOT_WORDCHAR:
+ case OP_WORDCHAR:
+ case OP_ANY:
+ case OP_ALLANY:
+ case OP_NOTPROP:
+ case OP_PROP:
+ case OP_ANYNL:
+ case OP_NOT_HSPACE:
+ case OP_HSPACE:
+ case OP_NOT_VSPACE:
+ case OP_VSPACE:
+ case OP_EXTUNI:
+ case OP_EODN:
+ case OP_EOD:
+ case OP_CIRC:
+ case OP_CIRCM:
+ case OP_DOLL:
+ case OP_DOLLM:
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ case OP_CRPOSSTAR:
+ case OP_CRPOSPLUS:
+ case OP_CRPOSQUERY:
+ case OP_CRPOSRANGE:
+ case OP_CLASS:
+ case OP_NCLASS:
+ case OP_REF:
+ case OP_REFI:
+ case OP_DNREF:
+ case OP_DNREFI:
+ case OP_RECURSE:
+ case OP_CALLOUT:
+ case OP_ALT:
+ case OP_KET:
+ case OP_KETRMAX:
+ case OP_KETRMIN:
+ case OP_KETRPOS:
+ case OP_REVERSE:
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ case OP_BRA:
+ case OP_BRAPOS:
+ case OP_CBRA:
+ case OP_CBRAPOS:
+ case OP_COND:
+ case OP_SBRA:
+ case OP_SBRAPOS:
+ case OP_SCBRA:
+ case OP_SCBRAPOS:
+ case OP_SCOND:
+ case OP_CREF:
+ case OP_DNCREF:
+ case OP_RREF:
+ case OP_DNRREF:
+ case OP_DEF:
+ case OP_BRAZERO:
+ case OP_BRAMINZERO:
+ case OP_BRAPOSZERO:
+ case OP_PRUNE:
+ case OP_SKIP:
+ case OP_THEN:
+ case OP_COMMIT:
+ case OP_FAIL:
+ case OP_ACCEPT:
+ case OP_ASSERT_ACCEPT:
+ case OP_CLOSE:
+ case OP_SKIPZERO:
+ return cc + PRIV(OP_lengths)[*cc];
+
+ case OP_CHAR:
+ case OP_CHARI:
+ case OP_NOT:
+ case OP_NOTI:
+ case OP_STAR:
+ case OP_MINSTAR:
+ case OP_PLUS:
+ case OP_MINPLUS:
+ case OP_QUERY:
+ case OP_MINQUERY:
+ case OP_UPTO:
+ case OP_MINUPTO:
+ case OP_EXACT:
+ case OP_POSSTAR:
+ case OP_POSPLUS:
+ case OP_POSQUERY:
+ case OP_POSUPTO:
+ case OP_STARI:
+ case OP_MINSTARI:
+ case OP_PLUSI:
+ case OP_MINPLUSI:
+ case OP_QUERYI:
+ case OP_MINQUERYI:
+ case OP_UPTOI:
+ case OP_MINUPTOI:
+ case OP_EXACTI:
+ case OP_POSSTARI:
+ case OP_POSPLUSI:
+ case OP_POSQUERYI:
+ case OP_POSUPTOI:
+ case OP_NOTSTAR:
+ case OP_NOTMINSTAR:
+ case OP_NOTPLUS:
+ case OP_NOTMINPLUS:
+ case OP_NOTQUERY:
+ case OP_NOTMINQUERY:
+ case OP_NOTUPTO:
+ case OP_NOTMINUPTO:
+ case OP_NOTEXACT:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSUPTO:
+ case OP_NOTSTARI:
+ case OP_NOTMINSTARI:
+ case OP_NOTPLUSI:
+ case OP_NOTMINPLUSI:
+ case OP_NOTQUERYI:
+ case OP_NOTMINQUERYI:
+ case OP_NOTUPTOI:
+ case OP_NOTMINUPTOI:
+ case OP_NOTEXACTI:
+ case OP_NOTPOSSTARI:
+ case OP_NOTPOSPLUSI:
+ case OP_NOTPOSQUERYI:
+ case OP_NOTPOSUPTOI:
+ cc += PRIV(OP_lengths)[*cc];
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ return cc;
+
+ /* Special cases. */
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ case OP_TYPEEXACT:
+ case OP_TYPEPOSSTAR:
+ case OP_TYPEPOSPLUS:
+ case OP_TYPEPOSQUERY:
+ case OP_TYPEPOSUPTO:
+ return cc + PRIV(OP_lengths)[*cc] - 1;
+
+ case OP_ANYBYTE:
+#ifdef SUPPORT_UTF
+ if (common->utf) return NULL;
+#endif
+ return cc + 1;
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+ return cc + GET(cc, 1);
+#endif
+
+ case OP_MARK:
+ case OP_PRUNE_ARG:
+ case OP_SKIP_ARG:
+ case OP_THEN_ARG:
+ return cc + 1 + 2 + cc[1];
+
+ default:
+ /* All opcodes are supported now! */
+ SLJIT_ASSERT_STOP();
+ return NULL;
+ }
+}
+
+static BOOL check_opcode_types(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)
+{
+int count;
+pcre_uchar *slot;
+
+/* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
+while (cc < ccend)
+ {
+ switch(*cc)
+ {
+ case OP_SET_SOM:
+ common->has_set_som = TRUE;
+ common->might_be_empty = TRUE;
+ cc += 1;
+ break;
+
+ case OP_REF:
+ case OP_REFI:
+ common->optimized_cbracket[GET2(cc, 1)] = 0;
+ cc += 1 + IMM2_SIZE;
+ break;
+
+ case OP_BRA:
+ case OP_CBRA:
+ case OP_SBRA:
+ case OP_SCBRA:
+ count = no_alternatives(cc);
+ if (count > 4)
+ common->read_only_data_size += count * sizeof(sljit_uw);
+ cc += 1 + LINK_SIZE + (*cc == OP_CBRA || *cc == OP_SCBRA ? IMM2_SIZE : 0);
+ break;
+
+ case OP_CBRAPOS:
+ case OP_SCBRAPOS:
+ common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0;
+ cc += 1 + LINK_SIZE + IMM2_SIZE;
+ break;
+
+ case OP_COND:
+ case OP_SCOND:
+ /* Only AUTO_CALLOUT can insert this opcode. We do
+ not intend to support this case. */
+ if (cc[1 + LINK_SIZE] == OP_CALLOUT)
+ return FALSE;
+ cc += 1 + LINK_SIZE;
+ break;
+
+ case OP_CREF:
+ common->optimized_cbracket[GET2(cc, 1)] = 0;
+ cc += 1 + IMM2_SIZE;
+ break;
+
+ case OP_DNREF:
+ case OP_DNREFI:
+ case OP_DNCREF:
+ count = GET2(cc, 1 + IMM2_SIZE);
+ slot = common->name_table + GET2(cc, 1) * common->name_entry_size;
+ while (count-- > 0)
+ {
+ common->optimized_cbracket[GET2(slot, 0)] = 0;
+ slot += common->name_entry_size;
+ }
+ cc += 1 + 2 * IMM2_SIZE;
+ break;
+
+ case OP_RECURSE:
+ /* Set its value only once. */
+ if (common->recursive_head_ptr == 0)
+ {
+ common->recursive_head_ptr = common->ovector_start;
+ common->ovector_start += sizeof(sljit_sw);
+ }
+ cc += 1 + LINK_SIZE;
+ break;
+
+ case OP_CALLOUT:
+ if (common->capture_last_ptr == 0)
+ {
+ common->capture_last_ptr = common->ovector_start;
+ common->ovector_start += sizeof(sljit_sw);
+ }
+ cc += 2 + 2 * LINK_SIZE;
+ break;
+
+ case OP_THEN_ARG:
+ common->has_then = TRUE;
+ common->control_head_ptr = 1;
+ /* Fall through. */
+
+ case OP_PRUNE_ARG:
+ common->needs_start_ptr = TRUE;
+ /* Fall through. */
+
+ case OP_MARK:
+ if (common->mark_ptr == 0)
+ {
+ common->mark_ptr = common->ovector_start;
+ common->ovector_start += sizeof(sljit_sw);
+ }
+ cc += 1 + 2 + cc[1];
+ break;
+
+ case OP_THEN:
+ common->has_then = TRUE;
+ common->control_head_ptr = 1;
+ /* Fall through. */
+
+ case OP_PRUNE:
+ case OP_SKIP:
+ common->needs_start_ptr = TRUE;
+ cc += 1;
+ break;
+
+ case OP_SKIP_ARG:
+ common->control_head_ptr = 1;
+ common->has_skip_arg = TRUE;
+ cc += 1 + 2 + cc[1];
+ break;
+
+ default:
+ cc = next_opcode(common, cc);
+ if (cc == NULL)
+ return FALSE;
+ break;
+ }
+ }
+return TRUE;
+}
+
+static int get_class_iterator_size(pcre_uchar *cc)
+{
+switch(*cc)
+ {
+ case OP_CRSTAR:
+ case OP_CRPLUS:
+ return 2;
+
+ case OP_CRMINSTAR:
+ case OP_CRMINPLUS:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ return 1;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ if (GET2(cc, 1) == GET2(cc, 1 + IMM2_SIZE))
+ return 0;
+ return 2;
+
+ default:
+ return 0;
+ }
+}
+
+static BOOL detect_repeat(compiler_common *common, pcre_uchar *begin)
+{
+pcre_uchar *end = bracketend(begin);
+pcre_uchar *next;
+pcre_uchar *next_end;
+pcre_uchar *max_end;
+pcre_uchar type;
+sljit_sw length = end - begin;
+int min, max, i;
+
+/* Detect fixed iterations first. */
+if (end[-(1 + LINK_SIZE)] != OP_KET)
+ return FALSE;
+
+/* Already detected repeat. */
+if (common->private_data_ptrs[end - common->start - LINK_SIZE] != 0)
+ return TRUE;
+
+next = end;
+min = 1;
+while (1)
+ {
+ if (*next != *begin)
+ break;
+ next_end = bracketend(next);
+ if (next_end - next != length || memcmp(begin, next, IN_UCHARS(length)) != 0)
+ break;
+ next = next_end;
+ min++;
+ }
+
+if (min == 2)
+ return FALSE;
+
+max = 0;
+max_end = next;
+if (*next == OP_BRAZERO || *next == OP_BRAMINZERO)
+ {
+ type = *next;
+ while (1)
+ {
+ if (next[0] != type || next[1] != OP_BRA || next[2 + LINK_SIZE] != *begin)
+ break;
+ next_end = bracketend(next + 2 + LINK_SIZE);
+ if (next_end - next != (length + 2 + LINK_SIZE) || memcmp(begin, next + 2 + LINK_SIZE, IN_UCHARS(length)) != 0)
+ break;
+ next = next_end;
+ max++;
+ }
+
+ if (next[0] == type && next[1] == *begin && max >= 1)
+ {
+ next_end = bracketend(next + 1);
+ if (next_end - next == (length + 1) && memcmp(begin, next + 1, IN_UCHARS(length)) == 0)
+ {
+ for (i = 0; i < max; i++, next_end += 1 + LINK_SIZE)
+ if (*next_end != OP_KET)
+ break;
+
+ if (i == max)
+ {
+ common->private_data_ptrs[max_end - common->start - LINK_SIZE] = next_end - max_end;
+ common->private_data_ptrs[max_end - common->start - LINK_SIZE + 1] = (type == OP_BRAZERO) ? OP_UPTO : OP_MINUPTO;
+ /* +2 the original and the last. */
+ common->private_data_ptrs[max_end - common->start - LINK_SIZE + 2] = max + 2;
+ if (min == 1)
+ return TRUE;
+ min--;
+ max_end -= (1 + LINK_SIZE) + GET(max_end, -LINK_SIZE);
+ }
+ }
+ }
+ }
+
+if (min >= 3)
+ {
+ common->private_data_ptrs[end - common->start - LINK_SIZE] = max_end - end;
+ common->private_data_ptrs[end - common->start - LINK_SIZE + 1] = OP_EXACT;
+ common->private_data_ptrs[end - common->start - LINK_SIZE + 2] = min;
+ return TRUE;
+ }
+
+return FALSE;
+}
+
+#define CASE_ITERATOR_PRIVATE_DATA_1 \
+ case OP_MINSTAR: \
+ case OP_MINPLUS: \
+ case OP_QUERY: \
+ case OP_MINQUERY: \
+ case OP_MINSTARI: \
+ case OP_MINPLUSI: \
+ case OP_QUERYI: \
+ case OP_MINQUERYI: \
+ case OP_NOTMINSTAR: \
+ case OP_NOTMINPLUS: \
+ case OP_NOTQUERY: \
+ case OP_NOTMINQUERY: \
+ case OP_NOTMINSTARI: \
+ case OP_NOTMINPLUSI: \
+ case OP_NOTQUERYI: \
+ case OP_NOTMINQUERYI:
+
+#define CASE_ITERATOR_PRIVATE_DATA_2A \
+ case OP_STAR: \
+ case OP_PLUS: \
+ case OP_STARI: \
+ case OP_PLUSI: \
+ case OP_NOTSTAR: \
+ case OP_NOTPLUS: \
+ case OP_NOTSTARI: \
+ case OP_NOTPLUSI:
+
+#define CASE_ITERATOR_PRIVATE_DATA_2B \
+ case OP_UPTO: \
+ case OP_MINUPTO: \
+ case OP_UPTOI: \
+ case OP_MINUPTOI: \
+ case OP_NOTUPTO: \
+ case OP_NOTMINUPTO: \
+ case OP_NOTUPTOI: \
+ case OP_NOTMINUPTOI:
+
+#define CASE_ITERATOR_TYPE_PRIVATE_DATA_1 \
+ case OP_TYPEMINSTAR: \
+ case OP_TYPEMINPLUS: \
+ case OP_TYPEQUERY: \
+ case OP_TYPEMINQUERY:
+
+#define CASE_ITERATOR_TYPE_PRIVATE_DATA_2A \
+ case OP_TYPESTAR: \
+ case OP_TYPEPLUS:
+
+#define CASE_ITERATOR_TYPE_PRIVATE_DATA_2B \
+ case OP_TYPEUPTO: \
+ case OP_TYPEMINUPTO:
+
+static void set_private_data_ptrs(compiler_common *common, int *private_data_start, pcre_uchar *ccend)
+{
+pcre_uchar *cc = common->start;
+pcre_uchar *alternative;
+pcre_uchar *end = NULL;
+int private_data_ptr = *private_data_start;
+int space, size, bracketlen;
+
+while (cc < ccend)
+ {
+ space = 0;
+ size = 0;
+ bracketlen = 0;
+ if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE)
+ return;
+
+ if (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND)
+ if (detect_repeat(common, cc))
+ {
+ /* These brackets are converted to repeats, so no global
+ based single character repeat is allowed. */
+ if (cc >= end)
+ end = bracketend(cc);
+ }
+
+ switch(*cc)
+ {
+ case OP_KET:
+ if (common->private_data_ptrs[cc + 1 - common->start] != 0)
+ {
+ common->private_data_ptrs[cc - common->start] = private_data_ptr;
+ private_data_ptr += sizeof(sljit_sw);
+ cc += common->private_data_ptrs[cc + 1 - common->start];
+ }
+ cc += 1 + LINK_SIZE;
+ break;
+
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ case OP_BRAPOS:
+ case OP_SBRA:
+ case OP_SBRAPOS:
+ case OP_SCOND:
+ common->private_data_ptrs[cc - common->start] = private_data_ptr;
+ private_data_ptr += sizeof(sljit_sw);
+ bracketlen = 1 + LINK_SIZE;
+ break;
+
+ case OP_CBRAPOS:
+ case OP_SCBRAPOS:
+ common->private_data_ptrs[cc - common->start] = private_data_ptr;
+ private_data_ptr += sizeof(sljit_sw);
+ bracketlen = 1 + LINK_SIZE + IMM2_SIZE;
+ break;
+
+ case OP_COND:
+ /* Might be a hidden SCOND. */
+ alternative = cc + GET(cc, 1);
+ if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
+ {
+ common->private_data_ptrs[cc - common->start] = private_data_ptr;
+ private_data_ptr += sizeof(sljit_sw);
+ }
+ bracketlen = 1 + LINK_SIZE;
+ break;
+
+ case OP_BRA:
+ bracketlen = 1 + LINK_SIZE;
+ break;
+
+ case OP_CBRA:
+ case OP_SCBRA:
+ bracketlen = 1 + LINK_SIZE + IMM2_SIZE;
+ break;
+
+ CASE_ITERATOR_PRIVATE_DATA_1
+ space = 1;
+ size = -2;
+ break;
+
+ CASE_ITERATOR_PRIVATE_DATA_2A
+ space = 2;
+ size = -2;
+ break;
+
+ CASE_ITERATOR_PRIVATE_DATA_2B
+ space = 2;
+ size = -(2 + IMM2_SIZE);
+ break;
+
+ CASE_ITERATOR_TYPE_PRIVATE_DATA_1
+ space = 1;
+ size = 1;
+ break;
+
+ CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
+ if (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI)
+ space = 2;
+ size = 1;
+ break;
+
+ CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
+ if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI)
+ space = 2;
+ size = 1 + IMM2_SIZE;
+ break;
+
+ case OP_CLASS:
+ case OP_NCLASS:
+ size += 1 + 32 / sizeof(pcre_uchar);
+ space = get_class_iterator_size(cc + size);
+ break;
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+ size = GET(cc, 1);
+ space = get_class_iterator_size(cc + size);
+ break;
+#endif
+
+ default:
+ cc = next_opcode(common, cc);
+ SLJIT_ASSERT(cc != NULL);
+ break;
+ }
+
+ /* Character iterators, which are not inside a repeated bracket,
+ gets a private slot instead of allocating it on the stack. */
+ if (space > 0 && cc >= end)
+ {
+ common->private_data_ptrs[cc - common->start] = private_data_ptr;
+ private_data_ptr += sizeof(sljit_sw) * space;
+ }
+
+ if (size != 0)
+ {
+ if (size < 0)
+ {
+ cc += -size;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ }
+ else
+ cc += size;
+ }
+
+ if (bracketlen > 0)
+ {
+ if (cc >= end)
+ {
+ end = bracketend(cc);
+ if (end[-1 - LINK_SIZE] == OP_KET)
+ end = NULL;
+ }
+ cc += bracketlen;
+ }
+ }
+*private_data_start = private_data_ptr;
+}
+
+/* Returns with a frame_types (always < 0) if no need for frame. */
+static int get_framesize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL recursive, BOOL* needs_control_head)
+{
+int length = 0;
+int possessive = 0;
+BOOL stack_restore = FALSE;
+BOOL setsom_found = recursive;
+BOOL setmark_found = recursive;
+/* The last capture is a local variable even for recursions. */
+BOOL capture_last_found = FALSE;
+
+#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD
+SLJIT_ASSERT(common->control_head_ptr != 0);
+*needs_control_head = TRUE;
+#else
+*needs_control_head = FALSE;
+#endif
+
+if (ccend == NULL)
+ {
+ ccend = bracketend(cc) - (1 + LINK_SIZE);
+ if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))
+ {
+ possessive = length = (common->capture_last_ptr != 0) ? 5 : 3;
+ /* This is correct regardless of common->capture_last_ptr. */
+ capture_last_found = TRUE;
+ }
+ cc = next_opcode(common, cc);
+ }
+
+SLJIT_ASSERT(cc != NULL);
+while (cc < ccend)
+ switch(*cc)
+ {
+ case OP_SET_SOM:
+ SLJIT_ASSERT(common->has_set_som);
+ stack_restore = TRUE;
+ if (!setsom_found)
+ {
+ length += 2;
+ setsom_found = TRUE;
+ }
+ cc += 1;
+ break;
+
+ case OP_MARK:
+ case OP_PRUNE_ARG:
+ case OP_THEN_ARG:
+ SLJIT_ASSERT(common->mark_ptr != 0);
+ stack_restore = TRUE;
+ if (!setmark_found)
+ {
+ length += 2;
+ setmark_found = TRUE;
+ }
+ if (common->control_head_ptr != 0)
+ *needs_control_head = TRUE;
+ cc += 1 + 2 + cc[1];
+ break;
+
+ case OP_RECURSE:
+ stack_restore = TRUE;
+ if (common->has_set_som && !setsom_found)
+ {
+ length += 2;
+ setsom_found = TRUE;
+ }
+ if (common->mark_ptr != 0 && !setmark_found)
+ {
+ length += 2;
+ setmark_found = TRUE;
+ }
+ if (common->capture_last_ptr != 0 && !capture_last_found)
+ {
+ length += 2;
+ capture_last_found = TRUE;
+ }
+ cc += 1 + LINK_SIZE;
+ break;
+
+ case OP_CBRA:
+ case OP_CBRAPOS:
+ case OP_SCBRA:
+ case OP_SCBRAPOS:
+ stack_restore = TRUE;
+ if (common->capture_last_ptr != 0 && !capture_last_found)
+ {
+ length += 2;
+ capture_last_found = TRUE;
+ }
+ length += 3;
+ cc += 1 + LINK_SIZE + IMM2_SIZE;
+ break;
+
+ default:
+ stack_restore = TRUE;
+ /* Fall through. */
+
+ case OP_NOT_WORD_BOUNDARY:
+ case OP_WORD_BOUNDARY:
+ case OP_NOT_DIGIT:
+ case OP_DIGIT:
+ case OP_NOT_WHITESPACE:
+ case OP_WHITESPACE:
+ case OP_NOT_WORDCHAR:
+ case OP_WORDCHAR:
+ case OP_ANY:
+ case OP_ALLANY:
+ case OP_ANYBYTE:
+ case OP_NOTPROP:
+ case OP_PROP:
+ case OP_ANYNL:
+ case OP_NOT_HSPACE:
+ case OP_HSPACE:
+ case OP_NOT_VSPACE:
+ case OP_VSPACE:
+ case OP_EXTUNI:
+ case OP_EODN:
+ case OP_EOD:
+ case OP_CIRC:
+ case OP_CIRCM:
+ case OP_DOLL:
+ case OP_DOLLM:
+ case OP_CHAR:
+ case OP_CHARI:
+ case OP_NOT:
+ case OP_NOTI:
+
+ case OP_EXACT:
+ case OP_POSSTAR:
+ case OP_POSPLUS:
+ case OP_POSQUERY:
+ case OP_POSUPTO:
+
+ case OP_EXACTI:
+ case OP_POSSTARI:
+ case OP_POSPLUSI:
+ case OP_POSQUERYI:
+ case OP_POSUPTOI:
+
+ case OP_NOTEXACT:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSUPTO:
+
+ case OP_NOTEXACTI:
+ case OP_NOTPOSSTARI:
+ case OP_NOTPOSPLUSI:
+ case OP_NOTPOSQUERYI:
+ case OP_NOTPOSUPTOI:
+
+ case OP_TYPEEXACT:
+ case OP_TYPEPOSSTAR:
+ case OP_TYPEPOSPLUS:
+ case OP_TYPEPOSQUERY:
+ case OP_TYPEPOSUPTO:
+
+ case OP_CLASS:
+ case OP_NCLASS:
+ case OP_XCLASS:
+
+ cc = next_opcode(common, cc);
+ SLJIT_ASSERT(cc != NULL);
+ break;
+ }
+
+/* Possessive quantifiers can use a special case. */
+if (SLJIT_UNLIKELY(possessive == length))
+ return stack_restore ? no_frame : no_stack;
+
+if (length > 0)
+ return length + 1;
+return stack_restore ? no_frame : no_stack;
+}
+
+static void init_frame(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, int stackpos, int stacktop, BOOL recursive)
+{
+DEFINE_COMPILER;
+BOOL setsom_found = recursive;
+BOOL setmark_found = recursive;
+/* The last capture is a local variable even for recursions. */
+BOOL capture_last_found = FALSE;
+int offset;
+
+/* >= 1 + shortest item size (2) */
+SLJIT_UNUSED_ARG(stacktop);
+SLJIT_ASSERT(stackpos >= stacktop + 2);
+
+stackpos = STACK(stackpos);
+if (ccend == NULL)
+ {
+ ccend = bracketend(cc) - (1 + LINK_SIZE);
+ if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS))
+ cc = next_opcode(common, cc);
+ }
+
+SLJIT_ASSERT(cc != NULL);
+while (cc < ccend)
+ switch(*cc)
+ {
+ case OP_SET_SOM:
+ SLJIT_ASSERT(common->has_set_som);
+ if (!setsom_found)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0));
+ stackpos += (int)sizeof(sljit_sw);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
+ stackpos += (int)sizeof(sljit_sw);
+ setsom_found = TRUE;
+ }
+ cc += 1;
+ break;
+
+ case OP_MARK:
+ case OP_PRUNE_ARG:
+ case OP_THEN_ARG:
+ SLJIT_ASSERT(common->mark_ptr != 0);
+ if (!setmark_found)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr);
+ stackpos += (int)sizeof(sljit_sw);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
+ stackpos += (int)sizeof(sljit_sw);
+ setmark_found = TRUE;
+ }
+ cc += 1 + 2 + cc[1];
+ break;
+
+ case OP_RECURSE:
+ if (common->has_set_som && !setsom_found)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0));
+ stackpos += (int)sizeof(sljit_sw);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
+ stackpos += (int)sizeof(sljit_sw);
+ setsom_found = TRUE;
+ }
+ if (common->mark_ptr != 0 && !setmark_found)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr);
+ stackpos += (int)sizeof(sljit_sw);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
+ stackpos += (int)sizeof(sljit_sw);
+ setmark_found = TRUE;
+ }
+ if (common->capture_last_ptr != 0 && !capture_last_found)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr);
+ stackpos += (int)sizeof(sljit_sw);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
+ stackpos += (int)sizeof(sljit_sw);
+ capture_last_found = TRUE;
+ }
+ cc += 1 + LINK_SIZE;
+ break;
+
+ case OP_CBRA:
+ case OP_CBRAPOS:
+ case OP_SCBRA:
+ case OP_SCBRAPOS:
+ if (common->capture_last_ptr != 0 && !capture_last_found)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr);
+ stackpos += (int)sizeof(sljit_sw);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
+ stackpos += (int)sizeof(sljit_sw);
+ capture_last_found = TRUE;
+ }
+ offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));
+ stackpos += (int)sizeof(sljit_sw);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
+ stackpos += (int)sizeof(sljit_sw);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);
+ stackpos += (int)sizeof(sljit_sw);
+
+ cc += 1 + LINK_SIZE + IMM2_SIZE;
+ break;
+
+ default:
+ cc = next_opcode(common, cc);
+ SLJIT_ASSERT(cc != NULL);
+ break;
+ }
+
+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, 0);
+SLJIT_ASSERT(stackpos == STACK(stacktop));
+}
+
+static SLJIT_INLINE int get_private_data_copy_length(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL needs_control_head)
+{
+int private_data_length = needs_control_head ? 3 : 2;
+int size;
+pcre_uchar *alternative;
+/* Calculate the sum of the private machine words. */
+while (cc < ccend)
+ {
+ size = 0;
+ switch(*cc)
+ {
+ case OP_KET:
+ if (PRIVATE_DATA(cc) != 0)
+ private_data_length++;
+ cc += 1 + LINK_SIZE;
+ break;
+
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ case OP_BRAPOS:
+ case OP_SBRA:
+ case OP_SBRAPOS:
+ case OP_SCOND:
+ private_data_length++;
+ cc += 1 + LINK_SIZE;
+ break;
+
+ case OP_CBRA:
+ case OP_SCBRA:
+ if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
+ private_data_length++;
+ cc += 1 + LINK_SIZE + IMM2_SIZE;
+ break;
+
+ case OP_CBRAPOS:
+ case OP_SCBRAPOS:
+ private_data_length += 2;
+ cc += 1 + LINK_SIZE + IMM2_SIZE;
+ break;
+
+ case OP_COND:
+ /* Might be a hidden SCOND. */
+ alternative = cc + GET(cc, 1);
+ if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
+ private_data_length++;
+ cc += 1 + LINK_SIZE;
+ break;
+
+ CASE_ITERATOR_PRIVATE_DATA_1
+ if (PRIVATE_DATA(cc))
+ private_data_length++;
+ cc += 2;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ break;
+
+ CASE_ITERATOR_PRIVATE_DATA_2A
+ if (PRIVATE_DATA(cc))
+ private_data_length += 2;
+ cc += 2;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ break;
+
+ CASE_ITERATOR_PRIVATE_DATA_2B
+ if (PRIVATE_DATA(cc))
+ private_data_length += 2;
+ cc += 2 + IMM2_SIZE;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ break;
+
+ CASE_ITERATOR_TYPE_PRIVATE_DATA_1
+ if (PRIVATE_DATA(cc))
+ private_data_length++;
+ cc += 1;
+ break;
+
+ CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
+ if (PRIVATE_DATA(cc))
+ private_data_length += 2;
+ cc += 1;
+ break;
+
+ CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
+ if (PRIVATE_DATA(cc))
+ private_data_length += 2;
+ cc += 1 + IMM2_SIZE;
+ break;
+
+ case OP_CLASS:
+ case OP_NCLASS:
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+ size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(pcre_uchar);
+#else
+ size = 1 + 32 / (int)sizeof(pcre_uchar);
+#endif
+ if (PRIVATE_DATA(cc))
+ private_data_length += get_class_iterator_size(cc + size);
+ cc += size;
+ break;
+
+ default:
+ cc = next_opcode(common, cc);
+ SLJIT_ASSERT(cc != NULL);
+ break;
+ }
+ }
+SLJIT_ASSERT(cc == ccend);
+return private_data_length;
+}
+
+static void copy_private_data(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend,
+ BOOL save, int stackptr, int stacktop, BOOL needs_control_head)
+{
+DEFINE_COMPILER;
+int srcw[2];
+int count, size;
+BOOL tmp1next = TRUE;
+BOOL tmp1empty = TRUE;
+BOOL tmp2empty = TRUE;
+pcre_uchar *alternative;
+enum {
+ start,
+ loop,
+ end
+} status;
+
+status = save ? start : loop;
+stackptr = STACK(stackptr - 2);
+stacktop = STACK(stacktop - 1);
+
+if (!save)
+ {
+ stackptr += (needs_control_head ? 2 : 1) * sizeof(sljit_sw);
+ if (stackptr < stacktop)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
+ stackptr += sizeof(sljit_sw);
+ tmp1empty = FALSE;
+ }
+ if (stackptr < stacktop)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
+ stackptr += sizeof(sljit_sw);
+ tmp2empty = FALSE;
+ }
+ /* The tmp1next must be TRUE in either way. */
+ }
+
+do
+ {
+ count = 0;
+ switch(status)
+ {
+ case start:
+ SLJIT_ASSERT(save && common->recursive_head_ptr != 0);
+ count = 1;
+ srcw[0] = common->recursive_head_ptr;
+ if (needs_control_head)
+ {
+ SLJIT_ASSERT(common->control_head_ptr != 0);
+ count = 2;
+ srcw[1] = common->control_head_ptr;
+ }
+ status = loop;
+ break;
+
+ case loop:
+ if (cc >= ccend)
+ {
+ status = end;
+ break;
+ }
+
+ switch(*cc)
+ {
+ case OP_KET:
+ if (PRIVATE_DATA(cc) != 0)
+ {
+ count = 1;
+ srcw[0] = PRIVATE_DATA(cc);
+ }
+ cc += 1 + LINK_SIZE;
+ break;
+
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ case OP_BRAPOS:
+ case OP_SBRA:
+ case OP_SBRAPOS:
+ case OP_SCOND:
+ count = 1;
+ srcw[0] = PRIVATE_DATA(cc);
+ SLJIT_ASSERT(srcw[0] != 0);
+ cc += 1 + LINK_SIZE;
+ break;
+
+ case OP_CBRA:
+ case OP_SCBRA:
+ if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
+ {
+ count = 1;
+ srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
+ }
+ cc += 1 + LINK_SIZE + IMM2_SIZE;
+ break;
+
+ case OP_CBRAPOS:
+ case OP_SCBRAPOS:
+ count = 2;
+ srcw[0] = PRIVATE_DATA(cc);
+ srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
+ SLJIT_ASSERT(srcw[0] != 0 && srcw[1] != 0);
+ cc += 1 + LINK_SIZE + IMM2_SIZE;
+ break;
+
+ case OP_COND:
+ /* Might be a hidden SCOND. */
+ alternative = cc + GET(cc, 1);
+ if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
+ {
+ count = 1;
+ srcw[0] = PRIVATE_DATA(cc);
+ SLJIT_ASSERT(srcw[0] != 0);
+ }
+ cc += 1 + LINK_SIZE;
+ break;
+
+ CASE_ITERATOR_PRIVATE_DATA_1
+ if (PRIVATE_DATA(cc))
+ {
+ count = 1;
+ srcw[0] = PRIVATE_DATA(cc);
+ }
+ cc += 2;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ break;
+
+ CASE_ITERATOR_PRIVATE_DATA_2A
+ if (PRIVATE_DATA(cc))
+ {
+ count = 2;
+ srcw[0] = PRIVATE_DATA(cc);
+ srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
+ }
+ cc += 2;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ break;
+
+ CASE_ITERATOR_PRIVATE_DATA_2B
+ if (PRIVATE_DATA(cc))
+ {
+ count = 2;
+ srcw[0] = PRIVATE_DATA(cc);
+ srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
+ }
+ cc += 2 + IMM2_SIZE;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ break;
+
+ CASE_ITERATOR_TYPE_PRIVATE_DATA_1
+ if (PRIVATE_DATA(cc))
+ {
+ count = 1;
+ srcw[0] = PRIVATE_DATA(cc);
+ }
+ cc += 1;
+ break;
+
+ CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
+ if (PRIVATE_DATA(cc))
+ {
+ count = 2;
+ srcw[0] = PRIVATE_DATA(cc);
+ srcw[1] = srcw[0] + sizeof(sljit_sw);
+ }
+ cc += 1;
+ break;
+
+ CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
+ if (PRIVATE_DATA(cc))
+ {
+ count = 2;
+ srcw[0] = PRIVATE_DATA(cc);
+ srcw[1] = srcw[0] + sizeof(sljit_sw);
+ }
+ cc += 1 + IMM2_SIZE;
+ break;
+
+ case OP_CLASS:
+ case OP_NCLASS:
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+ size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(pcre_uchar);
+#else
+ size = 1 + 32 / (int)sizeof(pcre_uchar);
+#endif
+ if (PRIVATE_DATA(cc))
+ switch(get_class_iterator_size(cc + size))
+ {
+ case 1:
+ count = 1;
+ srcw[0] = PRIVATE_DATA(cc);
+ break;
+
+ case 2:
+ count = 2;
+ srcw[0] = PRIVATE_DATA(cc);
+ srcw[1] = srcw[0] + sizeof(sljit_sw);
+ break;
+
+ default:
+ SLJIT_ASSERT_STOP();
+ break;
+ }
+ cc += size;
+ break;
+
+ default:
+ cc = next_opcode(common, cc);
+ SLJIT_ASSERT(cc != NULL);
+ break;
+ }
+ break;
+
+ case end:
+ SLJIT_ASSERT_STOP();
+ break;
+ }
+
+ while (count > 0)
+ {
+ count--;
+ if (save)
+ {
+ if (tmp1next)
+ {
+ if (!tmp1empty)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
+ stackptr += sizeof(sljit_sw);
+ }
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]);
+ tmp1empty = FALSE;
+ tmp1next = FALSE;
+ }
+ else
+ {
+ if (!tmp2empty)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
+ stackptr += sizeof(sljit_sw);
+ }
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]);
+ tmp2empty = FALSE;
+ tmp1next = TRUE;
+ }
+ }
+ else
+ {
+ if (tmp1next)
+ {
+ SLJIT_ASSERT(!tmp1empty);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP1, 0);
+ tmp1empty = stackptr >= stacktop;
+ if (!tmp1empty)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
+ stackptr += sizeof(sljit_sw);
+ }
+ tmp1next = FALSE;
+ }
+ else
+ {
+ SLJIT_ASSERT(!tmp2empty);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP2, 0);
+ tmp2empty = stackptr >= stacktop;
+ if (!tmp2empty)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
+ stackptr += sizeof(sljit_sw);
+ }
+ tmp1next = TRUE;
+ }
+ }
+ }
+ }
+while (status != end);
+
+if (save)
+ {
+ if (tmp1next)
+ {
+ if (!tmp1empty)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
+ stackptr += sizeof(sljit_sw);
+ }
+ if (!tmp2empty)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
+ stackptr += sizeof(sljit_sw);
+ }
+ }
+ else
+ {
+ if (!tmp2empty)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
+ stackptr += sizeof(sljit_sw);
+ }
+ if (!tmp1empty)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
+ stackptr += sizeof(sljit_sw);
+ }
+ }
+ }
+SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty)));
+}
+
+static SLJIT_INLINE pcre_uchar *set_then_offsets(compiler_common *common, pcre_uchar *cc, pcre_uint8 *current_offset)
+{
+pcre_uchar *end = bracketend(cc);
+BOOL has_alternatives = cc[GET(cc, 1)] == OP_ALT;
+
+/* Assert captures then. */
+if (*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT)
+ current_offset = NULL;
+/* Conditional block does not. */
+if (*cc == OP_COND || *cc == OP_SCOND)
+ has_alternatives = FALSE;
+
+cc = next_opcode(common, cc);
+if (has_alternatives)
+ current_offset = common->then_offsets + (cc - common->start);
+
+while (cc < end)
+ {
+ if ((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND))
+ cc = set_then_offsets(common, cc, current_offset);
+ else
+ {
+ if (*cc == OP_ALT && has_alternatives)
+ current_offset = common->then_offsets + (cc + 1 + LINK_SIZE - common->start);
+ if (*cc >= OP_THEN && *cc <= OP_THEN_ARG && current_offset != NULL)
+ *current_offset = 1;
+ cc = next_opcode(common, cc);
+ }
+ }
+
+return end;
+}
+
+#undef CASE_ITERATOR_PRIVATE_DATA_1
+#undef CASE_ITERATOR_PRIVATE_DATA_2A
+#undef CASE_ITERATOR_PRIVATE_DATA_2B
+#undef CASE_ITERATOR_TYPE_PRIVATE_DATA_1
+#undef CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
+#undef CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
+
+static SLJIT_INLINE BOOL is_powerof2(unsigned int value)
+{
+return (value & (value - 1)) == 0;
+}
+
+static SLJIT_INLINE void set_jumps(jump_list *list, struct sljit_label *label)
+{
+while (list)
+ {
+ /* sljit_set_label is clever enough to do nothing
+ if either the jump or the label is NULL. */
+ SET_LABEL(list->jump, label);
+ list = list->next;
+ }
+}
+
+static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump* jump)
+{
+jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list));
+if (list_item)
+ {
+ list_item->next = *list;
+ list_item->jump = jump;
+ *list = list_item;
+ }
+}
+
+static void add_stub(compiler_common *common, struct sljit_jump *start)
+{
+DEFINE_COMPILER;
+stub_list* list_item = sljit_alloc_memory(compiler, sizeof(stub_list));
+
+if (list_item)
+ {
+ list_item->start = start;
+ list_item->quit = LABEL();
+ list_item->next = common->stubs;
+ common->stubs = list_item;
+ }
+}
+
+static void flush_stubs(compiler_common *common)
+{
+DEFINE_COMPILER;
+stub_list* list_item = common->stubs;
+
+while (list_item)
+ {
+ JUMPHERE(list_item->start);
+ add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL));
+ JUMPTO(SLJIT_JUMP, list_item->quit);
+ list_item = list_item->next;
+ }
+common->stubs = NULL;
+}
+
+static void add_label_addr(compiler_common *common)
+{
+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->addr = common->read_only_data_ptr;
+label_addr->next = common->label_addrs;
+common->label_addrs = label_addr;
+common->read_only_data_ptr++;
+}
+
+static SLJIT_INLINE void count_match(compiler_common *common)
+{
+DEFINE_COMPILER;
+
+OP2(SLJIT_SUB | SLJIT_SET_E, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1);
+add_jump(compiler, &common->calllimit, JUMP(SLJIT_C_ZERO));
+}
+
+static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)
+{
+/* May destroy all locals and registers except TMP2. */
+DEFINE_COMPILER;
+
+OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
+#ifdef DESTROY_REGISTERS
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345);
+OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
+OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, TMP1, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0);
+#endif
+add_stub(common, CMP(SLJIT_C_GREATER, STACK_TOP, 0, STACK_LIMIT, 0));
+}
+
+static SLJIT_INLINE void free_stack(compiler_common *common, int size)
+{
+DEFINE_COMPILER;
+OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
+}
+
+static SLJIT_INLINE void reset_ovector(compiler_common *common, int length)
+{
+DEFINE_COMPILER;
+struct sljit_label *loop;
+int i;
+
+/* At this point we can freely use all temporary registers. */
+SLJIT_ASSERT(length > 1);
+/* TMP1 returns with begin - 1. */
+OP2(SLJIT_SUB, SLJIT_SCRATCH_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1));
+if (length < 8)
+ {
+ for (i = 1; i < length; i++)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_SCRATCH_REG1, 0);
+ }
+else
+ {
+ GET_LOCAL_BASE(SLJIT_SCRATCH_REG2, 0, OVECTOR_START);
+ OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, length - 1);
+ loop = LABEL();
+ OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_SCRATCH_REG2), sizeof(sljit_sw), SLJIT_SCRATCH_REG1, 0);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 1);
+ JUMPTO(SLJIT_C_NOT_ZERO, loop);
+ }
+}
+
+static SLJIT_INLINE void do_reset_match(compiler_common *common, int length)
+{
+DEFINE_COMPILER;
+struct sljit_label *loop;
+int i;
+
+SLJIT_ASSERT(length > 1);
+/* OVECTOR(1) contains the "string begin - 1" constant. */
+if (length > 2)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
+if (length < 8)
+ {
+ for (i = 2; i < length; i++)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), TMP1, 0);
+ }
+else
+ {
+ GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw));
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);
+ loop = LABEL();
+ OP1(SLJIT_MOVU, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0);
+ OP2(SLJIT_SUB | SLJIT_SET_E, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);
+ JUMPTO(SLJIT_C_NOT_ZERO, loop);
+ }
+
+OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0);
+if (common->mark_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0);
+if (common->control_head_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0);
+OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack));
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr);
+OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base));
+}
+
+static sljit_sw SLJIT_CALL do_search_mark(sljit_sw *current, const pcre_uchar *skip_arg)
+{
+while (current != NULL)
+ {
+ switch (current[-2])
+ {
+ case type_then_trap:
+ break;
+
+ case type_mark:
+ if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[-3]) == 0)
+ return current[-4];
+ break;
+
+ default:
+ SLJIT_ASSERT_STOP();
+ break;
+ }
+ current = (sljit_sw*)current[-1];
+ }
+return -1;
+}
+
+static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)
+{
+DEFINE_COMPILER;
+struct sljit_label *loop;
+struct sljit_jump *early_quit;
+
+/* At this point we can freely use all registers. */
+OP1(SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0);
+
+OP1(SLJIT_MOV, SLJIT_SCRATCH_REG1, 0, ARGUMENTS, 0);
+if (common->mark_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
+OP1(SLJIT_MOV_SI, SLJIT_SCRATCH_REG2, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, offset_count));
+if (common->mark_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_SCRATCH_REG3, 0);
+OP2(SLJIT_SUB, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));
+OP1(SLJIT_MOV, SLJIT_SCRATCH_REG1, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, begin));
+GET_LOCAL_BASE(SLJIT_SAVED_REG1, 0, OVECTOR_START);
+/* Unlikely, but possible */
+early_quit = CMP(SLJIT_C_EQUAL, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, 0);
+loop = LABEL();
+OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), 0, SLJIT_SCRATCH_REG1, 0);
+OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_SAVED_REG1, 0, SLJIT_IMM, sizeof(sljit_sw));
+/* Copy the integer value to the output buffer */
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, UCHAR_SHIFT);
+#endif
+OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG3), sizeof(int), SLJIT_SAVED_REG2, 0);
+OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_SCRATCH_REG2, 0, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, 1);
+JUMPTO(SLJIT_C_NOT_ZERO, loop);
+JUMPHERE(early_quit);
+
+/* Calculate the return value, which is the maximum ovector value. */
+if (topbracket > 1)
+ {
+ GET_LOCAL_BASE(SLJIT_SCRATCH_REG1, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, topbracket + 1);
+
+ /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */
+ loop = LABEL();
+ OP1(SLJIT_MOVU, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), -(2 * (sljit_sw)sizeof(sljit_sw)));
+ OP2(SLJIT_SUB, SLJIT_SCRATCH_REG2, 0, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, 1);
+ CMPTO(SLJIT_C_EQUAL, SLJIT_SCRATCH_REG3, 0, SLJIT_SAVED_REG3, 0, loop);
+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_SCRATCH_REG2, 0);
+ }
+else
+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
+}
+
+static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *quit)
+{
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+
+SLJIT_COMPILE_ASSERT(STR_END == SLJIT_SAVED_REG2, str_end_must_be_saved_reg2);
+SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0
+ && (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0));
+
+OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, ARGUMENTS, 0);
+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL);
+OP1(SLJIT_MOV_SI, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, real_offset_count));
+CMPTO(SLJIT_C_SIG_LESS, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 2, quit);
+
+/* Store match begin and end. */
+OP1(SLJIT_MOV, SLJIT_SAVED_REG1, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, begin));
+OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, offsets));
+
+jump = CMP(SLJIT_C_SIG_LESS, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 3);
+OP2(SLJIT_SUB, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_ptr : (common->hit_start + (int)sizeof(sljit_sw)), SLJIT_SAVED_REG1, 0);
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+OP2(SLJIT_ASHR, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, UCHAR_SHIFT);
+#endif
+OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG2), 2 * sizeof(int), SLJIT_SCRATCH_REG3, 0);
+JUMPHERE(jump);
+
+OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start);
+OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, STR_END, 0, SLJIT_SAVED_REG1, 0);
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, UCHAR_SHIFT);
+#endif
+OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG2), sizeof(int), SLJIT_SAVED_REG2, 0);
+
+OP2(SLJIT_SUB, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_SAVED_REG1, 0);
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+OP2(SLJIT_ASHR, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, UCHAR_SHIFT);
+#endif
+OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG2), 0, SLJIT_SCRATCH_REG3, 0);
+
+JUMPTO(SLJIT_JUMP, quit);
+}
+
+static SLJIT_INLINE void check_start_used_ptr(compiler_common *common)
+{
+/* May destroy TMP1. */
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+
+if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
+ {
+ /* The value of -1 must be kept for start_used_ptr! */
+ OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, 1);
+ /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting
+ is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */
+ jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
+ JUMPHERE(jump);
+ }
+else if (common->mode == JIT_PARTIAL_HARD_COMPILE)
+ {
+ jump = CMP(SLJIT_C_LESS_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
+ JUMPHERE(jump);
+ }
+}
+
+static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar* cc)
+{
+/* Detects if the character has an othercase. */
+unsigned int c;
+
+#ifdef SUPPORT_UTF
+if (common->utf)
+ {
+ GETCHAR(c, cc);
+ if (c > 127)
+ {
+#ifdef SUPPORT_UCP
+ return c != UCD_OTHERCASE(c);
+#else
+ return FALSE;
+#endif
+ }
+#ifndef COMPILE_PCRE8
+ return common->fcc[c] != c;
+#endif
+ }
+else
+#endif
+ c = *cc;
+return MAX_255(c) ? common->fcc[c] != c : FALSE;
+}
+
+static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c)
+{
+/* Returns with the othercase. */
+#ifdef SUPPORT_UTF
+if (common->utf && c > 127)
+ {
+#ifdef SUPPORT_UCP
+ return UCD_OTHERCASE(c);
+#else
+ return c;
+#endif
+ }
+#endif
+return TABLE_GET(c, common->fcc, c);
+}
+
+static unsigned int char_get_othercase_bit(compiler_common *common, pcre_uchar* cc)
+{
+/* Detects if the character and its othercase has only 1 bit difference. */
+unsigned int c, oc, bit;
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+int n;
+#endif
+
+#ifdef SUPPORT_UTF
+if (common->utf)
+ {
+ GETCHAR(c, cc);
+ if (c <= 127)
+ oc = common->fcc[c];
+ else
+ {
+#ifdef SUPPORT_UCP
+ oc = UCD_OTHERCASE(c);
+#else
+ oc = c;
+#endif
+ }
+ }
+else
+ {
+ c = *cc;
+ oc = TABLE_GET(c, common->fcc, c);
+ }
+#else
+c = *cc;
+oc = TABLE_GET(c, common->fcc, c);
+#endif
+
+SLJIT_ASSERT(c != oc);
+
+bit = c ^ oc;
+/* Optimized for English alphabet. */
+if (c <= 127 && bit == 0x20)
+ return (0 << 8) | 0x20;
+
+/* Since c != oc, they must have at least 1 bit difference. */
+if (!is_powerof2(bit))
+ return 0;
+
+#if defined COMPILE_PCRE8
+
+#ifdef SUPPORT_UTF
+if (common->utf && c > 127)
+ {
+ n = GET_EXTRALEN(*cc);
+ while ((bit & 0x3f) == 0)
+ {
+ n--;
+ bit >>= 6;
+ }
+ return (n << 8) | bit;
+ }
+#endif /* SUPPORT_UTF */
+return (0 << 8) | bit;
+
+#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+
+#ifdef SUPPORT_UTF
+if (common->utf && c > 65535)
+ {
+ if (bit >= (1 << 10))
+ bit >>= 10;
+ else
+ return (bit < 256) ? ((2 << 8) | bit) : ((3 << 8) | (bit >> 8));
+ }
+#endif /* SUPPORT_UTF */
+return (bit < 256) ? ((0 << 8) | bit) : ((1 << 8) | (bit >> 8));
+
+#endif /* COMPILE_PCRE[8|16|32] */
+}
+
+static void check_partial(compiler_common *common, BOOL force)
+{
+/* Checks whether a partial matching is occurred. Does not modify registers. */
+DEFINE_COMPILER;
+struct sljit_jump *jump = NULL;
+
+SLJIT_ASSERT(!force || common->mode != JIT_COMPILE);
+
+if (common->mode == JIT_COMPILE)
+ return;
+
+if (!force)
+ jump = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
+else if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
+ jump = CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1);
+
+if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0);
+else
+ {
+ if (common->partialmatchlabel != NULL)
+ JUMPTO(SLJIT_JUMP, common->partialmatchlabel);
+ else
+ add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));
+ }
+
+if (jump != NULL)
+ JUMPHERE(jump);
+}
+
+static void check_str_end(compiler_common *common, jump_list **end_reached)
+{
+/* Does not affect registers. Usually used in a tight spot. */
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+
+if (common->mode == JIT_COMPILE)
+ {
+ add_jump(compiler, end_reached, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+ return;
+ }
+
+jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
+if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
+ {
+ add_jump(compiler, end_reached, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0);
+ add_jump(compiler, end_reached, JUMP(SLJIT_JUMP));
+ }
+else
+ {
+ add_jump(compiler, end_reached, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0));
+ if (common->partialmatchlabel != NULL)
+ JUMPTO(SLJIT_JUMP, common->partialmatchlabel);
+ else
+ add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));
+ }
+JUMPHERE(jump);
+}
+
+static void detect_partial_match(compiler_common *common, jump_list **backtracks)
+{
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+
+if (common->mode == JIT_COMPILE)
+ {
+ add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+ return;
+ }
+
+/* Partial matching mode. */
+jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
+add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0));
+if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0);
+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
+ }
+else
+ {
+ if (common->partialmatchlabel != NULL)
+ JUMPTO(SLJIT_JUMP, common->partialmatchlabel);
+ else
+ add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP));
+ }
+JUMPHERE(jump);
+}
+
+static void peek_char(compiler_common *common, pcre_uint32 max)
+{
+/* Reads the character into TMP1, keeps STR_PTR.
+Does not check STR_END. TMP2 Destroyed. */
+DEFINE_COMPILER;
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+struct sljit_jump *jump;
+#endif
+
+SLJIT_UNUSED_ARG(max);
+
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+if (common->utf)
+ {
+ if (max < 128) return;
+
+ jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
+ 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);
+ JUMPHERE(jump);
+ }
+#endif /* SUPPORT_UTF && !COMPILE_PCRE32 */
+
+#if defined SUPPORT_UTF && defined COMPILE_PCRE16
+if (common->utf)
+ {
+ if (max < 0xd800) return;
+
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ jump = CMP(SLJIT_C_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_UTF && defined COMPILE_PCRE8
+
+static BOOL is_char7_bitset(const pcre_uint8 *bitset, BOOL nclass)
+{
+/* Tells whether the character codes below 128 are enough
+to determine a match. */
+const pcre_uint8 value = nclass ? 0xff : 0;
+const pcre_uint8* end = bitset + 32;
+
+bitset += 16;
+do
+ {
+ if (*bitset++ != value)
+ return FALSE;
+ }
+while (bitset < end);
+return TRUE;
+}
+
+static void read_char7_type(compiler_common *common, BOOL full_read)
+{
+/* 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));
+
+OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+
+if (full_read)
+ {
+ jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 0xc0);
+ OP1(SLJIT_MOV_UB, 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_UTF && COMPILE_PCRE8 */
+
+static void read_char_range(compiler_common *common, pcre_uint32 min, pcre_uint32 max, BOOL update_str_ptr)
+{
+/* 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
+outside the range. Does not check STR_END. */
+DEFINE_COMPILER;
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+struct sljit_jump *jump;
+#endif
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+struct sljit_jump *jump2;
+#endif
+
+SLJIT_UNUSED_ARG(update_str_ptr);
+SLJIT_UNUSED_ARG(min);
+SLJIT_UNUSED_ARG(max);
+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_UTF && defined COMPILE_PCRE8
+if (common->utf)
+ {
+ if (max < 128 && !update_str_ptr) return;
+
+ jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
+ if (min >= 0x10000)
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xf0);
+ if (update_str_ptr)
+ OP1(SLJIT_MOV_UB, 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_C_GREATER, TMP2, 0, SLJIT_IMM, 0x7);
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
+ 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));
+ 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);
+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
+ if (!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)
+ 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)
+ OP1(SLJIT_MOV_UB, 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_C_GREATER, TMP2, 0, SLJIT_IMM, 0xf);
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
+ 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)
+ 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)
+ 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));
+ else if (max < 128)
+ {
+ OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+ }
+ else
+ {
+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ if (!update_str_ptr)
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ else
+ OP1(SLJIT_MOV_UB, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+ 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);
+ if (update_str_ptr)
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0);
+ }
+ JUMPHERE(jump);
+ }
+#endif
+
+#if defined SUPPORT_UTF && defined COMPILE_PCRE16
+if (common->utf)
+ {
+ if (max >= 0x10000)
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ jump = CMP(SLJIT_C_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_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);
+ 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_C_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);
+ }
+#endif
+}
+
+static SLJIT_INLINE void read_char(compiler_common *common)
+{
+read_char_range(common, 0, READ_CHAR_MAX, TRUE);
+}
+
+static void read_char8_type(compiler_common *common, BOOL update_str_ptr)
+{
+/* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
+DEFINE_COMPILER;
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+struct sljit_jump *jump;
+#endif
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+struct sljit_jump *jump2;
+#endif
+
+SLJIT_UNUSED_ARG(update_str_ptr);
+
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+if (common->utf)
+ {
+ /* This can be an extra read in some situations, but hopefully
+ it is needed in most cases. */
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+ jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 0xc0);
+ if (!update_str_ptr)
+ {
+ 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_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);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
+ jump2 = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+ JUMPHERE(jump2);
+ }
+ else
+ add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL));
+ JUMPHERE(jump);
+ return;
+ }
+#endif /* SUPPORT_UTF && COMPILE_PCRE8 */
+
+#if !defined COMPILE_PCRE8
+/* The ctypes array contains only 256 values. */
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
+jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
+#endif
+OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+#if !defined COMPILE_PCRE8
+JUMPHERE(jump);
+#endif
+
+#if defined SUPPORT_UTF && defined COMPILE_PCRE16
+if (common->utf && update_str_ptr)
+ {
+ /* Skip low surrogate if necessary. */
+ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);
+ jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ JUMPHERE(jump);
+ }
+#endif /* SUPPORT_UTF && COMPILE_PCRE16 */
+}
+
+static void skip_char_back(compiler_common *common)
+{
+/* Goes one character back. Affects STR_PTR and TMP1. Does not check begin. */
+DEFINE_COMPILER;
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined COMPILE_PCRE8
+struct sljit_label *label;
+
+if (common->utf)
+ {
+ 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));
+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
+ CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label);
+ return;
+ }
+#elif defined COMPILE_PCRE16
+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));
+ /* Skip low surrogate if necessary. */
+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00);
+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+ return;
+ }
+#endif /* COMPILE_PCRE[8|16] */
+#endif /* SUPPORT_UTF && !COMPILE_PCRE32 */
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+}
+
+static void check_newlinechar(compiler_common *common, int nltype, jump_list **backtracks, BOOL jumpifmatch)
+{
+/* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+
+if (nltype == NLTYPE_ANY)
+ {
+ add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
+ add_jump(compiler, backtracks, JUMP(jumpifmatch ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
+ }
+else if (nltype == NLTYPE_ANYCRLF)
+ {
+ if (jumpifmatch)
+ {
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
+ }
+ else
+ {
+ jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
+ JUMPHERE(jump);
+ }
+ }
+else
+ {
+ SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256);
+ add_jump(compiler, backtracks, CMP(jumpifmatch ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
+ }
+}
+
+#ifdef SUPPORT_UTF
+
+#if defined COMPILE_PCRE8
+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. */
+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_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+jump = JUMP(SLJIT_C_NOT_ZERO);
+/* Two byte sequence. */
+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);
+
+OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000);
+jump = JUMP(SLJIT_C_NOT_ZERO);
+/* Three byte sequence. */
+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_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_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+jump = JUMP(SLJIT_C_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_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_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);
+}
+
+static void do_utfreadtype8(compiler_common *common)
+{
+/* Fast decoding a UTF-8 character type. TMP2 contains the first byte
+of the character (>= 0xc0). Return value in TMP1. */
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+struct sljit_jump *compare;
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);
+jump = JUMP(SLJIT_C_NOT_ZERO);
+/* Two byte sequence. */
+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, 0x1f);
+/* The upper 5 bits are known at this point. */
+compare = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 0x3);
+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);
+OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(compare);
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+/* We only have types for characters less than 256. */
+JUMPHERE(jump);
+OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+#endif /* COMPILE_PCRE8 */
+
+#endif /* SUPPORT_UTF */
+
+#ifdef SUPPORT_UCP
+
+/* 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;
+
+SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8);
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
+OP1(SLJIT_MOV_UB, 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_UH, 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_UB, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+#endif
+
+static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf, BOOL firstline)
+{
+DEFINE_COMPILER;
+struct sljit_label *mainloop;
+struct sljit_label *newlinelabel = NULL;
+struct sljit_jump *start;
+struct sljit_jump *end = NULL;
+struct sljit_jump *nl = NULL;
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+struct sljit_jump *singlechar;
+#endif
+jump_list *newline = NULL;
+BOOL newlinecheck = FALSE;
+BOOL readuchar = FALSE;
+
+if (!(hascrorlf || firstline) && (common->nltype == NLTYPE_ANY ||
+ common->nltype == NLTYPE_ANYCRLF || common->newline > 255))
+ newlinecheck = TRUE;
+
+if (firstline)
+ {
+ /* Search for the end of the first line. */
+ SLJIT_ASSERT(common->first_line_end != 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_C_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_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop);
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop);
+ JUMPHERE(end);
+ OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ }
+ else
+ {
+ end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+ mainloop = LABEL();
+ /* Continual stores does not cause data dependency. */
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0);
+ read_char_range(common, common->nlmin, common->nlmax, TRUE);
+ check_newlinechar(common, common->nltype, &newline, TRUE);
+ CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);
+ JUMPHERE(end);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0);
+ set_jumps(newline, LABEL());
+ }
+
+ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
+ }
+
+start = JUMP(SLJIT_JUMP);
+
+if (newlinecheck)
+ {
+ newlinelabel = LABEL();
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff);
+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
+#endif
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+ nl = JUMP(SLJIT_JUMP);
+ }
+
+mainloop = LABEL();
+
+/* Increasing the STR_PTR here requires one less jump in the most common case. */
+#ifdef SUPPORT_UTF
+if (common->utf) readuchar = TRUE;
+#endif
+if (newlinecheck) readuchar = TRUE;
+
+if (readuchar)
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+
+if (newlinecheck)
+ CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel);
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined COMPILE_PCRE8
+if (common->utf)
+ {
+ singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+ JUMPHERE(singlechar);
+ }
+#elif defined COMPILE_PCRE16
+if (common->utf)
+ {
+ singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+ JUMPHERE(singlechar);
+ }
+#endif /* COMPILE_PCRE[8|16] */
+#endif /* SUPPORT_UTF && !COMPILE_PCRE32 */
+JUMPHERE(start);
+
+if (newlinecheck)
+ {
+ JUMPHERE(end);
+ JUMPHERE(nl);
+ }
+
+return mainloop;
+}
+
+#define MAX_N_CHARS 16
+#define MAX_N_BYTES 8
+
+static SLJIT_INLINE void add_prefix_byte(pcre_uint8 byte, pcre_uint8 *bytes)
+{
+pcre_uint8 len = bytes[0];
+int i;
+
+if (len == 255)
+ return;
+
+if (len == 0)
+ {
+ bytes[0] = 1;
+ bytes[1] = byte;
+ return;
+ }
+
+for (i = len; i > 0; i--)
+ if (bytes[i] == byte)
+ return;
+
+if (len >= MAX_N_BYTES - 1)
+ {
+ bytes[0] = 255;
+ return;
+ }
+
+len++;
+bytes[len] = byte;
+bytes[0] = len;
+}
+
+static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uint32 *chars, pcre_uint8 *bytes, int max_chars)
+{
+/* Recursive function, which scans prefix literals. */
+BOOL last, any, caseless;
+int len, repeat, len_save, consumed = 0;
+pcre_uint32 chr, mask;
+pcre_uchar *alternative, *cc_save, *oc;
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+pcre_uchar othercase[8];
+#elif defined SUPPORT_UTF && defined COMPILE_PCRE16
+pcre_uchar othercase[2];
+#else
+pcre_uchar othercase[1];
+#endif
+
+repeat = 1;
+while (TRUE)
+ {
+ last = TRUE;
+ any = FALSE;
+ caseless = FALSE;
+ switch (*cc)
+ {
+ case OP_CHARI:
+ caseless = TRUE;
+ case OP_CHAR:
+ last = FALSE;
+ cc++;
+ break;
+
+ case OP_SOD:
+ case OP_SOM:
+ case OP_SET_SOM:
+ case OP_NOT_WORD_BOUNDARY:
+ case OP_WORD_BOUNDARY:
+ case OP_EODN:
+ case OP_EOD:
+ case OP_CIRC:
+ case OP_CIRCM:
+ case OP_DOLL:
+ case OP_DOLLM:
+ /* Zero width assertions. */
+ cc++;
+ continue;
+
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ cc = bracketend(cc);
+ continue;
+
+ case OP_PLUSI:
+ case OP_MINPLUSI:
+ case OP_POSPLUSI:
+ caseless = TRUE;
+ case OP_PLUS:
+ case OP_MINPLUS:
+ case OP_POSPLUS:
+ cc++;
+ break;
+
+ case OP_EXACTI:
+ caseless = TRUE;
+ case OP_EXACT:
+ repeat = GET2(cc, 1);
+ last = FALSE;
+ cc += 1 + IMM2_SIZE;
+ break;
+
+ case OP_QUERYI:
+ case OP_MINQUERYI:
+ case OP_POSQUERYI:
+ caseless = TRUE;
+ case OP_QUERY:
+ case OP_MINQUERY:
+ case OP_POSQUERY:
+ len = 1;
+ cc++;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);
+#endif
+ max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars);
+ if (max_chars == 0)
+ return consumed;
+ last = FALSE;
+ break;
+
+ case OP_KET:
+ cc += 1 + LINK_SIZE;
+ continue;
+
+ case OP_ALT:
+ cc += GET(cc, 1);
+ continue;
+
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ case OP_BRA:
+ case OP_BRAPOS:
+ case OP_CBRA:
+ case OP_CBRAPOS:
+ alternative = cc + GET(cc, 1);
+ while (*alternative == OP_ALT)
+ {
+ max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars);
+ if (max_chars == 0)
+ return consumed;
+ alternative += GET(alternative, 1);
+ }
+
+ if (*cc == OP_CBRA || *cc == OP_CBRAPOS)
+ cc += IMM2_SIZE;
+ cc += 1 + LINK_SIZE;
+ continue;
+
+ case OP_CLASS:
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (common->utf && !is_char7_bitset((const pcre_uint8 *)(cc + 1), FALSE)) return consumed;
+#endif
+ any = TRUE;
+ cc += 1 + 32 / sizeof(pcre_uchar);
+ break;
+
+ case OP_NCLASS:
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (common->utf) return consumed;
+#endif
+ any = TRUE;
+ cc += 1 + 32 / sizeof(pcre_uchar);
+ break;
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (common->utf) return consumed;
+#endif
+ any = TRUE;
+ cc += GET(cc, 1);
+ break;
+#endif
+
+ case OP_DIGIT:
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (common->utf && !is_char7_bitset((const pcre_uint8 *)common->ctypes - cbit_length + cbit_digit, FALSE))
+ return consumed;
+#endif
+ any = TRUE;
+ cc++;
+ break;
+
+ case OP_WHITESPACE:
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (common->utf && !is_char7_bitset((const pcre_uint8 *)common->ctypes - cbit_length + cbit_space, FALSE))
+ return consumed;
+#endif
+ any = TRUE;
+ cc++;
+ break;
+
+ case OP_WORDCHAR:
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (common->utf && !is_char7_bitset((const pcre_uint8 *)common->ctypes - cbit_length + cbit_word, FALSE))
+ return consumed;
+#endif
+ any = TRUE;
+ cc++;
+ break;
+
+ case OP_NOT:
+ case OP_NOTI:
+ cc++;
+ /* Fall through. */
+ case OP_NOT_DIGIT:
+ case OP_NOT_WHITESPACE:
+ case OP_NOT_WORDCHAR:
+ case OP_ANY:
+ case OP_ALLANY:
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (common->utf) return consumed;
+#endif
+ any = TRUE;
+ cc++;
+ break;
+
+#ifdef SUPPORT_UCP
+ case OP_NOTPROP:
+ case OP_PROP:
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (common->utf) return consumed;
+#endif
+ any = TRUE;
+ cc += 1 + 2;
+ break;
+#endif
+
+ case OP_TYPEEXACT:
+ repeat = GET2(cc, 1);
+ cc += 1 + IMM2_SIZE;
+ continue;
+
+ case OP_NOTEXACT:
+ case OP_NOTEXACTI:
+#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ if (common->utf) return consumed;
+#endif
+ any = TRUE;
+ repeat = GET2(cc, 1);
+ cc += 1 + IMM2_SIZE + 1;
+ break;
+
+ default:
+ return consumed;
+ }
+
+ if (any)
+ {
+#if defined COMPILE_PCRE8
+ mask = 0xff;
+#elif defined COMPILE_PCRE16
+ mask = 0xffff;
+#elif defined COMPILE_PCRE32
+ mask = 0xffffffff;
+#else
+ SLJIT_ASSERT_STOP();
+#endif
+
+ do
+ {
+ chars[0] = mask;
+ chars[1] = mask;
+ bytes[0] = 255;
+
+ consumed++;
+ if (--max_chars == 0)
+ return consumed;
+ chars += 2;
+ bytes += MAX_N_BYTES;
+ }
+ while (--repeat > 0);
+
+ repeat = 1;
+ continue;
+ }
+
+ len = 1;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);
+#endif
+
+ if (caseless && char_has_othercase(common, cc))
+ {
+#ifdef SUPPORT_UTF
+ if (common->utf)
+ {
+ GETCHAR(chr, cc);
+ if ((int)PRIV(ord2utf)(char_othercase(common, chr), othercase) != len)
+ return consumed;
+ }
+ else
+#endif
+ {
+ chr = *cc;
+ othercase[0] = TABLE_GET(chr, common->fcc, chr);
+ }
+ }
+ else
+ caseless = FALSE;
+
+ len_save = len;
+ cc_save = cc;
+ while (TRUE)
+ {
+ oc = othercase;
+ do
+ {
+ chr = *cc;
+#ifdef COMPILE_PCRE32
+ if (SLJIT_UNLIKELY(chr == NOTACHAR))
+ return consumed;
+#endif
+ add_prefix_byte((pcre_uint8)chr, bytes);
+
+ mask = 0;
+ if (caseless)
+ {
+ add_prefix_byte((pcre_uint8)*oc, bytes);
+ mask = *cc ^ *oc;
+ chr |= mask;
+ }
+
+#ifdef COMPILE_PCRE32
+ if (chars[0] == NOTACHAR && chars[1] == 0)
+#else
+ if (chars[0] == NOTACHAR)
+#endif
+ {
+ chars[0] = chr;
+ chars[1] = mask;
+ }
+ else
+ {
+ mask |= chars[0] ^ chr;
+ chr |= mask;
+ chars[0] = chr;
+ chars[1] |= mask;
+ }
+
+ len--;
+ consumed++;
+ if (--max_chars == 0)
+ return consumed;
+ chars += 2;
+ bytes += MAX_N_BYTES;
+ cc++;
+ oc++;
+ }
+ while (len > 0);
+
+ if (--repeat == 0)
+ break;
+
+ len = len_save;
+ cc = cc_save;
+ }
+
+ repeat = 1;
+ if (last)
+ return consumed;
+ }
+}
+
+static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common, BOOL firstline)
+{
+DEFINE_COMPILER;
+struct sljit_label *start;
+struct sljit_jump *quit;
+pcre_uint32 chars[MAX_N_CHARS * 2];
+pcre_uint8 bytes[MAX_N_CHARS * MAX_N_BYTES];
+pcre_uint8 ones[MAX_N_CHARS];
+int offsets[3];
+pcre_uint32 mask;
+pcre_uint8 *byte_set, *byte_set_end;
+int i, max, from;
+int range_right = -1, range_len = 3 - 1;
+sljit_ub *update_table = NULL;
+BOOL in_range;
+
+/* This is even TRUE, if both are NULL. */
+SLJIT_ASSERT(common->read_only_data_ptr == common->read_only_data);
+
+for (i = 0; i < MAX_N_CHARS; i++)
+ {
+ chars[i << 1] = NOTACHAR;
+ chars[(i << 1) + 1] = 0;
+ bytes[i * MAX_N_BYTES] = 0;
+ }
+
+max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS);
+
+if (max <= 1)
+ return FALSE;
+
+for (i = 0; i < max; i++)
+ {
+ mask = chars[(i << 1) + 1];
+ ones[i] = ones_in_half_byte[mask & 0xf];
+ mask >>= 4;
+ while (mask != 0)
+ {
+ ones[i] += ones_in_half_byte[mask & 0xf];
+ mask >>= 4;
+ }
+ }
+
+in_range = FALSE;
+from = 0; /* Prevent compiler "uninitialized" warning */
+for (i = 0; i <= max; i++)
+ {
+ if (in_range && (i - from) > range_len && (bytes[(i - 1) * MAX_N_BYTES] <= 4))
+ {
+ range_len = i - from;
+ range_right = i - 1;
+ }
+
+ if (i < max && bytes[i * MAX_N_BYTES] < 255)
+ {
+ if (!in_range)
+ {
+ in_range = TRUE;
+ from = i;
+ }
+ }
+ else if (in_range)
+ in_range = FALSE;
+ }
+
+if (range_right >= 0)
+ {
+ /* Since no data is consumed (see the assert in the beginning
+ of this function), this space can be reallocated. */
+ if (common->read_only_data)
+ SLJIT_FREE(common->read_only_data);
+
+ common->read_only_data_size += 256;
+ common->read_only_data = (sljit_uw *)SLJIT_MALLOC(common->read_only_data_size);
+ if (common->read_only_data == NULL)
+ return TRUE;
+
+ update_table = (sljit_ub *)common->read_only_data;
+ common->read_only_data_ptr = (sljit_uw *)(update_table + 256);
+ memset(update_table, IN_UCHARS(range_len), 256);
+
+ for (i = 0; i < range_len; i++)
+ {
+ byte_set = bytes + ((range_right - i) * MAX_N_BYTES);
+ SLJIT_ASSERT(byte_set[0] > 0 && byte_set[0] < 255);
+ byte_set_end = byte_set + byte_set[0];
+ byte_set++;
+ while (byte_set <= byte_set_end)
+ {
+ if (update_table[*byte_set] > IN_UCHARS(i))
+ update_table[*byte_set] = IN_UCHARS(i);
+ byte_set++;
+ }
+ }
+ }
+
+offsets[0] = -1;
+/* Scan forward. */
+for (i = 0; i < max; i++)
+ if (ones[i] <= 2) {
+ offsets[0] = i;
+ break;
+ }
+
+if (offsets[0] < 0 && range_right < 0)
+ return FALSE;
+
+if (offsets[0] >= 0)
+ {
+ /* Scan backward. */
+ offsets[1] = -1;
+ for (i = max - 1; i > offsets[0]; i--)
+ if (ones[i] <= 2 && i != range_right)
+ {
+ offsets[1] = i;
+ break;
+ }
+
+ /* This case is handled better by fast_forward_first_char. */
+ if (offsets[1] == -1 && offsets[0] == 0 && range_right < 0)
+ return FALSE;
+
+ offsets[2] = -1;
+ /* We only search for a middle character if there is no range check. */
+ if (offsets[1] >= 0 && range_right == -1)
+ {
+ /* Scan from middle. */
+ for (i = (offsets[0] + offsets[1]) / 2 + 1; i < offsets[1]; i++)
+ if (ones[i] <= 2)
+ {
+ offsets[2] = i;
+ break;
+ }
+
+ if (offsets[2] == -1)
+ {
+ for (i = (offsets[0] + offsets[1]) / 2; i > offsets[0]; i--)
+ if (ones[i] <= 2)
+ {
+ offsets[2] = i;
+ break;
+ }
+ }
+ }
+
+ SLJIT_ASSERT(offsets[1] == -1 || (offsets[0] < offsets[1]));
+ SLJIT_ASSERT(offsets[2] == -1 || (offsets[0] < offsets[2] && offsets[1] > offsets[2]));
+
+ chars[0] = chars[offsets[0] << 1];
+ chars[1] = chars[(offsets[0] << 1) + 1];
+ if (offsets[2] >= 0)
+ {
+ chars[2] = chars[offsets[2] << 1];
+ chars[3] = chars[(offsets[2] << 1) + 1];
+ }
+ if (offsets[1] >= 0)
+ {
+ chars[4] = chars[offsets[1] << 1];
+ chars[5] = chars[(offsets[1] << 1) + 1];
+ }
+ }
+
+max -= 1;
+if (firstline)
+ {
+ SLJIT_ASSERT(common->first_line_end != 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
+ OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
+ quit = CMP(SLJIT_C_LESS_EQUAL, STR_END, 0, TMP1, 0);
+ OP1(SLJIT_MOV, STR_END, 0, TMP1, 0);
+ JUMPHERE(quit);
+ }
+else
+ OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
+
+#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+if (range_right >= 0)
+ OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table);
+#endif
+
+start = LABEL();
+quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+
+SLJIT_ASSERT(range_right >= 0 || offsets[0] >= 0);
+
+if (range_right >= 0)
+ {
+#if defined COMPILE_PCRE8 || (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right));
+#else
+ OP1(SLJIT_MOV_UB, 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_UB, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0);
+#else
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table);
+#endif
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, start);
+ }
+
+if (offsets[0] >= 0)
+ {
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offsets[0]));
+ if (offsets[1] >= 0)
+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offsets[1]));
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+ if (chars[1] != 0)
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, chars[1]);
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[0], start);
+ if (offsets[2] >= 0)
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offsets[2] - 1));
+
+ if (offsets[1] >= 0)
+ {
+ if (chars[5] != 0)
+ OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, chars[5]);
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, chars[4], start);
+ }
+
+ if (offsets[2] >= 0)
+ {
+ if (chars[3] != 0)
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, chars[3]);
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[2], start);
+ }
+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ }
+
+JUMPHERE(quit);
+
+if (firstline)
+ {
+ if (range_right >= 0)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
+ if (range_right >= 0)
+ {
+ quit = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0);
+ OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);
+ JUMPHERE(quit);
+ }
+ }
+else
+ OP2(SLJIT_ADD, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
+return TRUE;
+}
+
+#undef MAX_N_CHARS
+#undef MAX_N_BYTES
+
+static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless, BOOL firstline)
+{
+DEFINE_COMPILER;
+struct sljit_label *start;
+struct sljit_jump *quit;
+struct sljit_jump *found;
+pcre_uchar oc, bit;
+
+if (firstline)
+ {
+ SLJIT_ASSERT(common->first_line_end != 0);
+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
+ }
+
+start = LABEL();
+quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+
+oc = first_char;
+if (caseless)
+ {
+ oc = TABLE_GET(first_char, common->fcc, first_char);
+#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
+ if (first_char > 127 && common->utf)
+ oc = UCD_OTHERCASE(first_char);
+#endif
+ }
+if (first_char == oc)
+ found = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, first_char);
+else
+ {
+ bit = first_char ^ oc;
+ if (is_powerof2(bit))
+ {
+ OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, bit);
+ found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, first_char | bit);
+ }
+ else
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, first_char);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+ found = JUMP(SLJIT_C_NOT_ZERO);
+ }
+ }
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+JUMPTO(SLJIT_JUMP, start);
+JUMPHERE(found);
+JUMPHERE(quit);
+
+if (firstline)
+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
+}
+
+static SLJIT_INLINE void fast_forward_newline(compiler_common *common, BOOL firstline)
+{
+DEFINE_COMPILER;
+struct sljit_label *loop;
+struct sljit_jump *lastchar;
+struct sljit_jump *firstchar;
+struct sljit_jump *quit;
+struct sljit_jump *foundcr = NULL;
+struct sljit_jump *notfoundnl;
+jump_list *newline = NULL;
+
+if (firstline)
+ {
+ SLJIT_ASSERT(common->first_line_end != 0);
+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
+ }
+
+if (common->nltype == NLTYPE_FIXED && common->newline > 255)
+ {
+ lastchar = CMP(SLJIT_C_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));
+ firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
+
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2));
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_GREATER_EQUAL);
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT);
+#endif
+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+
+ loop = LABEL();
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 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));
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop);
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop);
+
+ JUMPHERE(quit);
+ JUMPHERE(firstchar);
+ JUMPHERE(lastchar);
+
+ if (firstline)
+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
+ return;
+ }
+
+OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
+skip_char_back(common);
+
+loop = LABEL();
+common->ff_newline_shortcut = loop;
+
+read_char_range(common, common->nlmin, common->nlmax, TRUE);
+lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
+ foundcr = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
+check_newlinechar(common, common->nltype, &newline, FALSE);
+set_jumps(newline, loop);
+
+if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
+ {
+ quit = JUMP(SLJIT_JUMP);
+ JUMPHERE(foundcr);
+ notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
+#endif
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+ JUMPHERE(notfoundnl);
+ JUMPHERE(quit);
+ }
+JUMPHERE(lastchar);
+JUMPHERE(firstchar);
+
+if (firstline)
+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
+}
+
+static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks);
+
+static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, pcre_uint8 *start_bits, BOOL firstline)
+{
+DEFINE_COMPILER;
+struct sljit_label *start;
+struct sljit_jump *quit;
+struct sljit_jump *found = NULL;
+jump_list *matches = NULL;
+#ifndef COMPILE_PCRE8
+struct sljit_jump *jump;
+#endif
+
+if (firstline)
+ {
+ SLJIT_ASSERT(common->first_line_end != 0);
+ OP1(SLJIT_MOV, RETURN_ADDR, 0, STR_END, 0);
+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
+ }
+
+start = LABEL();
+quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+#ifdef SUPPORT_UTF
+if (common->utf)
+ OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
+#endif
+
+if (!check_class_ranges(common, start_bits, (start_bits[31] & 0x80) != 0, TRUE, &matches))
+ {
+#ifndef COMPILE_PCRE8
+ jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 255);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255);
+ JUMPHERE(jump);
+#endif
+ OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits);
+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
+ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ found = JUMP(SLJIT_C_NOT_ZERO);
+ }
+
+#ifdef SUPPORT_UTF
+if (common->utf)
+ OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
+#endif
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+#ifdef SUPPORT_UTF
+#if defined COMPILE_PCRE8
+if (common->utf)
+ {
+ CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start);
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+ }
+#elif defined COMPILE_PCRE16
+if (common->utf)
+ {
+ CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start);
+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+ }
+#endif /* COMPILE_PCRE[8|16] */
+#endif /* SUPPORT_UTF */
+JUMPTO(SLJIT_JUMP, start);
+if (found != NULL)
+ JUMPHERE(found);
+if (matches != NULL)
+ set_jumps(matches, LABEL());
+JUMPHERE(quit);
+
+if (firstline)
+ OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0);
+}
+
+static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uchar req_char, BOOL caseless, BOOL has_firstchar)
+{
+DEFINE_COMPILER;
+struct sljit_label *loop;
+struct sljit_jump *toolong;
+struct sljit_jump *alreadyfound;
+struct sljit_jump *found;
+struct sljit_jump *foundoc = NULL;
+struct sljit_jump *notfound;
+pcre_uint32 oc, bit;
+
+SLJIT_ASSERT(common->req_char_ptr != 0);
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr);
+OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX);
+toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0);
+alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0);
+
+if (has_firstchar)
+ OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+else
+ OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0);
+
+loop = LABEL();
+notfound = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, STR_END, 0);
+
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0);
+oc = req_char;
+if (caseless)
+ {
+ oc = TABLE_GET(req_char, common->fcc, req_char);
+#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
+ if (req_char > 127 && common->utf)
+ oc = UCD_OTHERCASE(req_char);
+#endif
+ }
+if (req_char == oc)
+ found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char);
+else
+ {
+ bit = req_char ^ oc;
+ if (is_powerof2(bit))
+ {
+ OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit);
+ found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit);
+ }
+ else
+ {
+ found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char);
+ foundoc = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, oc);
+ }
+ }
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
+JUMPTO(SLJIT_JUMP, loop);
+
+JUMPHERE(found);
+if (foundoc)
+ JUMPHERE(foundoc);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr, TMP1, 0);
+JUMPHERE(alreadyfound);
+JUMPHERE(toolong);
+return notfound;
+}
+
+static void do_revertframes(compiler_common *common)
+{
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+struct sljit_label *mainloop;
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0);
+GET_LOCAL_BASE(TMP3, 0, 0);
+
+/* Drop frames until we reach STACK_TOP. */
+mainloop = LABEL();
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0);
+OP2(SLJIT_SUB | SLJIT_SET_S, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0);
+jump = JUMP(SLJIT_C_SIG_LESS_EQUAL);
+
+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw));
+OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_sw));
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_sw));
+JUMPTO(SLJIT_JUMP, mainloop);
+
+JUMPHERE(jump);
+jump = JUMP(SLJIT_C_SIG_LESS);
+/* End of dropping frames. */
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(jump);
+OP1(SLJIT_NEG, TMP2, 0, TMP2, 0);
+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw));
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));
+JUMPTO(SLJIT_JUMP, mainloop);
+}
+
+static void check_wordboundary(compiler_common *common)
+{
+DEFINE_COMPILER;
+struct sljit_jump *skipread;
+jump_list *skipread_list = NULL;
+#if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF
+struct sljit_jump *jump;
+#endif
+
+SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16);
+
+sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
+/* Get type of the previous char, and put it to LOCALS1. */
+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_LOCALS_REG), LOCALS1, SLJIT_IMM, 0);
+skipread = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0);
+skip_char_back(common);
+check_start_used_ptr(common);
+read_char(common);
+
+/* Testing char type. */
+#ifdef SUPPORT_UCP
+if (common->use_ucp)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
+ jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
+ add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL);
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL);
+ JUMPHERE(jump);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0);
+ }
+else
+#endif
+ {
+#ifndef COMPILE_PCRE8
+ jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
+#elif defined SUPPORT_UTF
+ /* Here LOCALS1 has already been zeroed. */
+ jump = NULL;
+ if (common->utf)
+ jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
+#endif /* COMPILE_PCRE8 */
+ OP1(SLJIT_MOV_UB, 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_LOCALS_REG), LOCALS1, TMP1, 0);
+#ifndef COMPILE_PCRE8
+ JUMPHERE(jump);
+#elif defined SUPPORT_UTF
+ if (jump != NULL)
+ JUMPHERE(jump);
+#endif /* COMPILE_PCRE8 */
+ }
+JUMPHERE(skipread);
+
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
+check_str_end(common, &skipread_list);
+peek_char(common, READ_CHAR_MAX);
+
+/* Testing char type. This is a code duplication. */
+#ifdef SUPPORT_UCP
+if (common->use_ucp)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
+ jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
+ add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL);
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL);
+ JUMPHERE(jump);
+ }
+else
+#endif
+ {
+#ifndef COMPILE_PCRE8
+ /* TMP2 may be destroyed by peek_char. */
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
+ jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
+#elif defined SUPPORT_UTF
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
+ jump = NULL;
+ if (common->utf)
+ jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
+#endif
+ OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes);
+ OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */);
+ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
+#ifndef COMPILE_PCRE8
+ JUMPHERE(jump);
+#elif defined SUPPORT_UTF
+ if (jump != NULL)
+ JUMPHERE(jump);
+#endif /* COMPILE_PCRE8 */
+ }
+set_jumps(skipread_list, LABEL());
+
+OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
+sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
+}
+
+static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks)
+{
+DEFINE_COMPILER;
+int ranges[MAX_RANGE_SIZE];
+pcre_uint8 bit, cbit, all;
+int i, byte, length = 0;
+
+bit = bits[0] & 0x1;
+/* All bits will be zero or one (since bit is zero or one). */
+all = -bit;
+
+for (i = 0; i < 256; )
+ {
+ byte = i >> 3;
+ if ((i & 0x7) == 0 && bits[byte] == all)
+ i += 8;
+ else
+ {
+ cbit = (bits[byte] >> (i & 0x7)) & 0x1;
+ if (cbit != bit)
+ {
+ if (length >= MAX_RANGE_SIZE)
+ return FALSE;
+ ranges[length] = i;
+ length++;
+ bit = cbit;
+ all = -cbit;
+ }
+ i++;
+ }
+ }
+
+if (((bit == 0) && nclass) || ((bit == 1) && !nclass))
+ {
+ if (length >= MAX_RANGE_SIZE)
+ return FALSE;
+ ranges[length] = 256;
+ length++;
+ }
+
+if (length < 0 || length > 4)
+ return FALSE;
+
+bit = bits[0] & 0x1;
+if (invert) bit ^= 0x1;
+
+/* No character is accepted. */
+if (length == 0 && bit == 0)
+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
+
+switch(length)
+ {
+ case 0:
+ /* When bit != 0, all characters are accepted. */
+ return TRUE;
+
+ case 1:
+ add_jump(compiler, backtracks, CMP(bit == 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));
+ return TRUE;
+
+ case 2:
+ if (ranges[0] + 1 != ranges[1])
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);
+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));
+ }
+ else
+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));
+ return TRUE;
+
+ case 3:
+ if (bit != 0)
+ {
+ add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]));
+ if (ranges[0] + 1 != ranges[1])
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));
+ }
+ else
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));
+ return TRUE;
+ }
+
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[0]));
+ if (ranges[1] + 1 != ranges[2])
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1]);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1]));
+ }
+ else
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1]));
+ return TRUE;
+
+ case 4:
+ if ((ranges[1] - ranges[0]) == (ranges[3] - ranges[2])
+ && (ranges[0] | (ranges[2] - ranges[0])) == ranges[2]
+ && is_powerof2(ranges[2] - ranges[0]))
+ {
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[0]);
+ if (ranges[2] + 1 != ranges[3])
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2]);
+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_C_LESS : SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2]));
+ }
+ else
+ add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2]));
+ return TRUE;
+ }
+
+ if (bit != 0)
+ {
+ i = 0;
+ if (ranges[0] + 1 != ranges[1])
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));
+ i = ranges[0];
+ }
+ else
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0]));
+
+ if (ranges[2] + 1 != ranges[3])
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - i);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2]));
+ }
+ else
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2] - i));
+ return TRUE;
+ }
+
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[0]));
+ if (ranges[1] + 1 != ranges[2])
+ {
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1]));
+ }
+ else
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]));
+ return TRUE;
+
+ default:
+ SLJIT_ASSERT_STOP();
+ return FALSE;
+ }
+}
+
+static void check_anynewline(compiler_common *common)
+{
+/* Check whether TMP1 contains a newline character. TMP2 destroyed. */
+DEFINE_COMPILER;
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
+OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL);
+OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
+#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#ifdef COMPILE_PCRE8
+if (common->utf)
+ {
+#endif
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
+#ifdef COMPILE_PCRE8
+ }
+#endif
+#endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
+OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+static void check_hspace(compiler_common *common)
+{
+/* Check whether TMP1 contains a newline character. TMP2 destroyed. */
+DEFINE_COMPILER;
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
+OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
+OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0);
+#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#ifdef COMPILE_PCRE8
+if (common->utf)
+ {
+#endif
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);
+#ifdef COMPILE_PCRE8
+ }
+#endif
+#endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
+OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+static void check_vspace(compiler_common *common)
+{
+/* Check whether TMP1 contains a newline character. TMP2 destroyed. */
+DEFINE_COMPILER;
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
+OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL);
+OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
+#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#ifdef COMPILE_PCRE8
+if (common->utf)
+ {
+#endif
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
+#ifdef COMPILE_PCRE8
+ }
+#endif
+#endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
+OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+#define CHAR1 STR_END
+#define CHAR2 STACK_TOP
+
+static void do_casefulcmp(compiler_common *common)
+{
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+struct sljit_label *label;
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0);
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+label = LABEL();
+OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1));
+OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
+OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
+JUMPTO(SLJIT_C_NOT_ZERO, label);
+
+JUMPHERE(jump);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0);
+OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+#define LCC_TABLE STACK_LIMIT
+
+static void do_caselesscmp(compiler_common *common)
+{
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+struct sljit_label *label;
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+
+OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR1, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, CHAR2, 0);
+OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc);
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+label = LABEL();
+OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1));
+OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+#ifndef COMPILE_PCRE8
+jump = CMP(SLJIT_C_GREATER, CHAR1, 0, SLJIT_IMM, 255);
+#endif
+OP1(SLJIT_MOV_UB, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0);
+#ifndef COMPILE_PCRE8
+JUMPHERE(jump);
+jump = CMP(SLJIT_C_GREATER, CHAR2, 0, SLJIT_IMM, 255);
+#endif
+OP1(SLJIT_MOV_UB, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0);
+#ifndef COMPILE_PCRE8
+JUMPHERE(jump);
+#endif
+jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
+OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
+JUMPTO(SLJIT_C_NOT_ZERO, label);
+
+JUMPHERE(jump);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0);
+OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
+OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+#undef LCC_TABLE
+#undef CHAR1
+#undef CHAR2
+
+#if defined SUPPORT_UTF && defined SUPPORT_UCP
+
+static const pcre_uchar * SLJIT_CALL do_utf_caselesscmp(pcre_uchar *src1, jit_arguments *args, pcre_uchar *end1)
+{
+/* This function would be ineffective to do in JIT level. */
+pcre_uint32 c1, c2;
+const pcre_uchar *src2 = args->uchar_ptr;
+const pcre_uchar *end2 = args->end;
+const ucd_record *ur;
+const pcre_uint32 *pp;
+
+while (src1 < end1)
+ {
+ if (src2 >= end2)
+ return (pcre_uchar*)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_UTF && SUPPORT_UCP */
+
+static pcre_uchar *byte_sequence_compare(compiler_common *common, BOOL caseless, pcre_uchar *cc,
+ compare_context* context, jump_list **backtracks)
+{
+DEFINE_COMPILER;
+unsigned int othercasebit = 0;
+pcre_uchar *othercasechar = NULL;
+#ifdef SUPPORT_UTF
+int utflength;
+#endif
+
+if (caseless && char_has_othercase(common, cc))
+ {
+ othercasebit = char_get_othercase_bit(common, cc);
+ SLJIT_ASSERT(othercasebit);
+ /* Extracting bit difference info. */
+#if defined COMPILE_PCRE8
+ othercasechar = cc + (othercasebit >> 8);
+ othercasebit &= 0xff;
+#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ /* Note that this code only handles characters in the BMP. If there
+ ever are characters outside the BMP whose othercase differs in only one
+ bit from itself (there currently are none), this code will need to be
+ revised for COMPILE_PCRE32. */
+ othercasechar = cc + (othercasebit >> 9);
+ if ((othercasebit & 0x100) != 0)
+ othercasebit = (othercasebit & 0xff) << 8;
+ else
+ othercasebit &= 0xff;
+#endif /* COMPILE_PCRE[8|16|32] */
+ }
+
+if (context->sourcereg == -1)
+ {
+#if defined COMPILE_PCRE8
+#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
+ if (context->length >= 4)
+ OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
+ else if (context->length >= 2)
+ OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
+ else
+#endif
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
+#elif defined COMPILE_PCRE16
+#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
+ if (context->length >= 4)
+ OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
+ else
+#endif
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
+#elif defined COMPILE_PCRE32
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
+#endif /* COMPILE_PCRE[8|16|32] */
+ context->sourcereg = TMP2;
+ }
+
+#ifdef SUPPORT_UTF
+utflength = 1;
+if (common->utf && HAS_EXTRALEN(*cc))
+ utflength += GET_EXTRALEN(*cc);
+
+do
+ {
+#endif
+
+ context->length -= IN_UCHARS(1);
+#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) && (defined COMPILE_PCRE8 || defined COMPILE_PCRE16)
+
+ /* Unaligned read is supported. */
+ if (othercasebit != 0 && othercasechar == cc)
+ {
+ context->c.asuchars[context->ucharptr] = *cc | othercasebit;
+ context->oc.asuchars[context->ucharptr] = othercasebit;
+ }
+ else
+ {
+ context->c.asuchars[context->ucharptr] = *cc;
+ context->oc.asuchars[context->ucharptr] = 0;
+ }
+ context->ucharptr++;
+
+#if defined COMPILE_PCRE8
+ if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1))
+#else
+ if (context->ucharptr >= 2 || context->length == 0)
+#endif
+ {
+ if (context->length >= 4)
+ OP1(SLJIT_MOV_SI, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
+ else if (context->length >= 2)
+ OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
+#if defined COMPILE_PCRE8
+ else if (context->length >= 1)
+ OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
+#endif /* COMPILE_PCRE8 */
+ context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
+
+ switch(context->ucharptr)
+ {
+ case 4 / sizeof(pcre_uchar):
+ if (context->oc.asint != 0)
+ OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint));
+ break;
+
+ case 2 / sizeof(pcre_uchar):
+ if (context->oc.asushort != 0)
+ OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort));
+ break;
+
+#ifdef COMPILE_PCRE8
+ case 1:
+ if (context->oc.asbyte != 0)
+ OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte));
+ break;
+#endif
+
+ default:
+ SLJIT_ASSERT_STOP();
+ break;
+ }
+ context->ucharptr = 0;
+ }
+
+#else
+
+ /* Unaligned read is unsupported or in 32 bit mode. */
+ if (context->length >= 1)
+ OP1(MOV_UCHAR, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
+
+ context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
+
+ if (othercasebit != 0 && othercasechar == cc)
+ {
+ OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit));
+ }
+ else
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc));
+
+#endif
+
+ cc++;
+#ifdef SUPPORT_UTF
+ utflength--;
+ }
+while (utflength > 0);
+#endif
+
+return cc;
+}
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+
+#define SET_TYPE_OFFSET(value) \
+ if ((value) != typeoffset) \
+ { \
+ if ((value) < typeoffset) \
+ OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \
+ else \
+ OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \
+ } \
+ typeoffset = (value);
+
+#define SET_CHAR_OFFSET(value) \
+ if ((value) != charoffset) \
+ { \
+ if ((value) < charoffset) \
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(charoffset - (value))); \
+ else \
+ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)((value) - charoffset)); \
+ } \
+ charoffset = (value);
+
+static void compile_xclass_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)
+{
+DEFINE_COMPILER;
+jump_list *found = NULL;
+jump_list **list = (cc[0] & XCL_NOT) == 0 ? &found : backtracks;
+sljit_uw c, charoffset, max = 256, min = READ_CHAR_MAX;
+struct sljit_jump *jump = NULL;
+pcre_uchar *ccbegin;
+int compares, invertcmp, numberofcmps;
+#if defined SUPPORT_UTF && (defined COMPILE_PCRE8 || defined COMPILE_PCRE16)
+BOOL utf = common->utf;
+#endif
+
+#ifdef SUPPORT_UCP
+BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;
+BOOL charsaved = FALSE;
+int typereg = TMP1, scriptreg = TMP1;
+const pcre_uint32 *other_cases;
+sljit_uw typeoffset;
+#endif
+
+/* Scanning the necessary info. */
+cc++;
+ccbegin = cc;
+compares = 0;
+if (cc[-1] & XCL_MAP)
+ {
+ min = 0;
+ cc += 32 / sizeof(pcre_uchar);
+ }
+
+while (*cc != XCL_END)
+ {
+ compares++;
+ if (*cc == XCL_SINGLE)
+ {
+ cc ++;
+ GETCHARINCTEST(c, cc);
+ if (c > max) max = c;
+ if (c < min) min = c;
+#ifdef SUPPORT_UCP
+ needschar = TRUE;
+#endif
+ }
+ else if (*cc == XCL_RANGE)
+ {
+ cc ++;
+ GETCHARINCTEST(c, cc);
+ if (c < min) min = c;
+ GETCHARINCTEST(c, cc);
+ if (c > max) max = c;
+#ifdef SUPPORT_UCP
+ needschar = TRUE;
+#endif
+ }
+#ifdef SUPPORT_UCP
+ else
+ {
+ SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
+ cc++;
+ if (*cc == PT_CLIST)
+ {
+ other_cases = PRIV(ucd_caseless_sets) + cc[1];
+ while (*other_cases != NOTACHAR)
+ {
+ if (*other_cases > max) max = *other_cases;
+ if (*other_cases < min) min = *other_cases;
+ other_cases++;
+ }
+ }
+ else
+ {
+ max = READ_CHAR_MAX;
+ min = 0;
+ }
+
+ switch(*cc)
+ {
+ case PT_ANY:
+ break;
+
+ case PT_LAMP:
+ case PT_GC:
+ case PT_PC:
+ case PT_ALNUM:
+ needstype = TRUE;
+ break;
+
+ case PT_SC:
+ needsscript = TRUE;
+ break;
+
+ case PT_SPACE:
+ case PT_PXSPACE:
+ case PT_WORD:
+ case PT_PXGRAPH:
+ case PT_PXPRINT:
+ case PT_PXPUNCT:
+ needstype = TRUE;
+ needschar = TRUE;
+ break;
+
+ case PT_CLIST:
+ case PT_UCNC:
+ needschar = TRUE;
+ break;
+
+ default:
+ SLJIT_ASSERT_STOP();
+ break;
+ }
+ cc += 2;
+ }
+#endif
+ }
+
+/* We are not necessary in utf mode even in 8 bit mode. */
+cc = ccbegin;
+detect_partial_match(common, backtracks);
+read_char_range(common, min, max, (cc[-1] & XCL_NOT) != 0);
+
+if ((cc[-1] & XCL_HASPROP) == 0)
+ {
+ if ((cc[-1] & XCL_MAP) != 0)
+ {
+ jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
+ if (!check_class_ranges(common, (const pcre_uint8 *)cc, (((const pcre_uint8 *)cc)[31] & 0x80) != 0, TRUE, &found))
+ {
+ OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
+ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ add_jump(compiler, &found, JUMP(SLJIT_C_NOT_ZERO));
+ }
+
+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
+ JUMPHERE(jump);
+
+ cc += 32 / sizeof(pcre_uchar);
+ }
+ else
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, min);
+ add_jump(compiler, (cc[-1] & XCL_NOT) == 0 ? backtracks : &found, CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, max - min));
+ }
+ }
+else if ((cc[-1] & XCL_MAP) != 0)
+ {
+ OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
+#ifdef SUPPORT_UCP
+ charsaved = TRUE;
+#endif
+ if (!check_class_ranges(common, (const pcre_uint8 *)cc, FALSE, TRUE, list))
+ {
+#ifdef COMPILE_PCRE8
+ SLJIT_ASSERT(common->utf);
+#endif
+ jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
+
+ OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
+ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO));
+
+ JUMPHERE(jump);
+ }
+
+ OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
+ cc += 32 / sizeof(pcre_uchar);
+ }
+
+#ifdef SUPPORT_UCP
+/* Simple register allocation. TMP1 is preferred if possible. */
+if (needstype || needsscript)
+ {
+ if (needschar && !charsaved)
+ OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
+ add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
+ if (needschar)
+ {
+ if (needstype)
+ {
+ OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
+ typereg = RETURN_ADDR;
+ }
+
+ if (needsscript)
+ scriptreg = TMP3;
+ OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
+ }
+ else if (needstype && needsscript)
+ scriptreg = TMP3;
+ /* In all other cases only one of them was specified, and that can goes to TMP1. */
+
+ if (needsscript)
+ {
+ if (scriptreg == TMP1)
+ {
+ OP1(SLJIT_MOV, scriptreg, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
+ OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM2(scriptreg, TMP2), 3);
+ }
+ else
+ {
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
+ OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM1(TMP2), 0);
+ }
+ }
+ }
+#endif
+
+/* Generating code. */
+charoffset = 0;
+numberofcmps = 0;
+#ifdef SUPPORT_UCP
+typeoffset = 0;
+#endif
+
+while (*cc != XCL_END)
+ {
+ compares--;
+ invertcmp = (compares == 0 && list != backtracks);
+ jump = NULL;
+
+ if (*cc == XCL_SINGLE)
+ {
+ cc ++;
+ GETCHARINCTEST(c, cc);
+
+ if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+ OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_C_EQUAL);
+ numberofcmps++;
+ }
+ else if (numberofcmps > 0)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+ jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
+ numberofcmps = 0;
+ }
+ else
+ {
+ jump = CMP(SLJIT_C_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+ numberofcmps = 0;
+ }
+ }
+ else if (*cc == XCL_RANGE)
+ {
+ cc ++;
+ GETCHARINCTEST(c, cc);
+ SET_CHAR_OFFSET(c);
+ GETCHARINCTEST(c, cc);
+
+ if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+ OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_C_LESS_EQUAL);
+ numberofcmps++;
+ }
+ else if (numberofcmps > 0)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL);
+ jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
+ numberofcmps = 0;
+ }
+ else
+ {
+ jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+ numberofcmps = 0;
+ }
+ }
+#ifdef SUPPORT_UCP
+ else
+ {
+ if (*cc == XCL_NOTPROP)
+ invertcmp ^= 0x1;
+ cc++;
+ switch(*cc)
+ {
+ case PT_ANY:
+ if (list != backtracks)
+ {
+ if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0))
+ continue;
+ }
+ else if (cc[-1] == XCL_NOTPROP)
+ continue;
+ jump = JUMP(SLJIT_JUMP);
+ break;
+
+ case PT_LAMP:
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+ jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
+ break;
+
+ case PT_GC:
+ c = PRIV(ucp_typerange)[(int)cc[1] * 2];
+ SET_TYPE_OFFSET(c);
+ jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, PRIV(ucp_typerange)[(int)cc[1] * 2 + 1] - c);
+ break;
+
+ case PT_PC:
+ jump = CMP(SLJIT_C_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, (int)cc[1] - typeoffset);
+ break;
+
+ case PT_SC:
+ jump = CMP(SLJIT_C_EQUAL ^ invertcmp, scriptreg, 0, SLJIT_IMM, (int)cc[1]);
+ break;
+
+ case PT_SPACE:
+ case PT_PXSPACE:
+ SET_CHAR_OFFSET(9);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd - 0x9);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL);
+
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x9);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x9);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+
+ SET_TYPE_OFFSET(ucp_Zl);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL);
+ jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
+ break;
+
+ case PT_WORD:
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_UNDERSCORE - charoffset));
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
+ /* Fall through. */
+
+ case PT_ALNUM:
+ SET_TYPE_OFFSET(ucp_Ll);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
+ OP_FLAGS((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, (*cc == PT_ALNUM) ? SLJIT_UNUSED : TMP2, 0, SLJIT_C_LESS_EQUAL);
+ SET_TYPE_OFFSET(ucp_Nd);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL);
+ jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
+ break;
+
+ case PT_CLIST:
+ other_cases = PRIV(ucd_caseless_sets) + cc[1];
+
+ /* At least three characters are required.
+ Otherwise this case would be handled by the normal code path. */
+ SLJIT_ASSERT(other_cases[0] != NOTACHAR && other_cases[1] != NOTACHAR && other_cases[2] != NOTACHAR);
+ SLJIT_ASSERT(other_cases[0] < other_cases[1] && other_cases[1] < other_cases[2]);
+
+ /* Optimizing character pairs, if their difference is power of 2. */
+ if (is_powerof2(other_cases[1] ^ other_cases[0]))
+ {
+ if (charoffset == 0)
+ OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);
+ else
+ {
+ OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset);
+ OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);
+ }
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[1]);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
+ other_cases += 2;
+ }
+ else if (is_powerof2(other_cases[2] ^ other_cases[1]))
+ {
+ if (charoffset == 0)
+ OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, other_cases[2] ^ other_cases[1]);
+ else
+ {
+ OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset);
+ OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);
+ }
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[2]);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
+
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[0] - charoffset));
+ OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+
+ other_cases += 3;
+ }
+ else
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
+ }
+
+ while (*other_cases != NOTACHAR)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
+ OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+ }
+ jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
+ break;
+
+ case PT_UCNC:
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset));
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset));
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset));
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+
+ SET_CHAR_OFFSET(0xa0);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset));
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL);
+ SET_CHAR_OFFSET(0);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xe000 - 0);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_GREATER_EQUAL);
+ jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
+ break;
+
+ case PT_PXGRAPH:
+ /* C and Z groups are the farthest two groups. */
+ SET_TYPE_OFFSET(ucp_Ll);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_GREATER);
+
+ jump = CMP(SLJIT_C_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll);
+
+ /* In case of ucp_Cf, we overwrite the result. */
+ SET_CHAR_OFFSET(0x2066);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL);
+
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+
+ JUMPHERE(jump);
+ jump = CMP(SLJIT_C_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0);
+ break;
+
+ case PT_PXPRINT:
+ /* C and Z groups are the farthest two groups. */
+ SET_TYPE_OFFSET(ucp_Ll);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_GREATER);
+
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Ll);
+ OP_FLAGS(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_C_NOT_EQUAL);
+
+ jump = CMP(SLJIT_C_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll);
+
+ /* In case of ucp_Cf, we overwrite the result. */
+ SET_CHAR_OFFSET(0x2066);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL);
+
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
+ OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL);
+
+ JUMPHERE(jump);
+ jump = CMP(SLJIT_C_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0);
+ break;
+
+ case PT_PXPUNCT:
+ SET_TYPE_OFFSET(ucp_Sc);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Sc);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL);
+
+ SET_CHAR_OFFSET(0);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xff);
+ OP_FLAGS(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL);
+
+ SET_TYPE_OFFSET(ucp_Pc);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ps - ucp_Pc);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL);
+ jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
+ break;
+ }
+ cc += 2;
+ }
+#endif
+
+ if (jump != NULL)
+ add_jump(compiler, compares > 0 ? list : backtracks, jump);
+ }
+
+if (found != NULL)
+ set_jumps(found, LABEL());
+}
+
+#undef SET_TYPE_OFFSET
+#undef SET_CHAR_OFFSET
+
+#endif
+
+static pcre_uchar *compile_char1_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks)
+{
+DEFINE_COMPILER;
+int length;
+unsigned int c, oc, bit;
+compare_context context;
+struct sljit_jump *jump[4];
+jump_list *end_list;
+#ifdef SUPPORT_UTF
+struct sljit_label *label;
+#ifdef SUPPORT_UCP
+pcre_uchar propdata[5];
+#endif
+#endif /* SUPPORT_UTF */
+
+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));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_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));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_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));
+ add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
+ return cc;
+
+ case OP_NOT_DIGIT:
+ case OP_DIGIT:
+ /* Digits are usually 0-9, so it is worth to optimize them. */
+ detect_partial_match(common, backtracks);
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (common->utf && is_char7_bitset((const pcre_uint8*)common->ctypes - cbit_length + cbit_digit, FALSE))
+ read_char7_type(common, type == OP_NOT_DIGIT);
+ else
+#endif
+ read_char8_type(common, type == OP_NOT_DIGIT);
+ /* Flip the starting bit in the negative case. */
+ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
+ add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
+ return cc;
+
+ case OP_NOT_WHITESPACE:
+ case OP_WHITESPACE:
+ detect_partial_match(common, backtracks);
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (common->utf && is_char7_bitset((const pcre_uint8*)common->ctypes - cbit_length + cbit_space, FALSE))
+ read_char7_type(common, type == OP_NOT_WHITESPACE);
+ else
+#endif
+ read_char8_type(common, type == OP_NOT_WHITESPACE);
+ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
+ add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
+ return cc;
+
+ case OP_NOT_WORDCHAR:
+ case OP_WORDCHAR:
+ detect_partial_match(common, backtracks);
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (common->utf && is_char7_bitset((const pcre_uint8*)common->ctypes - cbit_length + cbit_word, FALSE))
+ read_char7_type(common, type == OP_NOT_WORDCHAR);
+ else
+#endif
+ read_char8_type(common, type == OP_NOT_WORDCHAR);
+ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
+ add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
+ return cc;
+
+ case OP_ANY:
+ detect_partial_match(common, backtracks);
+ read_char_range(common, common->nlmin, common->nlmax, TRUE);
+ if (common->nltype == NLTYPE_FIXED && common->newline > 255)
+ {
+ jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
+ end_list = NULL;
+ if (common->mode != JIT_PARTIAL_HARD_COMPILE)
+ add_jump(compiler, &end_list, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+ else
+ check_str_end(common, &end_list);
+
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff));
+ set_jumps(end_list, LABEL());
+ JUMPHERE(jump[0]);
+ }
+ else
+ check_newlinechar(common, common->nltype, backtracks, TRUE);
+ return cc;
+
+ case OP_ALLANY:
+ detect_partial_match(common, backtracks);
+#ifdef SUPPORT_UTF
+ if (common->utf)
+ {
+ 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 defined COMPILE_PCRE8 || defined COMPILE_PCRE16
+#if defined COMPILE_PCRE8
+ jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+#elif defined COMPILE_PCRE16
+ jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL);
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+#endif
+ JUMPHERE(jump[0]);
+#endif /* COMPILE_PCRE[8|16] */
+ return cc;
+ }
+#endif
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ return cc;
+
+ case OP_ANYBYTE:
+ detect_partial_match(common, backtracks);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ return cc;
+
+#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UCP
+ case OP_NOTPROP:
+ case OP_PROP:
+ propdata[0] = XCL_HASPROP;
+ propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP;
+ propdata[2] = cc[0];
+ propdata[3] = cc[1];
+ propdata[4] = XCL_END;
+ compile_xclass_matchingpath(common, propdata, backtracks);
+ return cc + 2;
+#endif
+#endif
+
+ case OP_ANYNL:
+ detect_partial_match(common, backtracks);
+ read_char_range(common, common->bsr_nlmin, common->bsr_nlmax, FALSE);
+ jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
+ /* We don't need to handle soft partial matching case. */
+ end_list = NULL;
+ if (common->mode != JIT_PARTIAL_HARD_COMPILE)
+ add_jump(compiler, &end_list, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+ else
+ check_str_end(common, &end_list);
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+ jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ jump[2] = JUMP(SLJIT_JUMP);
+ JUMPHERE(jump[0]);
+ check_newlinechar(common, common->bsr_nltype, backtracks, FALSE);
+ set_jumps(end_list, LABEL());
+ JUMPHERE(jump[1]);
+ JUMPHERE(jump[2]);
+ return cc;
+
+ case OP_NOT_HSPACE:
+ case OP_HSPACE:
+ detect_partial_match(common, backtracks);
+ read_char_range(common, 0x9, 0x3000, type == OP_NOT_HSPACE);
+ add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
+ add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
+ return cc;
+
+ case OP_NOT_VSPACE:
+ case OP_VSPACE:
+ detect_partial_match(common, backtracks);
+ read_char_range(common, 0xa, 0x2029, type == OP_NOT_VSPACE);
+ add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
+ add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
+ return cc;
+
+#ifdef SUPPORT_UCP
+ case OP_EXTUNI:
+ detect_partial_match(common, backtracks);
+ read_char(common);
+ add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop));
+ /* Optimize register allocation: use a real register. */
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);
+ OP1(SLJIT_MOV_UB, STACK_TOP, 0, SLJIT_MEM2(TMP1, TMP2), 3);
+
+ label = LABEL();
+ jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
+ read_char(common);
+ add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop));
+ OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM2(TMP1, TMP2), 3);
+
+ OP2(SLJIT_SHL, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2);
+ OP1(SLJIT_MOV_UI, TMP1, 0, SLJIT_MEM1(STACK_TOP), (sljit_sw)PRIV(ucp_gbtable));
+ OP1(SLJIT_MOV, STACK_TOP, 0, TMP2, 0);
+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
+ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ JUMPTO(SLJIT_C_NOT_ZERO, label);
+
+ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
+ JUMPHERE(jump[0]);
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
+
+ if (common->mode == JIT_PARTIAL_HARD_COMPILE)
+ {
+ jump[0] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
+ /* Since we successfully read a char above, partial matching must occure. */
+ check_partial(common, TRUE);
+ JUMPHERE(jump[0]);
+ }
+ return cc;
+#endif
+
+ case OP_EODN:
+ /* Requires rather complex checks. */
+ jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+ if (common->nltype == NLTYPE_FIXED && common->newline > 255)
+ {
+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ if (common->mode == JIT_COMPILE)
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
+ else
+ {
+ jump[1] = CMP(SLJIT_C_EQUAL, TMP2, 0, STR_END, 0);
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
+ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS);
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
+ OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_NOT_EQUAL);
+ add_jump(compiler, backtracks, JUMP(SLJIT_C_NOT_EQUAL));
+ check_partial(common, TRUE);
+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
+ JUMPHERE(jump[1]);
+ }
+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
+ }
+ else if (common->nltype == NLTYPE_FIXED)
+ {
+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
+ }
+ else
+ {
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+ OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
+ jump[2] = JUMP(SLJIT_C_GREATER);
+ add_jump(compiler, backtracks, JUMP(SLJIT_C_LESS));
+ /* Equal. */
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+ jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
+
+ JUMPHERE(jump[1]);
+ if (common->nltype == NLTYPE_ANYCRLF)
+ {
+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
+ }
+ else
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0);
+ read_char_range(common, common->nlmin, common->nlmax, TRUE);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
+ add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
+ add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO));
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
+ }
+ JUMPHERE(jump[2]);
+ JUMPHERE(jump[3]);
+ }
+ JUMPHERE(jump[0]);
+ check_partial(common, FALSE);
+ return cc;
+
+ case OP_EOD:
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0));
+ check_partial(common, FALSE);
+ 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_C_GREATER, STR_PTR, 0, TMP1, 0));
+ OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+ 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_C_GREATER, STR_PTR, 0, TMP1, 0);
+ OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+ jump[0] = JUMP(SLJIT_JUMP);
+ JUMPHERE(jump[1]);
+
+ add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+ 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_C_LESS, TMP2, 0, TMP1, 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_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
+ }
+ else
+ {
+ skip_char_back(common);
+ read_char_range(common, common->nlmin, common->nlmax, TRUE);
+ check_newlinechar(common, common->nltype, backtracks, FALSE);
+ }
+ JUMPHERE(jump[0]);
+ return cc;
+
+ case OP_DOLL:
+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+
+ if (!common->endonly)
+ compile_char1_matchingpath(common, OP_EODN, cc, backtracks);
+ else
+ {
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0));
+ check_partial(common, FALSE);
+ }
+ return cc;
+
+ case OP_DOLLM:
+ jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+ check_partial(common, FALSE);
+ jump[0] = JUMP(SLJIT_JUMP);
+ JUMPHERE(jump[1]);
+
+ if (common->nltype == NLTYPE_FIXED && common->newline > 255)
+ {
+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ if (common->mode == JIT_COMPILE)
+ add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0));
+ else
+ {
+ jump[1] = CMP(SLJIT_C_LESS_EQUAL, TMP2, 0, STR_END, 0);
+ /* STR_PTR = STR_END - IN_UCHARS(1) */
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
+ check_partial(common, TRUE);
+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
+ JUMPHERE(jump[1]);
+ }
+
+ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
+ }
+ else
+ {
+ peek_char(common, common->nlmax);
+ check_newlinechar(common, common->nltype, backtracks, FALSE);
+ }
+ JUMPHERE(jump[0]);
+ return cc;
+
+ case OP_CHAR:
+ case OP_CHARI:
+ length = 1;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc);
+#endif
+ if (common->mode == JIT_COMPILE && (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_C_GREATER, STR_PTR, 0, STR_END, 0));
+
+ context.length = IN_UCHARS(length);
+ context.sourcereg = -1;
+#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
+ context.ucharptr = 0;
+#endif
+ return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks);
+ }
+
+ detect_partial_match(common, backtracks);
+#ifdef SUPPORT_UTF
+ if (common->utf)
+ {
+ GETCHAR(c, cc);
+ }
+ else
+#endif
+ c = *cc;
+
+ if (type == OP_CHAR || !char_has_othercase(common, cc))
+ {
+ read_char_range(common, c, c, FALSE);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_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))
+ {
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
+ return cc + length;
+ }
+ jump[0] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, oc));
+ JUMPHERE(jump[0]);
+ return cc + length;
+
+ case OP_NOT:
+ case OP_NOTI:
+ detect_partial_match(common, backtracks);
+ length = 1;
+#ifdef SUPPORT_UTF
+ if (common->utf)
+ {
+#ifdef COMPILE_PCRE8
+ c = *cc;
+ if (c < 128)
+ {
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+ if (type == OP_NOT || !char_has_othercase(common, cc))
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
+ else
+ {
+ /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */
+ OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20));
+ }
+ /* Skip the variable-length character. */
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+ JUMPHERE(jump[0]);
+ return cc + 1;
+ }
+ else
+#endif /* COMPILE_PCRE8 */
+ {
+ GETCHARLEN(c, cc, length);
+ }
+ }
+ else
+#endif /* SUPPORT_UTF */
+ c = *cc;
+
+ if (type == OP_NOT || !char_has_othercase(common, cc))
+ {
+ read_char_range(common, c, c, TRUE);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_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);
+ bit = c ^ oc;
+ if (is_powerof2(bit))
+ {
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
+ }
+ else
+ {
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc));
+ }
+ }
+ return cc + length;
+
+ case OP_CLASS:
+ case OP_NCLASS:
+ detect_partial_match(common, backtracks);
+
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ bit = (common->utf && is_char7_bitset((const pcre_uint8 *)cc, type == OP_NCLASS)) ? 127 : 255;
+ read_char_range(common, 0, bit, type == OP_NCLASS);
+#else
+ read_char_range(common, 0, 255, type == OP_NCLASS);
+#endif
+
+ if (check_class_ranges(common, (const pcre_uint8 *)cc, type == OP_NCLASS, FALSE, backtracks))
+ return cc + 32 / sizeof(pcre_uchar);
+
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ jump[0] = NULL;
+ if (common->utf)
+ {
+ jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, bit);
+ if (type == OP_CLASS)
+ {
+ add_jump(compiler, backtracks, jump[0]);
+ jump[0] = NULL;
+ }
+ }
+#elif !defined COMPILE_PCRE8
+ jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
+ if (type == OP_CLASS)
+ {
+ add_jump(compiler, backtracks, jump[0]);
+ jump[0] = NULL;
+ }
+#endif /* SUPPORT_UTF && COMPILE_PCRE8 */
+
+ OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
+ OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
+ OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
+ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO));
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ if (jump[0] != NULL)
+ JUMPHERE(jump[0]);
+#endif
+
+ return cc + 32 / sizeof(pcre_uchar);
+
+#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ case OP_XCLASS:
+ compile_xclass_matchingpath(common, cc + LINK_SIZE, backtracks);
+ return cc + GET(cc, 0) - 1;
+#endif
+
+ case OP_REVERSE:
+ length = GET(cc, 0);
+ if (length == 0)
+ return cc + LINK_SIZE;
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+#ifdef SUPPORT_UTF
+ if (common->utf)
+ {
+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length);
+ label = LABEL();
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP3, 0));
+ skip_char_back(common);
+ OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
+ JUMPTO(SLJIT_C_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_C_LESS, STR_PTR, 0, TMP1, 0));
+ }
+ check_start_used_ptr(common);
+ return cc + LINK_SIZE;
+ }
+SLJIT_ASSERT_STOP();
+return cc;
+}
+
+static SLJIT_INLINE pcre_uchar *compile_charn_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **backtracks)
+{
+/* This function consumes at least one input character. */
+/* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */
+DEFINE_COMPILER;
+pcre_uchar *ccbegin = cc;
+compare_context context;
+int size;
+
+context.length = 0;
+do
+ {
+ if (cc >= ccend)
+ break;
+
+ if (*cc == OP_CHAR)
+ {
+ size = 1;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(cc[1]))
+ size += GET_EXTRALEN(cc[1]);
+#endif
+ }
+ else if (*cc == OP_CHARI)
+ {
+ size = 1;
+#ifdef SUPPORT_UTF
+ if (common->utf)
+ {
+ if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
+ size = 0;
+ else if (HAS_EXTRALEN(cc[1]))
+ size += GET_EXTRALEN(cc[1]);
+ }
+ else
+#endif
+ if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
+ size = 0;
+ }
+ else
+ size = 0;
+
+ cc += 1 + size;
+ context.length += IN_UCHARS(size);
+ }
+while (size > 0 && context.length <= 128);
+
+cc = ccbegin;
+if (context.length > 0)
+ {
+ /* We have a fixed-length byte sequence. */
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length);
+ add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
+
+ context.sourcereg = -1;
+#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
+ context.ucharptr = 0;
+#endif
+ do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, backtracks); while (context.length > 0);
+ return cc;
+ }
+
+/* A non-fixed length character will be checked if length == 0. */
+return compile_char1_matchingpath(common, *cc, cc + 1, backtracks);
+}
+
+/* Forward definitions. */
+static void compile_matchingpath(compiler_common *, pcre_uchar *, pcre_uchar *, backtrack_common *);
+static void compile_backtrackingpath(compiler_common *, struct backtrack_common *);
+
+#define PUSH_BACKTRACK(size, ccstart, error) \
+ do \
+ { \
+ backtrack = sljit_alloc_memory(compiler, (size)); \
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
+ return error; \
+ memset(backtrack, 0, size); \
+ backtrack->prev = parent->top; \
+ backtrack->cc = (ccstart); \
+ parent->top = backtrack; \
+ } \
+ while (0)
+
+#define PUSH_BACKTRACK_NOVALUE(size, ccstart) \
+ do \
+ { \
+ backtrack = sljit_alloc_memory(compiler, (size)); \
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
+ return; \
+ memset(backtrack, 0, size); \
+ backtrack->prev = parent->top; \
+ backtrack->cc = (ccstart); \
+ parent->top = backtrack; \
+ } \
+ while (0)
+
+#define BACKTRACK_AS(type) ((type *)backtrack)
+
+static void compile_dnref_search(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)
+{
+/* The OVECTOR offset goes to TMP2. */
+DEFINE_COMPILER;
+int count = GET2(cc, 1 + IMM2_SIZE);
+pcre_uchar *slot = common->name_table + GET2(cc, 1) * common->name_entry_size;
+unsigned int offset;
+jump_list *found = NULL;
+
+SLJIT_ASSERT(*cc == OP_DNREF || *cc == OP_DNREFI);
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
+
+count--;
+while (count-- > 0)
+ {
+ offset = GET2(slot, 0) << 1;
+ GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset));
+ add_jump(compiler, &found, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0));
+ slot += common->name_entry_size;
+ }
+
+offset = GET2(slot, 0) << 1;
+GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset));
+if (backtracks != NULL && !common->jscript_compat)
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0));
+
+set_jumps(found, LABEL());
+}
+
+static void compile_ref_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail)
+{
+DEFINE_COMPILER;
+BOOL ref = (*cc == OP_REF || *cc == OP_REFI);
+int offset = 0;
+struct sljit_jump *jump = NULL;
+struct sljit_jump *partial;
+struct sljit_jump *nopartial;
+
+if (ref)
+ {
+ offset = GET2(cc, 1) << 1;
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
+ /* OVECTOR(1) contains the "string begin - 1" constant. */
+ if (withchecks && !common->jscript_compat)
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
+ }
+else
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
+
+#if defined SUPPORT_UTF && defined SUPPORT_UCP
+if (common->utf && *cc == OP_REFI)
+ {
+ SLJIT_ASSERT(TMP1 == SLJIT_SCRATCH_REG1 && STACK_TOP == SLJIT_SCRATCH_REG2 && TMP2 == SLJIT_SCRATCH_REG3);
+ if (ref)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
+ else
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
+
+ if (withchecks)
+ jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0);
+
+ /* Needed to save important temporary registers. */
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);
+ OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, uchar_ptr), STR_PTR, 0);
+ sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp));
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
+ if (common->mode == JIT_COMPILE)
+ add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1));
+ else
+ {
+ add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
+ nopartial = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
+ check_partial(common, FALSE);
+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
+ JUMPHERE(nopartial);
+ }
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
+ }
+else
+#endif /* SUPPORT_UTF && SUPPORT_UCP */
+ {
+ if (ref)
+ OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0);
+ else
+ OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0);
+
+ if (withchecks)
+ jump = JUMP(SLJIT_C_ZERO);
+
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+ partial = CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0);
+ if (common->mode == JIT_COMPILE)
+ add_jump(compiler, backtracks, partial);
+
+ add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+
+ if (common->mode != JIT_COMPILE)
+ {
+ nopartial = JUMP(SLJIT_JUMP);
+ JUMPHERE(partial);
+ /* TMP2 -= STR_END - STR_PTR */
+ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, STR_PTR, 0);
+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, STR_END, 0);
+ partial = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0);
+ OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);
+ add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
+ add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+ JUMPHERE(partial);
+ check_partial(common, FALSE);
+ add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
+ JUMPHERE(nopartial);
+ }
+ }
+
+if (jump != NULL)
+ {
+ if (emptyfail)
+ add_jump(compiler, backtracks, jump);
+ else
+ JUMPHERE(jump);
+ }
+}
+
+static SLJIT_INLINE pcre_uchar *compile_ref_iterator_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+{
+DEFINE_COMPILER;
+BOOL ref = (*cc == OP_REF || *cc == OP_REFI);
+backtrack_common *backtrack;
+pcre_uchar type;
+int offset = 0;
+struct sljit_label *label;
+struct sljit_jump *zerolength;
+struct sljit_jump *jump = NULL;
+pcre_uchar *ccbegin = cc;
+int min = 0, max = 0;
+BOOL minimize;
+
+PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL);
+
+if (ref)
+ offset = GET2(cc, 1) << 1;
+else
+ cc += IMM2_SIZE;
+type = cc[1 + IMM2_SIZE];
+
+SLJIT_COMPILE_ASSERT((OP_CRSTAR & 0x1) == 0, crstar_opcode_must_be_even);
+minimize = (type & 0x1) != 0;
+switch(type)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ min = 0;
+ max = 0;
+ cc += 1 + IMM2_SIZE + 1;
+ break;
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ min = 1;
+ max = 0;
+ cc += 1 + IMM2_SIZE + 1;
+ break;
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ min = 0;
+ max = 1;
+ cc += 1 + IMM2_SIZE + 1;
+ break;
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ min = GET2(cc, 1 + IMM2_SIZE + 1);
+ max = GET2(cc, 1 + IMM2_SIZE + 1 + IMM2_SIZE);
+ cc += 1 + IMM2_SIZE + 1 + 2 * IMM2_SIZE;
+ break;
+ default:
+ SLJIT_ASSERT_STOP();
+ break;
+ }
+
+if (!minimize)
+ {
+ if (min == 0)
+ {
+ allocate_stack(common, 2);
+ if (ref)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
+ /* Temporary release of STR_PTR. */
+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+ /* Handles both invalid and empty cases. Since the minimum repeat,
+ is zero the invalid case is basically the same as an empty case. */
+ if (ref)
+ zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
+ else
+ {
+ compile_dnref_search(common, ccbegin, NULL);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, TMP2, 0);
+ zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
+ }
+ /* Restore if not zero length. */
+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+ }
+ else
+ {
+ allocate_stack(common, 1);
+ if (ref)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+ if (ref)
+ {
+ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
+ zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
+ }
+ else
+ {
+ compile_dnref_search(common, ccbegin, &backtrack->topbacktracks);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, TMP2, 0);
+ zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
+ }
+ }
+
+ if (min > 1 || max > 1)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);
+
+ label = LABEL();
+ if (!ref)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
+ compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, FALSE, FALSE);
+
+ if (min > 1 || max > 1)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
+ if (min > 1)
+ CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, label);
+ if (max > 1)
+ {
+ jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max);
+ allocate_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+ JUMPTO(SLJIT_JUMP, label);
+ JUMPHERE(jump);
+ }
+ }
+
+ if (max == 0)
+ {
+ /* Includes min > 1 case as well. */
+ allocate_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+ JUMPTO(SLJIT_JUMP, label);
+ }
+
+ JUMPHERE(zerolength);
+ BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();
+
+ count_match(common);
+ return cc;
+ }
+
+allocate_stack(common, ref ? 2 : 3);
+if (ref)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+if (type != OP_CRMINSTAR)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
+
+if (min == 0)
+ {
+ /* Handles both invalid and empty cases. Since the minimum repeat,
+ is zero the invalid case is basically the same as an empty case. */
+ if (ref)
+ zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
+ else
+ {
+ compile_dnref_search(common, ccbegin, NULL);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0);
+ zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
+ }
+ /* Length is non-zero, we can match real repeats. */
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+ jump = JUMP(SLJIT_JUMP);
+ }
+else
+ {
+ if (ref)
+ {
+ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
+ zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
+ }
+ else
+ {
+ compile_dnref_search(common, ccbegin, &backtrack->topbacktracks);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0);
+ zerolength = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
+ }
+ }
+
+BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();
+if (max > 0)
+ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));
+
+if (!ref)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2));
+compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, TRUE, TRUE);
+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+
+if (min > 1)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
+ CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, BACKTRACK_AS(iterator_backtrack)->matchingpath);
+ }
+else if (max > 0)
+ OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
+
+if (jump != NULL)
+ JUMPHERE(jump);
+JUMPHERE(zerolength);
+
+count_match(common);
+return cc;
+}
+
+static SLJIT_INLINE pcre_uchar *compile_recurse_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+{
+DEFINE_COMPILER;
+backtrack_common *backtrack;
+recurse_entry *entry = common->entries;
+recurse_entry *prev = NULL;
+sljit_sw start = GET(cc, 1);
+pcre_uchar *start_cc;
+BOOL needs_control_head;
+
+PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL);
+
+/* Inlining simple patterns. */
+if (get_framesize(common, common->start + start, NULL, TRUE, &needs_control_head) == no_stack)
+ {
+ start_cc = common->start + start;
+ compile_matchingpath(common, next_opcode(common, start_cc), bracketend(start_cc) - (1 + LINK_SIZE), backtrack);
+ BACKTRACK_AS(recurse_backtrack)->inlined_pattern = TRUE;
+ return cc + 1 + LINK_SIZE;
+ }
+
+while (entry != NULL)
+ {
+ if (entry->start == start)
+ break;
+ prev = entry;
+ entry = entry->next;
+ }
+
+if (entry == NULL)
+ {
+ entry = sljit_alloc_memory(compiler, sizeof(recurse_entry));
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ return NULL;
+ entry->next = NULL;
+ entry->entry = NULL;
+ entry->calls = NULL;
+ entry->start = start;
+
+ if (prev != NULL)
+ prev->next = entry;
+ else
+ common->entries = entry;
+ }
+
+if (common->has_set_som && common->mark_ptr != 0)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
+ allocate_stack(common, 2);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
+ }
+else if (common->has_set_som || common->mark_ptr != 0)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr);
+ allocate_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
+ }
+
+if (entry->entry == NULL)
+ add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL));
+else
+ JUMPTO(SLJIT_FAST_CALL, entry->entry);
+/* Leave if the match is failed. */
+add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0));
+return cc + 1 + LINK_SIZE;
+}
+
+static int SLJIT_CALL do_callout(struct jit_arguments* arguments, PUBL(callout_block) *callout_block, pcre_uchar **jit_ovector)
+{
+const pcre_uchar *begin = arguments->begin;
+int *offset_vector = arguments->offsets;
+int offset_count = arguments->offset_count;
+int i;
+
+if (PUBL(callout) == NULL)
+ return 0;
+
+callout_block->version = 2;
+callout_block->callout_data = arguments->callout_data;
+
+/* Offsets in subject. */
+callout_block->subject_length = arguments->end - arguments->begin;
+callout_block->start_match = (pcre_uchar*)callout_block->subject - arguments->begin;
+callout_block->current_position = (pcre_uchar*)callout_block->offset_vector - arguments->begin;
+#if defined COMPILE_PCRE8
+callout_block->subject = (PCRE_SPTR)begin;
+#elif defined COMPILE_PCRE16
+callout_block->subject = (PCRE_SPTR16)begin;
+#elif defined COMPILE_PCRE32
+callout_block->subject = (PCRE_SPTR32)begin;
+#endif
+
+/* Convert and copy the JIT offset vector to the offset_vector array. */
+callout_block->capture_top = 0;
+callout_block->offset_vector = offset_vector;
+for (i = 2; i < offset_count; i += 2)
+ {
+ offset_vector[i] = jit_ovector[i] - begin;
+ offset_vector[i + 1] = jit_ovector[i + 1] - begin;
+ if (jit_ovector[i] >= begin)
+ callout_block->capture_top = i;
+ }
+
+callout_block->capture_top = (callout_block->capture_top >> 1) + 1;
+if (offset_count > 0)
+ offset_vector[0] = -1;
+if (offset_count > 1)
+ offset_vector[1] = -1;
+return (*PUBL(callout))(callout_block);
+}
+
+/* Aligning to 8 byte. */
+#define CALLOUT_ARG_SIZE \
+ (((int)sizeof(PUBL(callout_block)) + 7) & ~7)
+
+#define CALLOUT_ARG_OFFSET(arg) \
+ (-CALLOUT_ARG_SIZE + SLJIT_OFFSETOF(PUBL(callout_block), arg))
+
+static SLJIT_INLINE pcre_uchar *compile_callout_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+{
+DEFINE_COMPILER;
+backtrack_common *backtrack;
+
+PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);
+
+allocate_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw));
+
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr);
+OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+SLJIT_ASSERT(common->capture_last_ptr != 0);
+OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, cc[1]);
+OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0);
+
+/* These pointer sized fields temporarly stores internal variables. */
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(offset_vector), STR_PTR, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(subject), TMP2, 0);
+
+if (common->mark_ptr != 0)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr));
+OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(pattern_position), SLJIT_IMM, GET(cc, 2));
+OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(next_item_length), SLJIT_IMM, GET(cc, 2 + LINK_SIZE));
+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_ptr != 0) ? TMP2 : SLJIT_IMM, 0);
+
+/* Needed to save important temporary registers. */
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);
+OP2(SLJIT_SUB, SLJIT_SCRATCH_REG2, 0, STACK_TOP, 0, SLJIT_IMM, CALLOUT_ARG_SIZE);
+GET_LOCAL_BASE(SLJIT_SCRATCH_REG3, 0, OVECTOR_START);
+sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_callout));
+OP1(SLJIT_MOV_SI, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0);
+OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
+free_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw));
+
+/* Check return value. */
+OP2(SLJIT_SUB | SLJIT_SET_S, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
+add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_C_SIG_GREATER));
+if (common->forced_quit_label == NULL)
+ add_jump(compiler, &common->forced_quit, JUMP(SLJIT_C_SIG_LESS));
+else
+ JUMPTO(SLJIT_C_SIG_LESS, common->forced_quit_label);
+return cc + 2 + 2 * LINK_SIZE;
+}
+
+#undef CALLOUT_ARG_SIZE
+#undef CALLOUT_ARG_OFFSET
+
+static pcre_uchar *compile_assert_matchingpath(compiler_common *common, pcre_uchar *cc, assert_backtrack *backtrack, BOOL conditional)
+{
+DEFINE_COMPILER;
+int framesize;
+int extrasize;
+BOOL needs_control_head;
+int private_data_ptr;
+backtrack_common altbacktrack;
+pcre_uchar *ccbegin;
+pcre_uchar opcode;
+pcre_uchar bra = OP_BRA;
+jump_list *tmp = NULL;
+jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks;
+jump_list **found;
+/* Saving previous accept variables. */
+BOOL save_local_exit = common->local_exit;
+BOOL save_positive_assert = common->positive_assert;
+then_trap_backtrack *save_then_trap = common->then_trap;
+struct sljit_label *save_quit_label = common->quit_label;
+struct sljit_label *save_accept_label = common->accept_label;
+jump_list *save_quit = common->quit;
+jump_list *save_positive_assert_quit = common->positive_assert_quit;
+jump_list *save_accept = common->accept;
+struct sljit_jump *jump;
+struct sljit_jump *brajump = NULL;
+
+/* Assert captures then. */
+common->then_trap = NULL;
+
+if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
+ {
+ SLJIT_ASSERT(!conditional);
+ bra = *cc;
+ cc++;
+ }
+private_data_ptr = PRIVATE_DATA(cc);
+SLJIT_ASSERT(private_data_ptr != 0);
+framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head);
+backtrack->framesize = framesize;
+backtrack->private_data_ptr = private_data_ptr;
+opcode = *cc;
+SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT);
+found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target;
+ccbegin = cc;
+cc += GET(cc, 1);
+
+if (bra == OP_BRAMINZERO)
+ {
+ /* This is a braminzero backtrack path. */
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ free_stack(common, 1);
+ brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
+ }
+
+if (framesize < 0)
+ {
+ extrasize = needs_control_head ? 2 : 1;
+ if (framesize == no_frame)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0);
+ allocate_stack(common, extrasize);
+ if (needs_control_head)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+ if (needs_control_head)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
+ }
+ }
+else
+ {
+ extrasize = needs_control_head ? 3 : 2;
+ allocate_stack(common, framesize + extrasize);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0);
+ if (needs_control_head)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+ if (needs_control_head)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0);
+ }
+ else
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
+ init_frame(common, ccbegin, NULL, framesize + extrasize - 1, extrasize, FALSE);
+ }
+
+memset(&altbacktrack, 0, sizeof(backtrack_common));
+if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
+ {
+ /* Negative assert is stronger than positive assert. */
+ common->local_exit = TRUE;
+ common->quit_label = NULL;
+ common->quit = NULL;
+ common->positive_assert = FALSE;
+ }
+else
+ common->positive_assert = TRUE;
+common->positive_assert_quit = NULL;
+
+while (1)
+ {
+ common->accept_label = NULL;
+ common->accept = NULL;
+ altbacktrack.top = NULL;
+ altbacktrack.topbacktracks = NULL;
+
+ if (*ccbegin == OP_ALT)
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+
+ altbacktrack.cc = ccbegin;
+ compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack);
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ {
+ if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
+ {
+ common->local_exit = save_local_exit;
+ common->quit_label = save_quit_label;
+ common->quit = save_quit;
+ }
+ common->positive_assert = save_positive_assert;
+ common->then_trap = save_then_trap;
+ common->accept_label = save_accept_label;
+ common->positive_assert_quit = save_positive_assert_quit;
+ common->accept = save_accept;
+ return NULL;
+ }
+ common->accept_label = LABEL();
+ if (common->accept != NULL)
+ set_jumps(common->accept, common->accept_label);
+
+ /* Reset stack. */
+ if (framesize < 0)
+ {
+ if (framesize == no_frame)
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ else
+ free_stack(common, extrasize);
+ if (needs_control_head)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0);
+ }
+ else
+ {
+ if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional)
+ {
+ /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */
+ OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw));
+ if (needs_control_head)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0);
+ }
+ else
+ {
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ if (needs_control_head)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_sw));
+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+ }
+ }
+
+ if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
+ {
+ /* We know that STR_PTR was stored on the top of the stack. */
+ if (conditional)
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? sizeof(sljit_sw) : 0);
+ else if (bra == OP_BRAZERO)
+ {
+ if (framesize < 0)
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw));
+ else
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + extrasize - 1) * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0);
+ }
+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+ }
+ else if (framesize >= 0)
+ {
+ /* For OP_BRA and OP_BRAMINZERO. */
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw));
+ }
+ }
+ add_jump(compiler, found, JUMP(SLJIT_JUMP));
+
+ compile_backtrackingpath(common, altbacktrack.top);
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ {
+ if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
+ {
+ common->local_exit = save_local_exit;
+ common->quit_label = save_quit_label;
+ common->quit = save_quit;
+ }
+ common->positive_assert = save_positive_assert;
+ common->then_trap = save_then_trap;
+ common->accept_label = save_accept_label;
+ common->positive_assert_quit = save_positive_assert_quit;
+ common->accept = save_accept;
+ return NULL;
+ }
+ set_jumps(altbacktrack.topbacktracks, LABEL());
+
+ if (*cc != OP_ALT)
+ break;
+
+ ccbegin = cc;
+ cc += GET(cc, 1);
+ }
+
+if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
+ {
+ SLJIT_ASSERT(common->positive_assert_quit == NULL);
+ /* Makes the check less complicated below. */
+ common->positive_assert_quit = common->quit;
+ }
+
+/* None of them matched. */
+if (common->positive_assert_quit != NULL)
+ {
+ jump = JUMP(SLJIT_JUMP);
+ set_jumps(common->positive_assert_quit, LABEL());
+ SLJIT_ASSERT(framesize != no_stack);
+ if (framesize < 0)
+ OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw));
+ else
+ {
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));
+ }
+ JUMPHERE(jump);
+ }
+
+if (needs_control_head)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(1));
+
+if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
+ {
+ /* Assert is failed. */
+ if (conditional || bra == OP_BRAZERO)
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+
+ if (framesize < 0)
+ {
+ /* The topmost item should be 0. */
+ if (bra == OP_BRAZERO)
+ {
+ if (extrasize == 2)
+ free_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+ }
+ else
+ free_stack(common, extrasize);
+ }
+ else
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1));
+ /* The topmost item should be 0. */
+ if (bra == OP_BRAZERO)
+ {
+ free_stack(common, framesize + extrasize - 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+ }
+ else
+ free_stack(common, framesize + extrasize);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0);
+ }
+ jump = JUMP(SLJIT_JUMP);
+ if (bra != OP_BRAZERO)
+ add_jump(compiler, target, jump);
+
+ /* Assert is successful. */
+ set_jumps(tmp, LABEL());
+ if (framesize < 0)
+ {
+ /* We know that STR_PTR was stored on the top of the stack. */
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw));
+ /* Keep the STR_PTR on the top of the stack. */
+ if (bra == OP_BRAZERO)
+ {
+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+ if (extrasize == 2)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+ }
+ else if (bra == OP_BRAMINZERO)
+ {
+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+ }
+ }
+ else
+ {
+ if (bra == OP_BRA)
+ {
+ /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */
+ OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 2) * sizeof(sljit_sw));
+ }
+ else
+ {
+ /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */
+ OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw));
+ if (extrasize == 2)
+ {
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ if (bra == OP_BRAMINZERO)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+ }
+ else
+ {
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0);
+ }
+ }
+ }
+
+ if (bra == OP_BRAZERO)
+ {
+ backtrack->matchingpath = LABEL();
+ SET_LABEL(jump, backtrack->matchingpath);
+ }
+ else if (bra == OP_BRAMINZERO)
+ {
+ JUMPTO(SLJIT_JUMP, backtrack->matchingpath);
+ JUMPHERE(brajump);
+ if (framesize >= 0)
+ {
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw));
+ }
+ set_jumps(backtrack->common.topbacktracks, LABEL());
+ }
+ }
+else
+ {
+ /* AssertNot is successful. */
+ if (framesize < 0)
+ {
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ if (bra != OP_BRA)
+ {
+ if (extrasize == 2)
+ free_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+ }
+ else
+ free_stack(common, extrasize);
+ }
+ else
+ {
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1));
+ /* The topmost item should be 0. */
+ if (bra != OP_BRA)
+ {
+ free_stack(common, framesize + extrasize - 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+ }
+ else
+ free_stack(common, framesize + extrasize);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0);
+ }
+
+ if (bra == OP_BRAZERO)
+ backtrack->matchingpath = LABEL();
+ else if (bra == OP_BRAMINZERO)
+ {
+ JUMPTO(SLJIT_JUMP, backtrack->matchingpath);
+ JUMPHERE(brajump);
+ }
+
+ if (bra != OP_BRA)
+ {
+ SLJIT_ASSERT(found == &backtrack->common.topbacktracks);
+ set_jumps(backtrack->common.topbacktracks, LABEL());
+ backtrack->common.topbacktracks = NULL;
+ }
+ }
+
+if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
+ {
+ common->local_exit = save_local_exit;
+ common->quit_label = save_quit_label;
+ common->quit = save_quit;
+ }
+common->positive_assert = save_positive_assert;
+common->then_trap = save_then_trap;
+common->accept_label = save_accept_label;
+common->positive_assert_quit = save_positive_assert_quit;
+common->accept = save_accept;
+return cc + 1 + LINK_SIZE;
+}
+
+static SLJIT_INLINE void match_once_common(compiler_common *common, pcre_uchar ket, int framesize, int private_data_ptr, BOOL has_alternatives, BOOL needs_control_head)
+{
+DEFINE_COMPILER;
+int stacksize;
+
+if (framesize < 0)
+ {
+ if (framesize == no_frame)
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ else
+ {
+ stacksize = needs_control_head ? 1 : 0;
+ if (ket != OP_KET || has_alternatives)
+ stacksize++;
+ free_stack(common, stacksize);
+ }
+
+ if (needs_control_head)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), (ket != OP_KET || has_alternatives) ? sizeof(sljit_sw) : 0);
+
+ /* TMP2 which is set here used by OP_KETRMAX below. */
+ if (ket == OP_KETRMAX)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0);
+ else if (ket == OP_KETRMIN)
+ {
+ /* Move the STR_PTR to the private_data_ptr. */
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), 0);
+ }
+ }
+else
+ {
+ stacksize = (ket != OP_KET || has_alternatives) ? 2 : 1;
+ OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + stacksize) * sizeof(sljit_sw));
+ if (needs_control_head)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), 0);
+
+ if (ket == OP_KETRMAX)
+ {
+ /* TMP2 which is set here used by OP_KETRMAX below. */
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ }
+ }
+if (needs_control_head)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP1, 0);
+}
+
+static SLJIT_INLINE int match_capture_common(compiler_common *common, int stacksize, int offset, int private_data_ptr)
+{
+DEFINE_COMPILER;
+
+if (common->capture_last_ptr != 0)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, offset >> 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);
+ stacksize++;
+ }
+if (common->optimized_cbracket[offset >> 1] == 0)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
+ stacksize += 2;
+ }
+return stacksize;
+}
+
+/*
+ Handling bracketed expressions is probably the most complex part.
+
+ Stack layout naming characters:
+ S - Push the current STR_PTR
+ 0 - Push a 0 (NULL)
+ A - Push the current STR_PTR. Needed for restoring the STR_PTR
+ before the next alternative. Not pushed if there are no alternatives.
+ M - Any values pushed by the current alternative. Can be empty, or anything.
+ C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack.
+ L - Push the previous local (pointed by localptr) to the stack
+ () - opional values stored on the stack
+ ()* - optonal, can be stored multiple times
+
+ The following list shows the regular expression templates, their PCRE byte codes
+ and stack layout supported by pcre-sljit.
+
+ (?:) OP_BRA | OP_KET A M
+ () OP_CBRA | OP_KET C M
+ (?:)+ OP_BRA | OP_KETRMAX 0 A M S ( A M S )*
+ OP_SBRA | OP_KETRMAX 0 L M S ( L M S )*
+ (?:)+? OP_BRA | OP_KETRMIN 0 A M S ( A M S )*
+ OP_SBRA | OP_KETRMIN 0 L M S ( L M S )*
+ ()+ OP_CBRA | OP_KETRMAX 0 C M S ( C M S )*
+ OP_SCBRA | OP_KETRMAX 0 C M S ( C M S )*
+ ()+? OP_CBRA | OP_KETRMIN 0 C M S ( C M S )*
+ OP_SCBRA | OP_KETRMIN 0 C M S ( C M S )*
+ (?:)? OP_BRAZERO | OP_BRA | OP_KET S ( A M 0 )
+ (?:)?? OP_BRAMINZERO | OP_BRA | OP_KET S ( A M 0 )
+ ()? OP_BRAZERO | OP_CBRA | OP_KET S ( C M 0 )
+ ()?? OP_BRAMINZERO | OP_CBRA | OP_KET S ( C M 0 )
+ (?:)* OP_BRAZERO | OP_BRA | OP_KETRMAX S 0 ( A M S )*
+ OP_BRAZERO | OP_SBRA | OP_KETRMAX S 0 ( L M S )*
+ (?:)*? OP_BRAMINZERO | OP_BRA | OP_KETRMIN S 0 ( A M S )*
+ OP_BRAMINZERO | OP_SBRA | OP_KETRMIN S 0 ( L M S )*
+ ()* OP_BRAZERO | OP_CBRA | OP_KETRMAX S 0 ( C M S )*
+ OP_BRAZERO | OP_SCBRA | OP_KETRMAX S 0 ( C M S )*
+ ()*? OP_BRAMINZERO | OP_CBRA | OP_KETRMIN S 0 ( C M S )*
+ OP_BRAMINZERO | OP_SCBRA | OP_KETRMIN S 0 ( C M S )*
+
+
+ Stack layout naming characters:
+ A - Push the alternative index (starting from 0) on the stack.
+ Not pushed if there is no alternatives.
+ M - Any values pushed by the current alternative. Can be empty, or anything.
+
+ The next list shows the possible content of a bracket:
+ (|) OP_*BRA | OP_ALT ... M A
+ (?()|) OP_*COND | OP_ALT M A
+ (?>|) OP_ONCE | OP_ALT ... [stack trace] M A
+ (?>|) OP_ONCE_NC | OP_ALT ... [stack trace] M A
+ Or nothing, if trace is unnecessary
+*/
+
+static pcre_uchar *compile_bracket_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+{
+DEFINE_COMPILER;
+backtrack_common *backtrack;
+pcre_uchar opcode;
+int private_data_ptr = 0;
+int offset = 0;
+int i, stacksize;
+int repeat_ptr = 0, repeat_length = 0;
+int repeat_type = 0, repeat_count = 0;
+pcre_uchar *ccbegin;
+pcre_uchar *matchingpath;
+pcre_uchar *slot;
+pcre_uchar bra = OP_BRA;
+pcre_uchar ket;
+assert_backtrack *assert;
+BOOL has_alternatives;
+BOOL needs_control_head = FALSE;
+struct sljit_jump *jump;
+struct sljit_jump *skip;
+struct sljit_label *rmax_label = NULL;
+struct sljit_jump *braminzero = NULL;
+
+PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL);
+
+if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
+ {
+ bra = *cc;
+ cc++;
+ opcode = *cc;
+ }
+
+opcode = *cc;
+ccbegin = cc;
+matchingpath = bracketend(cc) - 1 - LINK_SIZE;
+ket = *matchingpath;
+if (ket == OP_KET && PRIVATE_DATA(matchingpath) != 0)
+ {
+ repeat_ptr = PRIVATE_DATA(matchingpath);
+ repeat_length = PRIVATE_DATA(matchingpath + 1);
+ repeat_type = PRIVATE_DATA(matchingpath + 2);
+ repeat_count = PRIVATE_DATA(matchingpath + 3);
+ SLJIT_ASSERT(repeat_length != 0 && repeat_type != 0 && repeat_count != 0);
+ if (repeat_type == OP_UPTO)
+ ket = OP_KETRMAX;
+ if (repeat_type == OP_MINUPTO)
+ ket = OP_KETRMIN;
+ }
+
+if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF)
+ {
+ /* Drop this bracket_backtrack. */
+ parent->top = backtrack->prev;
+ return matchingpath + 1 + LINK_SIZE + repeat_length;
+ }
+
+matchingpath = ccbegin + 1 + LINK_SIZE;
+SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);
+SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));
+cc += GET(cc, 1);
+
+has_alternatives = *cc == OP_ALT;
+if (SLJIT_UNLIKELY(opcode == OP_COND || opcode == OP_SCOND))
+ has_alternatives = (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF) ? FALSE : TRUE;
+
+if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
+ opcode = OP_SCOND;
+if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC))
+ opcode = OP_ONCE;
+
+if (opcode == OP_CBRA || opcode == OP_SCBRA)
+ {
+ /* Capturing brackets has a pre-allocated space. */
+ offset = GET2(ccbegin, 1 + LINK_SIZE);
+ if (common->optimized_cbracket[offset] == 0)
+ {
+ private_data_ptr = OVECTOR_PRIV(offset);
+ offset <<= 1;
+ }
+ else
+ {
+ offset <<= 1;
+ private_data_ptr = OVECTOR(offset);
+ }
+ BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr;
+ matchingpath += IMM2_SIZE;
+ }
+else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND)
+ {
+ /* Other brackets simply allocate the next entry. */
+ private_data_ptr = PRIVATE_DATA(ccbegin);
+ SLJIT_ASSERT(private_data_ptr != 0);
+ BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr;
+ if (opcode == OP_ONCE)
+ BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, NULL, FALSE, &needs_control_head);
+ }
+
+/* Instructions before the first alternative. */
+stacksize = 0;
+if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
+ stacksize++;
+if (bra == OP_BRAZERO)
+ stacksize++;
+
+if (stacksize > 0)
+ allocate_stack(common, stacksize);
+
+stacksize = 0;
+if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
+ stacksize++;
+ }
+
+if (bra == OP_BRAZERO)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
+
+if (bra == OP_BRAMINZERO)
+ {
+ /* This is a backtrack path! (Since the try-path of OP_BRAMINZERO matches to the empty string) */
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ if (ket != OP_KETRMIN)
+ {
+ free_stack(common, 1);
+ braminzero = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
+ }
+ else
+ {
+ if (opcode == OP_ONCE || opcode >= OP_SBRA)
+ {
+ jump = CMP(SLJIT_C_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_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ }
+ else
+ {
+ /* Except when the whole stack frame must be saved. */
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ braminzero = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw));
+ }
+ JUMPHERE(skip);
+ }
+ else
+ {
+ jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
+ JUMPHERE(jump);
+ }
+ }
+ }
+
+if (repeat_type != 0)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, repeat_count);
+ if (repeat_type == OP_EXACT)
+ rmax_label = LABEL();
+ }
+
+if (ket == OP_KETRMIN)
+ BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();
+
+if (ket == OP_KETRMAX)
+ {
+ rmax_label = LABEL();
+ if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA && repeat_type == 0)
+ BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmax_label;
+ }
+
+/* Handling capturing brackets and alternatives. */
+if (opcode == OP_ONCE)
+ {
+ stacksize = 0;
+ if (needs_control_head)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
+ stacksize++;
+ }
+
+ if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0)
+ {
+ /* Neither capturing brackets nor recursions are found in the block. */
+ if (ket == OP_KETRMIN)
+ {
+ stacksize += 2;
+ if (!needs_control_head)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ }
+ else
+ {
+ if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0);
+ if (ket == OP_KETRMAX || has_alternatives)
+ stacksize++;
+ }
+
+ if (stacksize > 0)
+ allocate_stack(common, stacksize);
+
+ stacksize = 0;
+ if (needs_control_head)
+ {
+ stacksize++;
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
+ }
+
+ if (ket == OP_KETRMIN)
+ {
+ if (needs_control_head)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
+ if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame)
+ OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, needs_control_head ? (2 * sizeof(sljit_sw)) : sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0);
+ }
+ else if (ket == OP_KETRMAX || has_alternatives)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
+ }
+ else
+ {
+ if (ket != OP_KET || has_alternatives)
+ stacksize++;
+
+ stacksize += BACKTRACK_AS(bracket_backtrack)->u.framesize + 1;
+ allocate_stack(common, stacksize);
+
+ if (needs_control_head)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
+
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));
+
+ stacksize = needs_control_head ? 1 : 0;
+ if (ket != OP_KET || has_alternatives)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0);
+ stacksize++;
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);
+ }
+ else
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);
+ }
+ init_frame(common, ccbegin, NULL, BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize, stacksize + 1, FALSE);
+ }
+ }
+else if (opcode == OP_CBRA || opcode == OP_SCBRA)
+ {
+ /* Saving the previous values. */
+ if (common->optimized_cbracket[offset >> 1] != 0)
+ {
+ SLJIT_ASSERT(private_data_ptr == OVECTOR(offset));
+ allocate_stack(common, 2);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr + sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
+ }
+ else
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ allocate_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
+ }
+ }
+else if (opcode == OP_SBRA || opcode == OP_SCOND)
+ {
+ /* Saving the previous value. */
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ allocate_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
+ }
+else if (has_alternatives)
+ {
+ /* Pushing the starting string pointer. */
+ allocate_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+ }
+
+/* Generating code for the first alternative. */
+if (opcode == OP_COND || opcode == OP_SCOND)
+ {
+ if (*matchingpath == OP_CREF)
+ {
+ SLJIT_ASSERT(has_alternatives);
+ add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed),
+ CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(matchingpath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
+ matchingpath += 1 + IMM2_SIZE;
+ }
+ else if (*matchingpath == OP_DNCREF)
+ {
+ SLJIT_ASSERT(has_alternatives);
+
+ i = GET2(matchingpath, 1 + IMM2_SIZE);
+ slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size;
+ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
+ OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(slot, 0) << 1), TMP1, 0);
+ slot += common->name_entry_size;
+ i--;
+ while (i-- > 0)
+ {
+ OP2(SLJIT_SUB, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(slot, 0) << 1), TMP1, 0);
+ OP2(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, STR_PTR, 0);
+ slot += common->name_entry_size;
+ }
+ OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
+ add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), JUMP(SLJIT_C_ZERO));
+ matchingpath += 1 + 2 * IMM2_SIZE;
+ }
+ else if (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF)
+ {
+ /* Never has other case. */
+ BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL;
+ SLJIT_ASSERT(!has_alternatives);
+
+ if (*matchingpath == OP_RREF)
+ {
+ stacksize = GET2(matchingpath, 1);
+ if (common->currententry == NULL)
+ stacksize = 0;
+ else if (stacksize == RREF_ANY)
+ stacksize = 1;
+ else if (common->currententry->start == 0)
+ stacksize = stacksize == 0;
+ else
+ stacksize = stacksize == (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE);
+
+ if (stacksize != 0)
+ matchingpath += 1 + IMM2_SIZE;
+ }
+ else
+ {
+ if (common->currententry == NULL || common->currententry->start == 0)
+ stacksize = 0;
+ else
+ {
+ stacksize = GET2(matchingpath, 1 + IMM2_SIZE);
+ slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size;
+ i = (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE);
+ while (stacksize > 0)
+ {
+ if ((int)GET2(slot, 0) == i)
+ break;
+ slot += common->name_entry_size;
+ stacksize--;
+ }
+ }
+
+ if (stacksize != 0)
+ matchingpath += 1 + 2 * IMM2_SIZE;
+ }
+
+ /* The stacksize == 0 is a common "else" case. */
+ if (stacksize == 0)
+ {
+ if (*cc == OP_ALT)
+ {
+ matchingpath = cc + 1 + LINK_SIZE;
+ cc += GET(cc, 1);
+ }
+ else
+ matchingpath = cc;
+ }
+ }
+ else
+ {
+ SLJIT_ASSERT(has_alternatives && *matchingpath >= OP_ASSERT && *matchingpath <= OP_ASSERTBACK_NOT);
+ /* Similar code as PUSH_BACKTRACK macro. */
+ assert = sljit_alloc_memory(compiler, sizeof(assert_backtrack));
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ return NULL;
+ memset(assert, 0, sizeof(assert_backtrack));
+ assert->common.cc = matchingpath;
+ BACKTRACK_AS(bracket_backtrack)->u.assert = assert;
+ matchingpath = compile_assert_matchingpath(common, matchingpath, assert, TRUE);
+ }
+ }
+
+compile_matchingpath(common, matchingpath, cc, backtrack);
+if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ return NULL;
+
+if (opcode == OP_ONCE)
+ match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);
+
+stacksize = 0;
+if (repeat_type == OP_MINUPTO)
+ {
+ /* We need to preserve the counter. TMP2 will be used below. */
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr);
+ stacksize++;
+ }
+if (ket != OP_KET || bra != OP_BRA)
+ stacksize++;
+if (offset != 0)
+ {
+ if (common->capture_last_ptr != 0)
+ stacksize++;
+ if (common->optimized_cbracket[offset >> 1] == 0)
+ stacksize += 2;
+ }
+if (has_alternatives && opcode != OP_ONCE)
+ stacksize++;
+
+if (stacksize > 0)
+ allocate_stack(common, stacksize);
+
+stacksize = 0;
+if (repeat_type == OP_MINUPTO)
+ {
+ /* TMP2 was set above. */
+ OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);
+ stacksize++;
+ }
+
+if (ket != OP_KET || bra != OP_BRA)
+ {
+ if (ket != OP_KET)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
+ else
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
+ stacksize++;
+ }
+
+if (offset != 0)
+ stacksize = match_capture_common(common, stacksize, offset, private_data_ptr);
+
+if (has_alternatives)
+ {
+ if (opcode != OP_ONCE)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
+ if (ket != OP_KETRMAX)
+ BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
+ }
+
+/* Must be after the matchingpath label. */
+if (offset != 0 && common->optimized_cbracket[offset >> 1] != 0)
+ {
+ SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
+ }
+
+if (ket == OP_KETRMAX)
+ {
+ if (repeat_type != 0)
+ {
+ if (has_alternatives)
+ BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
+ JUMPTO(SLJIT_C_NOT_ZERO, rmax_label);
+ /* Drop STR_PTR for greedy plus quantifier. */
+ if (opcode != OP_ONCE)
+ free_stack(common, 1);
+ }
+ else if (opcode == OP_ONCE || opcode >= OP_SBRA)
+ {
+ if (has_alternatives)
+ BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
+ /* Checking zero-length iteration. */
+ if (opcode != OP_ONCE)
+ {
+ CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0, rmax_label);
+ /* Drop STR_PTR for greedy plus quantifier. */
+ if (bra != OP_BRAZERO)
+ free_stack(common, 1);
+ }
+ else
+ /* TMP2 must contain the starting STR_PTR. */
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmax_label);
+ }
+ else
+ JUMPTO(SLJIT_JUMP, rmax_label);
+ BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL();
+ }
+
+if (repeat_type == OP_EXACT)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
+ JUMPTO(SLJIT_C_NOT_ZERO, rmax_label);
+ }
+else if (repeat_type == OP_UPTO)
+ {
+ /* We need to preserve the counter. */
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr);
+ allocate_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
+ }
+
+if (bra == OP_BRAZERO)
+ BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL();
+
+if (bra == OP_BRAMINZERO)
+ {
+ /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */
+ JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->matchingpath);
+ if (braminzero != NULL)
+ {
+ JUMPHERE(braminzero);
+ /* We need to release the end pointer to perform the
+ backtrack for the zero-length iteration. When
+ framesize is < 0, OP_ONCE will do the release itself. */
+ if (opcode == OP_ONCE && BACKTRACK_AS(bracket_backtrack)->u.framesize >= 0)
+ {
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+ }
+ else if (ket == OP_KETRMIN && opcode != OP_ONCE)
+ free_stack(common, 1);
+ }
+ /* Continue to the normal backtrack. */
+ }
+
+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;
+
+/* Temporarily encoding the needs_control_head in framesize. */
+if (opcode == OP_ONCE)
+ BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);
+return cc + repeat_length;
+}
+
+static pcre_uchar *compile_bracketpos_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+{
+DEFINE_COMPILER;
+backtrack_common *backtrack;
+pcre_uchar opcode;
+int private_data_ptr;
+int cbraprivptr = 0;
+BOOL needs_control_head;
+int framesize;
+int stacksize;
+int offset = 0;
+BOOL zero = FALSE;
+pcre_uchar *ccbegin = NULL;
+int stack; /* Also contains the offset of control head. */
+struct sljit_label *loop = NULL;
+struct jump_list *emptymatch = NULL;
+
+PUSH_BACKTRACK(sizeof(bracketpos_backtrack), cc, NULL);
+if (*cc == OP_BRAPOSZERO)
+ {
+ zero = TRUE;
+ cc++;
+ }
+
+opcode = *cc;
+private_data_ptr = PRIVATE_DATA(cc);
+SLJIT_ASSERT(private_data_ptr != 0);
+BACKTRACK_AS(bracketpos_backtrack)->private_data_ptr = private_data_ptr;
+switch(opcode)
+ {
+ case OP_BRAPOS:
+ case OP_SBRAPOS:
+ ccbegin = cc + 1 + LINK_SIZE;
+ break;
+
+ case OP_CBRAPOS:
+ case OP_SCBRAPOS:
+ offset = GET2(cc, 1 + LINK_SIZE);
+ /* This case cannot be optimized in the same was as
+ normal capturing brackets. */
+ SLJIT_ASSERT(common->optimized_cbracket[offset] == 0);
+ cbraprivptr = OVECTOR_PRIV(offset);
+ offset <<= 1;
+ ccbegin = cc + 1 + LINK_SIZE + IMM2_SIZE;
+ break;
+
+ default:
+ SLJIT_ASSERT_STOP();
+ break;
+ }
+
+framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head);
+BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize;
+if (framesize < 0)
+ {
+ if (offset != 0)
+ {
+ stacksize = 2;
+ if (common->capture_last_ptr != 0)
+ stacksize++;
+ }
+ else
+ stacksize = 1;
+
+ if (needs_control_head)
+ stacksize++;
+ if (!zero)
+ stacksize++;
+
+ BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;
+ allocate_stack(common, stacksize);
+ if (framesize == no_frame)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0);
+
+ stack = 0;
+ if (offset != 0)
+ {
+ stack = 2;
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
+ if (common->capture_last_ptr != 0)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
+ if (needs_control_head)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
+ if (common->capture_last_ptr != 0)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);
+ stack = 3;
+ }
+ }
+ else
+ {
+ if (needs_control_head)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+ stack = 1;
+ }
+
+ if (needs_control_head)
+ stack++;
+ if (!zero)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), SLJIT_IMM, 1);
+ if (needs_control_head)
+ {
+ stack--;
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0);
+ }
+ }
+else
+ {
+ stacksize = framesize + 1;
+ if (!zero)
+ stacksize++;
+ if (needs_control_head)
+ stacksize++;
+ if (offset == 0)
+ stacksize++;
+ BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize;
+
+ allocate_stack(common, stacksize);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ if (needs_control_head)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
+ OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1));
+
+ stack = 0;
+ if (!zero)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1);
+ stack = 1;
+ }
+ if (needs_control_head)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0);
+ stack++;
+ }
+ if (offset == 0)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0);
+ stack++;
+ }
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0);
+ init_frame(common, cc, NULL, stacksize - 1, stacksize - framesize, FALSE);
+ stack -= 1 + (offset == 0);
+ }
+
+if (offset != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
+
+loop = LABEL();
+while (*cc != OP_KETRPOS)
+ {
+ backtrack->top = NULL;
+ backtrack->topbacktracks = NULL;
+ cc += GET(cc, 1);
+
+ compile_matchingpath(common, ccbegin, cc, backtrack);
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ return NULL;
+
+ if (framesize < 0)
+ {
+ if (framesize == no_frame)
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+
+ if (offset != 0)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
+ if (common->capture_last_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, offset >> 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
+ }
+ else
+ {
+ if (opcode == OP_SBRAPOS)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+ }
+
+ if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
+ add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0));
+
+ if (!zero)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);
+ }
+ else
+ {
+ if (offset != 0)
+ {
+ OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, stacksize * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
+ if (common->capture_last_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, offset >> 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
+ }
+ else
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ OP2(SLJIT_ADD, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw));
+ if (opcode == OP_SBRAPOS)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw), STR_PTR, 0);
+ }
+
+ if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
+ add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0));
+
+ if (!zero)
+ {
+ if (framesize < 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);
+ else
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+ }
+ }
+
+ if (needs_control_head)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack));
+
+ JUMPTO(SLJIT_JUMP, loop);
+ flush_stubs(common);
+
+ compile_backtrackingpath(common, backtrack->top);
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ return NULL;
+ set_jumps(backtrack->topbacktracks, LABEL());
+
+ if (framesize < 0)
+ {
+ if (offset != 0)
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
+ else
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ }
+ else
+ {
+ if (offset != 0)
+ {
+ /* Last alternative. */
+ if (*cc == OP_KETRPOS)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
+ }
+ else
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw));
+ }
+ }
+
+ if (*cc == OP_KETRPOS)
+ break;
+ ccbegin = cc + 1 + LINK_SIZE;
+ }
+
+/* We don't have to restore the control head in case of a failed match. */
+
+backtrack->topbacktracks = NULL;
+if (!zero)
+ {
+ if (framesize < 0)
+ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0));
+ else /* TMP2 is set to [private_data_ptr] above. */
+ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_sw), SLJIT_IMM, 0));
+ }
+
+/* None of them matched. */
+set_jumps(emptymatch, LABEL());
+count_match(common);
+return cc + 1 + LINK_SIZE;
+}
+
+static SLJIT_INLINE pcre_uchar *get_iterator_parameters(compiler_common *common, pcre_uchar *cc, pcre_uchar *opcode, pcre_uchar *type, int *max, int *min, pcre_uchar **end)
+{
+int class_len;
+
+*opcode = *cc;
+if (*opcode >= OP_STAR && *opcode <= OP_POSUPTO)
+ {
+ cc++;
+ *type = OP_CHAR;
+ }
+else if (*opcode >= OP_STARI && *opcode <= OP_POSUPTOI)
+ {
+ cc++;
+ *type = OP_CHARI;
+ *opcode -= OP_STARI - OP_STAR;
+ }
+else if (*opcode >= OP_NOTSTAR && *opcode <= OP_NOTPOSUPTO)
+ {
+ cc++;
+ *type = OP_NOT;
+ *opcode -= OP_NOTSTAR - OP_STAR;
+ }
+else if (*opcode >= OP_NOTSTARI && *opcode <= OP_NOTPOSUPTOI)
+ {
+ cc++;
+ *type = OP_NOTI;
+ *opcode -= OP_NOTSTARI - OP_STAR;
+ }
+else if (*opcode >= OP_TYPESTAR && *opcode <= OP_TYPEPOSUPTO)
+ {
+ cc++;
+ *opcode -= OP_TYPESTAR - OP_STAR;
+ *type = 0;
+ }
+else
+ {
+ SLJIT_ASSERT(*opcode == OP_CLASS || *opcode == OP_NCLASS || *opcode == OP_XCLASS);
+ *type = *opcode;
+ cc++;
+ class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0);
+ *opcode = cc[class_len - 1];
+ if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY)
+ {
+ *opcode -= OP_CRSTAR - OP_STAR;
+ if (end != NULL)
+ *end = cc + class_len;
+ }
+ else if (*opcode >= OP_CRPOSSTAR && *opcode <= OP_CRPOSQUERY)
+ {
+ *opcode -= OP_CRPOSSTAR - OP_POSSTAR;
+ if (end != NULL)
+ *end = cc + class_len;
+ }
+ else
+ {
+ SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE || *opcode == OP_CRPOSRANGE);
+ *max = GET2(cc, (class_len + IMM2_SIZE));
+ *min = GET2(cc, class_len);
+
+ if (*min == 0)
+ {
+ SLJIT_ASSERT(*max != 0);
+ *opcode = (*opcode == OP_CRRANGE) ? OP_UPTO : (*opcode == OP_CRMINRANGE ? OP_MINUPTO : OP_POSUPTO);
+ }
+ if (*max == *min)
+ *opcode = OP_EXACT;
+
+ if (end != NULL)
+ *end = cc + class_len + 2 * IMM2_SIZE;
+ }
+ return cc;
+ }
+
+if (*opcode == OP_UPTO || *opcode == OP_MINUPTO || *opcode == OP_EXACT || *opcode == OP_POSUPTO)
+ {
+ *max = GET2(cc, 0);
+ cc += IMM2_SIZE;
+ }
+
+if (*type == 0)
+ {
+ *type = *cc;
+ if (end != NULL)
+ *end = next_opcode(common, cc);
+ cc++;
+ return cc;
+ }
+
+if (end != NULL)
+ {
+ *end = cc + 1;
+#ifdef SUPPORT_UTF
+ if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc);
+#endif
+ }
+return cc;
+}
+
+static pcre_uchar *compile_iterator_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+{
+DEFINE_COMPILER;
+backtrack_common *backtrack;
+pcre_uchar opcode;
+pcre_uchar type;
+int max = -1, min = -1;
+pcre_uchar* end;
+jump_list *nomatch = NULL;
+struct sljit_jump *jump = NULL;
+struct sljit_label *label;
+int private_data_ptr = PRIVATE_DATA(cc);
+int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_LOCALS_REG);
+int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr;
+int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw);
+int tmp_base, tmp_offset;
+
+PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL);
+
+cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &min, &end);
+
+switch(type)
+ {
+ case OP_NOT_DIGIT:
+ case OP_DIGIT:
+ case OP_NOT_WHITESPACE:
+ case OP_WHITESPACE:
+ case OP_NOT_WORDCHAR:
+ case OP_WORDCHAR:
+ case OP_ANY:
+ case OP_ALLANY:
+ case OP_ANYBYTE:
+ case OP_ANYNL:
+ case OP_NOT_HSPACE:
+ case OP_HSPACE:
+ case OP_NOT_VSPACE:
+ case OP_VSPACE:
+ case OP_CHAR:
+ case OP_CHARI:
+ case OP_NOT:
+ case OP_NOTI:
+ case OP_CLASS:
+ case OP_NCLASS:
+ tmp_base = TMP3;
+ tmp_offset = 0;
+ break;
+
+ default:
+ SLJIT_ASSERT_STOP();
+ /* Fall through. */
+
+ case OP_EXTUNI:
+ case OP_XCLASS:
+ case OP_NOTPROP:
+ case OP_PROP:
+ tmp_base = SLJIT_MEM1(SLJIT_LOCALS_REG);
+ tmp_offset = POSSESSIVE0;
+ break;
+ }
+
+switch(opcode)
+ {
+ case OP_STAR:
+ case OP_PLUS:
+ case OP_UPTO:
+ case OP_CRRANGE:
+ if (type == OP_ANYNL || type == OP_EXTUNI)
+ {
+ SLJIT_ASSERT(private_data_ptr == 0);
+ if (opcode == OP_STAR || opcode == OP_UPTO)
+ {
+ allocate_stack(common, 2);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
+ }
+ else
+ {
+ allocate_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+ }
+
+ if (opcode == OP_UPTO || opcode == OP_CRRANGE)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);
+
+ label = LABEL();
+ compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks);
+ if (opcode == OP_UPTO || opcode == OP_CRRANGE)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+ if (opcode == OP_CRRANGE && min > 0)
+ CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, label);
+ if (opcode == OP_UPTO || (opcode == OP_CRRANGE && max > 0))
+ jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
+ }
+
+ /* We cannot use TMP3 because of this allocate_stack. */
+ allocate_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+ JUMPTO(SLJIT_JUMP, label);
+ if (jump != NULL)
+ JUMPHERE(jump);
+ }
+ else
+ {
+ if (opcode == OP_PLUS)
+ compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks);
+ if (private_data_ptr == 0)
+ allocate_stack(common, 2);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ if (opcode <= OP_PLUS)
+ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
+ else
+ OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, 1);
+ label = LABEL();
+ compile_char1_matchingpath(common, type, cc, &nomatch);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ if (opcode <= OP_PLUS)
+ JUMPTO(SLJIT_JUMP, label);
+ else if (opcode == OP_CRRANGE && max == 0)
+ {
+ OP2(SLJIT_ADD, base, offset1, base, offset1, SLJIT_IMM, 1);
+ JUMPTO(SLJIT_JUMP, label);
+ }
+ else
+ {
+ OP1(SLJIT_MOV, TMP1, 0, base, offset1);
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+ OP1(SLJIT_MOV, base, offset1, TMP1, 0);
+ CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, max + 1, label);
+ }
+ set_jumps(nomatch, LABEL());
+ if (opcode == OP_CRRANGE)
+ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_LESS, base, offset1, SLJIT_IMM, min + 1));
+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
+ }
+ BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();
+ break;
+
+ case OP_MINSTAR:
+ case OP_MINPLUS:
+ if (opcode == OP_MINPLUS)
+ compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks);
+ if (private_data_ptr == 0)
+ allocate_stack(common, 1);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();
+ break;
+
+ case OP_MINUPTO:
+ case OP_CRMINRANGE:
+ if (private_data_ptr == 0)
+ allocate_stack(common, 2);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, 1);
+ if (opcode == OP_CRMINRANGE)
+ add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
+ BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();
+ break;
+
+ case OP_QUERY:
+ case OP_MINQUERY:
+ if (private_data_ptr == 0)
+ allocate_stack(common, 1);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ if (opcode == OP_QUERY)
+ compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks);
+ BACKTRACK_AS(iterator_backtrack)->matchingpath = LABEL();
+ break;
+
+ case OP_EXACT:
+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
+ label = LABEL();
+ compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks);
+ OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ JUMPTO(SLJIT_C_NOT_ZERO, label);
+ break;
+
+ case OP_POSSTAR:
+ case OP_POSPLUS:
+ case OP_POSUPTO:
+ if (opcode == OP_POSPLUS)
+ compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks);
+ if (opcode == OP_POSUPTO)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, SLJIT_IMM, max);
+ OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
+ label = LABEL();
+ compile_char1_matchingpath(common, type, cc, &nomatch);
+ OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
+ if (opcode != OP_POSUPTO)
+ JUMPTO(SLJIT_JUMP, label);
+ else
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, SLJIT_IMM, 1);
+ JUMPTO(SLJIT_C_NOT_ZERO, label);
+ }
+ set_jumps(nomatch, LABEL());
+ OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);
+ break;
+
+ case OP_POSQUERY:
+ OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
+ compile_char1_matchingpath(common, type, cc, &nomatch);
+ OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
+ set_jumps(nomatch, LABEL());
+ OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);
+ break;
+
+ case OP_CRPOSRANGE:
+ /* Combination of OP_EXACT and OP_POSSTAR or OP_POSUPTO */
+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, min);
+ label = LABEL();
+ compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks);
+ OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ JUMPTO(SLJIT_C_NOT_ZERO, label);
+
+ if (max != 0)
+ {
+ SLJIT_ASSERT(max - min > 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, SLJIT_IMM, max - min);
+ }
+ OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
+ label = LABEL();
+ compile_char1_matchingpath(common, type, cc, &nomatch);
+ OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
+ if (max == 0)
+ JUMPTO(SLJIT_JUMP, label);
+ else
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, SLJIT_IMM, 1);
+ JUMPTO(SLJIT_C_NOT_ZERO, label);
+ }
+ set_jumps(nomatch, LABEL());
+ OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);
+ break;
+
+ default:
+ SLJIT_ASSERT_STOP();
+ break;
+ }
+
+count_match(common);
+return end;
+}
+
+static SLJIT_INLINE pcre_uchar *compile_fail_accept_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+{
+DEFINE_COMPILER;
+backtrack_common *backtrack;
+
+PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);
+
+if (*cc == OP_FAIL)
+ {
+ add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
+ return cc + 1;
+ }
+
+if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL || !common->might_be_empty)
+ {
+ /* No need to check notempty conditions. */
+ if (common->accept_label == NULL)
+ add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));
+ else
+ JUMPTO(SLJIT_JUMP, common->accept_label);
+ return cc + 1;
+ }
+
+if (common->accept_label == NULL)
+ add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)));
+else
+ CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), common->accept_label);
+OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
+add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
+if (common->accept_label == NULL)
+ add_jump(compiler, &common->accept, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+else
+ CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, common->accept_label);
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+if (common->accept_label == NULL)
+ add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0));
+else
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->accept_label);
+add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
+return cc + 1;
+}
+
+static SLJIT_INLINE pcre_uchar *compile_close_matchingpath(compiler_common *common, pcre_uchar *cc)
+{
+DEFINE_COMPILER;
+int offset = GET2(cc, 1);
+BOOL optimized_cbracket = common->optimized_cbracket[offset] != 0;
+
+/* Data will be discarded anyway... */
+if (common->currententry != NULL)
+ return cc + 1 + IMM2_SIZE;
+
+if (!optimized_cbracket)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR_PRIV(offset));
+offset <<= 1;
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
+if (!optimized_cbracket)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
+return cc + 1 + IMM2_SIZE;
+}
+
+static SLJIT_INLINE pcre_uchar *compile_control_verb_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+{
+DEFINE_COMPILER;
+backtrack_common *backtrack;
+pcre_uchar opcode = *cc;
+pcre_uchar *ccend = cc + 1;
+
+if (opcode == OP_PRUNE_ARG || opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG)
+ ccend += 2 + cc[1];
+
+PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);
+
+if (opcode == OP_SKIP)
+ {
+ allocate_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+ return ccend;
+ }
+
+if (opcode == OP_PRUNE_ARG || opcode == OP_THEN_ARG)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
+ }
+
+return ccend;
+}
+
+static pcre_uchar then_trap_opcode[1] = { OP_THEN_TRAP };
+
+static SLJIT_INLINE void compile_then_trap_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent)
+{
+DEFINE_COMPILER;
+backtrack_common *backtrack;
+BOOL needs_control_head;
+int size;
+
+PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc);
+common->then_trap = BACKTRACK_AS(then_trap_backtrack);
+BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode;
+BACKTRACK_AS(then_trap_backtrack)->start = (sljit_sw)(cc - common->start);
+BACKTRACK_AS(then_trap_backtrack)->framesize = get_framesize(common, cc, ccend, FALSE, &needs_control_head);
+
+size = BACKTRACK_AS(then_trap_backtrack)->framesize;
+size = 3 + (size < 0 ? 0 : size);
+
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
+allocate_stack(common, size);
+if (size > 3)
+ OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 3) * sizeof(sljit_sw));
+else
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 1), SLJIT_IMM, BACKTRACK_AS(then_trap_backtrack)->start);
+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 2), SLJIT_IMM, type_then_trap);
+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 3), TMP2, 0);
+
+size = BACKTRACK_AS(then_trap_backtrack)->framesize;
+if (size >= 0)
+ init_frame(common, cc, ccend, size - 1, 0, FALSE);
+}
+
+static void compile_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent)
+{
+DEFINE_COMPILER;
+backtrack_common *backtrack;
+BOOL has_then_trap = FALSE;
+then_trap_backtrack *save_then_trap = NULL;
+
+SLJIT_ASSERT(*ccend == OP_END || (*ccend >= OP_ALT && *ccend <= OP_KETRPOS));
+
+if (common->has_then && common->then_offsets[cc - common->start] != 0)
+ {
+ SLJIT_ASSERT(*ccend != OP_END && common->control_head_ptr != 0);
+ has_then_trap = TRUE;
+ save_then_trap = common->then_trap;
+ /* Tail item on backtrack. */
+ compile_then_trap_matchingpath(common, cc, ccend, parent);
+ }
+
+while (cc < ccend)
+ {
+ switch(*cc)
+ {
+ case OP_SOD:
+ case OP_SOM:
+ case OP_NOT_WORD_BOUNDARY:
+ case OP_WORD_BOUNDARY:
+ case OP_NOT_DIGIT:
+ case OP_DIGIT:
+ case OP_NOT_WHITESPACE:
+ case OP_WHITESPACE:
+ case OP_NOT_WORDCHAR:
+ case OP_WORDCHAR:
+ case OP_ANY:
+ case OP_ALLANY:
+ case OP_ANYBYTE:
+ case OP_NOTPROP:
+ case OP_PROP:
+ case OP_ANYNL:
+ case OP_NOT_HSPACE:
+ case OP_HSPACE:
+ case OP_NOT_VSPACE:
+ case OP_VSPACE:
+ case OP_EXTUNI:
+ case OP_EODN:
+ case OP_EOD:
+ case OP_CIRC:
+ case OP_CIRCM:
+ case OP_DOLL:
+ case OP_DOLLM:
+ case OP_NOT:
+ case OP_NOTI:
+ case OP_REVERSE:
+ cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
+ break;
+
+ case OP_SET_SOM:
+ PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
+ allocate_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
+ cc++;
+ break;
+
+ case OP_CHAR:
+ case OP_CHARI:
+ if (common->mode == JIT_COMPILE)
+ cc = compile_charn_matchingpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
+ else
+ cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
+ break;
+
+ case OP_STAR:
+ case OP_MINSTAR:
+ case OP_PLUS:
+ case OP_MINPLUS:
+ case OP_QUERY:
+ case OP_MINQUERY:
+ case OP_UPTO:
+ case OP_MINUPTO:
+ case OP_EXACT:
+ case OP_POSSTAR:
+ case OP_POSPLUS:
+ case OP_POSQUERY:
+ case OP_POSUPTO:
+ case OP_STARI:
+ case OP_MINSTARI:
+ case OP_PLUSI:
+ case OP_MINPLUSI:
+ case OP_QUERYI:
+ case OP_MINQUERYI:
+ case OP_UPTOI:
+ case OP_MINUPTOI:
+ case OP_EXACTI:
+ case OP_POSSTARI:
+ case OP_POSPLUSI:
+ case OP_POSQUERYI:
+ case OP_POSUPTOI:
+ case OP_NOTSTAR:
+ case OP_NOTMINSTAR:
+ case OP_NOTPLUS:
+ case OP_NOTMINPLUS:
+ case OP_NOTQUERY:
+ case OP_NOTMINQUERY:
+ case OP_NOTUPTO:
+ case OP_NOTMINUPTO:
+ case OP_NOTEXACT:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSUPTO:
+ case OP_NOTSTARI:
+ case OP_NOTMINSTARI:
+ case OP_NOTPLUSI:
+ case OP_NOTMINPLUSI:
+ case OP_NOTQUERYI:
+ case OP_NOTMINQUERYI:
+ case OP_NOTUPTOI:
+ case OP_NOTMINUPTOI:
+ case OP_NOTEXACTI:
+ case OP_NOTPOSSTARI:
+ case OP_NOTPOSPLUSI:
+ case OP_NOTPOSQUERYI:
+ case OP_NOTPOSUPTOI:
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ case OP_TYPEEXACT:
+ case OP_TYPEPOSSTAR:
+ case OP_TYPEPOSPLUS:
+ case OP_TYPEPOSQUERY:
+ case OP_TYPEPOSUPTO:
+ cc = compile_iterator_matchingpath(common, cc, parent);
+ break;
+
+ case OP_CLASS:
+ case OP_NCLASS:
+ if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRPOSRANGE)
+ cc = compile_iterator_matchingpath(common, cc, parent);
+ else
+ cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
+ break;
+
+#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ case OP_XCLASS:
+ if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRPOSRANGE)
+ cc = compile_iterator_matchingpath(common, cc, parent);
+ else
+ cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
+ break;
+#endif
+
+ case OP_REF:
+ case OP_REFI:
+ if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRPOSRANGE)
+ cc = compile_ref_iterator_matchingpath(common, cc, parent);
+ else
+ {
+ compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE);
+ cc += 1 + IMM2_SIZE;
+ }
+ break;
+
+ case OP_DNREF:
+ case OP_DNREFI:
+ if (cc[1 + 2 * IMM2_SIZE] >= OP_CRSTAR && cc[1 + 2 * IMM2_SIZE] <= OP_CRPOSRANGE)
+ cc = compile_ref_iterator_matchingpath(common, cc, parent);
+ else
+ {
+ compile_dnref_search(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
+ compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE);
+ cc += 1 + 2 * IMM2_SIZE;
+ }
+ break;
+
+ case OP_RECURSE:
+ cc = compile_recurse_matchingpath(common, cc, parent);
+ break;
+
+ case OP_CALLOUT:
+ cc = compile_callout_matchingpath(common, cc, parent);
+ break;
+
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);
+ cc = compile_assert_matchingpath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);
+ break;
+
+ case OP_BRAMINZERO:
+ PUSH_BACKTRACK_NOVALUE(sizeof(braminzero_backtrack), cc);
+ cc = bracketend(cc + 1);
+ if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN)
+ {
+ allocate_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+ }
+ else
+ {
+ allocate_stack(common, 2);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0);
+ }
+ BACKTRACK_AS(braminzero_backtrack)->matchingpath = LABEL();
+ if (cc[1] > OP_ASSERTBACK_NOT)
+ count_match(common);
+ break;
+
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ case OP_BRA:
+ case OP_CBRA:
+ case OP_COND:
+ case OP_SBRA:
+ case OP_SCBRA:
+ case OP_SCOND:
+ cc = compile_bracket_matchingpath(common, cc, parent);
+ break;
+
+ case OP_BRAZERO:
+ if (cc[1] > OP_ASSERTBACK_NOT)
+ cc = compile_bracket_matchingpath(common, cc, parent);
+ else
+ {
+ PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc);
+ cc = compile_assert_matchingpath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE);
+ }
+ break;
+
+ case OP_BRAPOS:
+ case OP_CBRAPOS:
+ case OP_SBRAPOS:
+ case OP_SCBRAPOS:
+ case OP_BRAPOSZERO:
+ cc = compile_bracketpos_matchingpath(common, cc, parent);
+ break;
+
+ case OP_MARK:
+ PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc);
+ SLJIT_ASSERT(common->mark_ptr != 0);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr);
+ allocate_stack(common, common->has_skip_arg ? 5 : 1);
+ 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_LOCALS_REG), common->mark_ptr, TMP2, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
+ if (common->has_skip_arg)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, type_mark);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), SLJIT_IMM, (sljit_sw)(cc + 2));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(3), STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
+ }
+ cc += 1 + 2 + cc[1];
+ break;
+
+ case OP_PRUNE:
+ case OP_PRUNE_ARG:
+ case OP_SKIP:
+ case OP_SKIP_ARG:
+ case OP_THEN:
+ case OP_THEN_ARG:
+ case OP_COMMIT:
+ cc = compile_control_verb_matchingpath(common, cc, parent);
+ break;
+
+ case OP_FAIL:
+ case OP_ACCEPT:
+ case OP_ASSERT_ACCEPT:
+ cc = compile_fail_accept_matchingpath(common, cc, parent);
+ break;
+
+ case OP_CLOSE:
+ cc = compile_close_matchingpath(common, cc);
+ break;
+
+ case OP_SKIPZERO:
+ cc = bracketend(cc + 1);
+ break;
+
+ default:
+ SLJIT_ASSERT_STOP();
+ return;
+ }
+ if (cc == NULL)
+ return;
+ }
+
+if (has_then_trap)
+ {
+ /* Head item on backtrack. */
+ PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc);
+ BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode;
+ BACKTRACK_AS(then_trap_backtrack)->then_trap = common->then_trap;
+ common->then_trap = save_then_trap;
+ }
+SLJIT_ASSERT(cc == ccend);
+}
+
+#undef PUSH_BACKTRACK
+#undef PUSH_BACKTRACK_NOVALUE
+#undef BACKTRACK_AS
+
+#define COMPILE_BACKTRACKINGPATH(current) \
+ do \
+ { \
+ compile_backtrackingpath(common, (current)); \
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
+ return; \
+ } \
+ while (0)
+
+#define CURRENT_AS(type) ((type *)current)
+
+static void compile_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current)
+{
+DEFINE_COMPILER;
+pcre_uchar *cc = current->cc;
+pcre_uchar opcode;
+pcre_uchar type;
+int max = -1, min = -1;
+struct sljit_label *label = NULL;
+struct sljit_jump *jump = NULL;
+jump_list *jumplist = NULL;
+int private_data_ptr = PRIVATE_DATA(cc);
+int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_LOCALS_REG);
+int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr;
+int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw);
+
+cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &min, NULL);
+
+switch(opcode)
+ {
+ case OP_STAR:
+ case OP_PLUS:
+ case OP_UPTO:
+ case OP_CRRANGE:
+ if (type == OP_ANYNL || type == OP_EXTUNI)
+ {
+ SLJIT_ASSERT(private_data_ptr == 0);
+ set_jumps(current->topbacktracks, LABEL());
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ free_stack(common, 1);
+ CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath);
+ }
+ else
+ {
+ if (opcode == OP_UPTO)
+ min = 0;
+ if (opcode <= OP_PLUS)
+ {
+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
+ jump = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, base, offset1);
+ }
+ else
+ {
+ OP1(SLJIT_MOV, TMP1, 0, base, offset1);
+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
+ jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, min + 1);
+ OP2(SLJIT_SUB, base, offset1, TMP1, 0, SLJIT_IMM, 1);
+ }
+ skip_char_back(common);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath);
+ if (opcode == OP_CRRANGE)
+ set_jumps(current->topbacktracks, LABEL());
+ JUMPHERE(jump);
+ if (private_data_ptr == 0)
+ free_stack(common, 2);
+ if (opcode == OP_PLUS)
+ set_jumps(current->topbacktracks, LABEL());
+ }
+ break;
+
+ case OP_MINSTAR:
+ case OP_MINPLUS:
+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
+ compile_char1_matchingpath(common, type, cc, &jumplist);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath);
+ set_jumps(jumplist, LABEL());
+ if (private_data_ptr == 0)
+ free_stack(common, 1);
+ if (opcode == OP_MINPLUS)
+ set_jumps(current->topbacktracks, LABEL());
+ break;
+
+ case OP_MINUPTO:
+ case OP_CRMINRANGE:
+ if (opcode == OP_CRMINRANGE)
+ {
+ label = LABEL();
+ set_jumps(current->topbacktracks, label);
+ }
+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
+ compile_char1_matchingpath(common, type, cc, &jumplist);
+
+ OP1(SLJIT_MOV, TMP1, 0, base, offset1);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+ OP1(SLJIT_MOV, base, offset1, TMP1, 0);
+
+ if (opcode == OP_CRMINRANGE)
+ CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min + 1, label);
+
+ if (opcode == OP_CRMINRANGE && max == 0)
+ JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath);
+ else
+ CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, max + 2, CURRENT_AS(iterator_backtrack)->matchingpath);
+
+ set_jumps(jumplist, LABEL());
+ if (private_data_ptr == 0)
+ free_stack(common, 2);
+ break;
+
+ case OP_QUERY:
+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
+ OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);
+ CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath);
+ jump = JUMP(SLJIT_JUMP);
+ set_jumps(current->topbacktracks, LABEL());
+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
+ OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);
+ JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath);
+ JUMPHERE(jump);
+ if (private_data_ptr == 0)
+ free_stack(common, 1);
+ break;
+
+ case OP_MINQUERY:
+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
+ OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0);
+ jump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
+ compile_char1_matchingpath(common, type, cc, &jumplist);
+ JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->matchingpath);
+ set_jumps(jumplist, LABEL());
+ JUMPHERE(jump);
+ if (private_data_ptr == 0)
+ free_stack(common, 1);
+ break;
+
+ case OP_EXACT:
+ case OP_POSPLUS:
+ case OP_CRPOSRANGE:
+ set_jumps(current->topbacktracks, LABEL());
+ break;
+
+ case OP_POSSTAR:
+ case OP_POSQUERY:
+ case OP_POSUPTO:
+ break;
+
+ default:
+ SLJIT_ASSERT_STOP();
+ break;
+ }
+}
+
+static SLJIT_INLINE void compile_ref_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current)
+{
+DEFINE_COMPILER;
+pcre_uchar *cc = current->cc;
+BOOL ref = (*cc == OP_REF || *cc == OP_REFI);
+pcre_uchar type;
+
+type = cc[ref ? 1 + IMM2_SIZE : 1 + 2 * IMM2_SIZE];
+
+if ((type & 0x1) == 0)
+ {
+ /* Maximize case. */
+ set_jumps(current->topbacktracks, LABEL());
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ free_stack(common, 1);
+ CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath);
+ return;
+ }
+
+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->matchingpath);
+set_jumps(current->topbacktracks, LABEL());
+free_stack(common, ref ? 2 : 3);
+}
+
+static SLJIT_INLINE void compile_recurse_backtrackingpath(compiler_common *common, struct backtrack_common *current)
+{
+DEFINE_COMPILER;
+
+if (CURRENT_AS(recurse_backtrack)->inlined_pattern)
+ compile_backtrackingpath(common, current->top);
+set_jumps(current->topbacktracks, LABEL());
+if (CURRENT_AS(recurse_backtrack)->inlined_pattern)
+ return;
+
+if (common->has_set_som && common->mark_ptr != 0)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
+ free_stack(common, 2);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0);
+ }
+else if (common->has_set_som || common->mark_ptr != 0)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ free_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr, TMP2, 0);
+ }
+}
+
+static void compile_assert_backtrackingpath(compiler_common *common, struct backtrack_common *current)
+{
+DEFINE_COMPILER;
+pcre_uchar *cc = current->cc;
+pcre_uchar bra = OP_BRA;
+struct sljit_jump *brajump = NULL;
+
+SLJIT_ASSERT(*cc != OP_BRAMINZERO);
+if (*cc == OP_BRAZERO)
+ {
+ bra = *cc;
+ cc++;
+ }
+
+if (bra == OP_BRAZERO)
+ {
+ SLJIT_ASSERT(current->topbacktracks == NULL);
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ }
+
+if (CURRENT_AS(assert_backtrack)->framesize < 0)
+ {
+ set_jumps(current->topbacktracks, LABEL());
+
+ if (bra == OP_BRAZERO)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+ CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath);
+ free_stack(common, 1);
+ }
+ return;
+ }
+
+if (bra == OP_BRAZERO)
+ {
+ if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+ CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath);
+ free_stack(common, 1);
+ return;
+ }
+ free_stack(common, 1);
+ brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
+ }
+
+if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK)
+ {
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_backtrack)->private_data_ptr);
+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_backtrack)->framesize * sizeof(sljit_sw));
+
+ set_jumps(current->topbacktracks, LABEL());
+ }
+else
+ set_jumps(current->topbacktracks, LABEL());
+
+if (bra == OP_BRAZERO)
+ {
+ /* We know there is enough place on the stack. */
+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+ JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_backtrack)->matchingpath);
+ JUMPHERE(brajump);
+ }
+}
+
+static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current)
+{
+DEFINE_COMPILER;
+int opcode, stacksize, alt_count, alt_max;
+int offset = 0;
+int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr;
+int repeat_ptr = 0, repeat_type = 0, repeat_count = 0;
+pcre_uchar *cc = current->cc;
+pcre_uchar *ccbegin;
+pcre_uchar *ccprev;
+pcre_uchar bra = OP_BRA;
+pcre_uchar ket;
+assert_backtrack *assert;
+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 *once = NULL;
+struct sljit_jump *cond = NULL;
+struct sljit_label *rmin_label = NULL;
+struct sljit_label *exact_label = NULL;
+
+if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
+ {
+ bra = *cc;
+ cc++;
+ }
+
+opcode = *cc;
+ccbegin = bracketend(cc) - 1 - LINK_SIZE;
+ket = *ccbegin;
+if (ket == OP_KET && PRIVATE_DATA(ccbegin) != 0)
+ {
+ repeat_ptr = PRIVATE_DATA(ccbegin);
+ repeat_type = PRIVATE_DATA(ccbegin + 2);
+ repeat_count = PRIVATE_DATA(ccbegin + 3);
+ SLJIT_ASSERT(repeat_type != 0 && repeat_count != 0);
+ if (repeat_type == OP_UPTO)
+ ket = OP_KETRMAX;
+ if (repeat_type == OP_MINUPTO)
+ ket = OP_KETRMIN;
+ }
+ccbegin = cc;
+cc += GET(cc, 1);
+has_alternatives = *cc == OP_ALT;
+if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
+ has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_backtrack)->u.condfailed != NULL;
+if (opcode == OP_CBRA || opcode == OP_SCBRA)
+ offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1;
+if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
+ opcode = OP_SCOND;
+if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC))
+ opcode = OP_ONCE;
+
+alt_max = has_alternatives ? no_alternatives(ccbegin) : 0;
+
+/* Decoding the needs_control_head in framesize. */
+if (opcode == OP_ONCE)
+ {
+ needs_control_head = (CURRENT_AS(bracket_backtrack)->u.framesize & 0x1) != 0;
+ CURRENT_AS(bracket_backtrack)->u.framesize >>= 1;
+ }
+
+if (ket != OP_KET && repeat_type != 0)
+ {
+ /* TMP1 is used in OP_KETRMIN below. */
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ free_stack(common, 1);
+ if (repeat_type == OP_UPTO)
+ OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0, SLJIT_IMM, 1);
+ else
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0);
+ }
+
+if (ket == OP_KETRMAX)
+ {
+ if (bra == OP_BRAZERO)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ free_stack(common, 1);
+ brazero = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0);
+ }
+ }
+else if (ket == OP_KETRMIN)
+ {
+ if (bra != OP_BRAMINZERO)
+ {
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ if (repeat_type != 0)
+ {
+ /* TMP1 was set a few lines above. */
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
+ /* Drop STR_PTR for non-greedy plus quantifier. */
+ if (opcode != OP_ONCE)
+ free_stack(common, 1);
+ }
+ else if (opcode >= OP_SBRA || opcode == OP_ONCE)
+ {
+ /* Checking zero-length iteration. */
+ if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0)
+ CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
+ else
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw), CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
+ }
+ /* Drop STR_PTR for non-greedy plus quantifier. */
+ if (opcode != OP_ONCE)
+ free_stack(common, 1);
+ }
+ else
+ JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
+ }
+ rmin_label = LABEL();
+ if (repeat_type != 0)
+ OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
+ }
+else if (bra == OP_BRAZERO)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ free_stack(common, 1);
+ brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
+ }
+else if (repeat_type == OP_EXACT)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
+ exact_label = LABEL();
+ }
+
+if (offset != 0)
+ {
+ if (common->capture_last_ptr != 0)
+ {
+ SLJIT_ASSERT(common->optimized_cbracket[offset >> 1] == 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, TMP1, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2));
+ free_stack(common, 3);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP2, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0);
+ }
+ else if (common->optimized_cbracket[offset >> 1] == 0)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
+ free_stack(common, 2);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
+ }
+ }
+
+if (SLJIT_UNLIKELY(opcode == OP_ONCE))
+ {
+ if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
+ {
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+ }
+ once = JUMP(SLJIT_JUMP);
+ }
+else if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
+ {
+ if (has_alternatives)
+ {
+ /* Always exactly one alternative. */
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ free_stack(common, 1);
+
+ alt_max = 2;
+ alt1 = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw));
+ }
+ }
+else if (has_alternatives)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ free_stack(common, 1);
+
+ if (alt_max > 4)
+ {
+ /* Table jump if alt_max is greater than 4. */
+ sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(TMP1), (sljit_sw)common->read_only_data_ptr);
+ add_label_addr(common);
+ }
+ else
+ {
+ if (alt_max == 4)
+ alt2 = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw));
+ alt1 = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw));
+ }
+ }
+
+COMPILE_BACKTRACKINGPATH(current->top);
+if (current->topbacktracks)
+ set_jumps(current->topbacktracks, LABEL());
+
+if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
+ {
+ /* Conditional block always has at most one alternative. */
+ if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT)
+ {
+ SLJIT_ASSERT(has_alternatives);
+ assert = CURRENT_AS(bracket_backtrack)->u.assert;
+ if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK))
+ {
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->private_data_ptr);
+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_sw));
+ }
+ cond = JUMP(SLJIT_JUMP);
+ set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL());
+ }
+ else if (CURRENT_AS(bracket_backtrack)->u.condfailed != NULL)
+ {
+ SLJIT_ASSERT(has_alternatives);
+ cond = JUMP(SLJIT_JUMP);
+ set_jumps(CURRENT_AS(bracket_backtrack)->u.condfailed, LABEL());
+ }
+ else
+ SLJIT_ASSERT(!has_alternatives);
+ }
+
+if (has_alternatives)
+ {
+ alt_count = sizeof(sljit_uw);
+ do
+ {
+ current->top = NULL;
+ current->topbacktracks = NULL;
+ current->nextbacktracks = NULL;
+ /* Conditional blocks always have an additional alternative, even if it is empty. */
+ if (*cc == OP_ALT)
+ {
+ ccprev = cc + 1 + LINK_SIZE;
+ cc += GET(cc, 1);
+ if (opcode != OP_COND && opcode != OP_SCOND)
+ {
+ if (opcode != OP_ONCE)
+ {
+ if (private_data_ptr != 0)
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr);
+ else
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ }
+ else
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(needs_control_head ? 1 : 0));
+ }
+ compile_matchingpath(common, ccprev, cc, current);
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ return;
+ }
+
+ /* Instructions after the current alternative is successfully matched. */
+ /* There is a similar code in compile_bracket_matchingpath. */
+ if (opcode == OP_ONCE)
+ match_once_common(common, ket, CURRENT_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head);
+
+ stacksize = 0;
+ if (repeat_type == OP_MINUPTO)
+ {
+ /* We need to preserve the counter. TMP2 will be used below. */
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr);
+ stacksize++;
+ }
+ if (ket != OP_KET || bra != OP_BRA)
+ stacksize++;
+ if (offset != 0)
+ {
+ if (common->capture_last_ptr != 0)
+ stacksize++;
+ if (common->optimized_cbracket[offset >> 1] == 0)
+ stacksize += 2;
+ }
+ if (opcode != OP_ONCE)
+ stacksize++;
+
+ if (stacksize > 0)
+ allocate_stack(common, stacksize);
+
+ stacksize = 0;
+ if (repeat_type == OP_MINUPTO)
+ {
+ /* TMP2 was set above. */
+ OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1);
+ stacksize++;
+ }
+
+ if (ket != OP_KET || bra != OP_BRA)
+ {
+ if (ket != OP_KET)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
+ else
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
+ stacksize++;
+ }
+
+ if (offset != 0)
+ 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 (offset != 0 && ket == OP_KETRMAX && common->optimized_cbracket[offset >> 1] != 0)
+ {
+ /* If ket is not OP_KETRMAX, this code path is executed after the jump to alternative_matchingpath. */
+ SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
+ }
+
+ JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->alternative_matchingpath);
+
+ if (opcode != OP_ONCE)
+ {
+ if (alt_max > 4)
+ add_label_addr(common);
+ else
+ {
+ if (alt_count != 2 * sizeof(sljit_uw))
+ {
+ JUMPHERE(alt1);
+ if (alt_max == 3 && alt_count == sizeof(sljit_uw))
+ alt2 = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw));
+ }
+ else
+ {
+ JUMPHERE(alt2);
+ if (alt_max == 4)
+ alt1 = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_uw));
+ }
+ }
+ alt_count += sizeof(sljit_uw);
+ }
+
+ COMPILE_BACKTRACKINGPATH(current->top);
+ if (current->topbacktracks)
+ set_jumps(current->topbacktracks, LABEL());
+ SLJIT_ASSERT(!current->nextbacktracks);
+ }
+ while (*cc == OP_ALT);
+
+ if (cond != NULL)
+ {
+ SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND);
+ assert = CURRENT_AS(bracket_backtrack)->u.assert;
+ if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0)
+ {
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->private_data_ptr);
+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_sw));
+ }
+ JUMPHERE(cond);
+ }
+
+ /* Free the STR_PTR. */
+ if (private_data_ptr == 0)
+ free_stack(common, 1);
+ }
+
+if (offset != 0)
+ {
+ /* Using both tmp register is better for instruction scheduling. */
+ if (common->optimized_cbracket[offset >> 1] != 0)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
+ free_stack(common, 2);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
+ }
+ else
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ free_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0);
+ }
+ }
+else if (opcode == OP_SBRA || opcode == OP_SCOND)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(0));
+ free_stack(common, 1);
+ }
+else if (opcode == OP_ONCE)
+ {
+ cc = ccbegin + GET(ccbegin, 1);
+ stacksize = needs_control_head ? 1 : 0;
+
+ if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
+ {
+ /* Reset head and drop saved frame. */
+ stacksize += CURRENT_AS(bracket_backtrack)->u.framesize + ((ket != OP_KET || *cc == OP_ALT) ? 2 : 1);
+ }
+ else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN))
+ {
+ /* The STR_PTR must be released. */
+ stacksize++;
+ }
+ free_stack(common, stacksize);
+
+ JUMPHERE(once);
+ /* Restore previous private_data_ptr */
+ if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_backtrack)->u.framesize * sizeof(sljit_sw));
+ else if (ket == OP_KETRMIN)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
+ /* See the comment below. */
+ free_stack(common, 2);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0);
+ }
+ }
+
+if (repeat_type == OP_EXACT)
+ {
+ OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, SLJIT_IMM, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), repeat_ptr, TMP1, 0);
+ CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, repeat_count, exact_label);
+ }
+else if (ket == OP_KETRMAX)
+ {
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ if (bra != OP_BRAZERO)
+ free_stack(common, 1);
+
+ CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath);
+ if (bra == OP_BRAZERO)
+ {
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
+ JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zero_matchingpath);
+ JUMPHERE(brazero);
+ free_stack(common, 1);
+ }
+ }
+else if (ket == OP_KETRMIN)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+
+ /* OP_ONCE removes everything in case of a backtrack, so we don't
+ need to explicitly release the STR_PTR. The extra release would
+ affect badly the free_stack(2) above. */
+ if (opcode != OP_ONCE)
+ free_stack(common, 1);
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rmin_label);
+ if (opcode == OP_ONCE)
+ free_stack(common, bra == OP_BRAMINZERO ? 2 : 1);
+ else if (bra == OP_BRAMINZERO)
+ free_stack(common, 1);
+ }
+else if (bra == OP_BRAZERO)
+ {
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zero_matchingpath);
+ JUMPHERE(brazero);
+ }
+}
+
+static SLJIT_INLINE void compile_bracketpos_backtrackingpath(compiler_common *common, struct backtrack_common *current)
+{
+DEFINE_COMPILER;
+int offset;
+struct sljit_jump *jump;
+
+if (CURRENT_AS(bracketpos_backtrack)->framesize < 0)
+ {
+ if (*current->cc == OP_CBRAPOS || *current->cc == OP_SCBRAPOS)
+ {
+ offset = (GET2(current->cc, 1 + LINK_SIZE)) << 1;
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
+ if (common->capture_last_ptr != 0)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
+ if (common->capture_last_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, TMP1, 0);
+ }
+ set_jumps(current->topbacktracks, LABEL());
+ free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);
+ return;
+ }
+
+OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->private_data_ptr);
+add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+
+if (current->topbacktracks)
+ {
+ jump = JUMP(SLJIT_JUMP);
+ set_jumps(current->topbacktracks, LABEL());
+ /* Drop the stack frame. */
+ free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize);
+ JUMPHERE(jump);
+ }
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_backtrack)->framesize * sizeof(sljit_sw));
+}
+
+static SLJIT_INLINE void compile_braminzero_backtrackingpath(compiler_common *common, struct backtrack_common *current)
+{
+assert_backtrack backtrack;
+
+current->top = NULL;
+current->topbacktracks = NULL;
+current->nextbacktracks = NULL;
+if (current->cc[1] > OP_ASSERTBACK_NOT)
+ {
+ /* Manual call of compile_bracket_matchingpath and compile_bracket_backtrackingpath. */
+ compile_bracket_matchingpath(common, current->cc, current);
+ compile_bracket_backtrackingpath(common, current->top);
+ }
+else
+ {
+ memset(&backtrack, 0, sizeof(backtrack));
+ backtrack.common.cc = current->cc;
+ backtrack.matchingpath = CURRENT_AS(braminzero_backtrack)->matchingpath;
+ /* Manual call of compile_assert_matchingpath. */
+ compile_assert_matchingpath(common, current->cc, &backtrack, FALSE);
+ }
+SLJIT_ASSERT(!current->nextbacktracks && !current->topbacktracks);
+}
+
+static SLJIT_INLINE void compile_control_verb_backtrackingpath(compiler_common *common, struct backtrack_common *current)
+{
+DEFINE_COMPILER;
+pcre_uchar opcode = *current->cc;
+struct sljit_label *loop;
+struct sljit_jump *jump;
+
+if (opcode == OP_THEN || opcode == OP_THEN_ARG)
+ {
+ if (common->then_trap != NULL)
+ {
+ SLJIT_ASSERT(common->control_head_ptr != 0);
+
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, type_then_trap);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, common->then_trap->start);
+ jump = JUMP(SLJIT_JUMP);
+
+ loop = LABEL();
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), -(int)sizeof(sljit_sw));
+ JUMPHERE(jump);
+ CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(2 * sizeof(sljit_sw)), TMP1, 0, loop);
+ CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(3 * sizeof(sljit_sw)), TMP2, 0, loop);
+ add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP));
+ return;
+ }
+ else if (common->positive_assert)
+ {
+ add_jump(compiler, &common->positive_assert_quit, JUMP(SLJIT_JUMP));
+ return;
+ }
+ }
+
+if (common->local_exit)
+ {
+ if (common->quit_label == NULL)
+ add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));
+ else
+ JUMPTO(SLJIT_JUMP, common->quit_label);
+ return;
+ }
+
+if (opcode == OP_SKIP_ARG)
+ {
+ SLJIT_ASSERT(common->control_head_ptr != 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2));
+ sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark));
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
+
+ OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);
+ add_jump(compiler, &common->reset_match, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, -1));
+ return;
+ }
+
+if (opcode == OP_SKIP)
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+else
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_IMM, 0);
+add_jump(compiler, &common->reset_match, JUMP(SLJIT_JUMP));
+}
+
+static SLJIT_INLINE void compile_then_trap_backtrackingpath(compiler_common *common, struct backtrack_common *current)
+{
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+int size;
+
+if (CURRENT_AS(then_trap_backtrack)->then_trap)
+ {
+ common->then_trap = CURRENT_AS(then_trap_backtrack)->then_trap;
+ return;
+ }
+
+size = CURRENT_AS(then_trap_backtrack)->framesize;
+size = 3 + (size < 0 ? 0 : size);
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(size - 3));
+free_stack(common, size);
+jump = JUMP(SLJIT_JUMP);
+
+set_jumps(CURRENT_AS(then_trap_backtrack)->quit, LABEL());
+/* STACK_TOP is set by THEN. */
+if (CURRENT_AS(then_trap_backtrack)->framesize >= 0)
+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+free_stack(common, 3);
+
+JUMPHERE(jump);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP1, 0);
+}
+
+static void compile_backtrackingpath(compiler_common *common, struct backtrack_common *current)
+{
+DEFINE_COMPILER;
+then_trap_backtrack *save_then_trap = common->then_trap;
+
+while (current)
+ {
+ if (current->nextbacktracks != NULL)
+ set_jumps(current->nextbacktracks, LABEL());
+ switch(*current->cc)
+ {
+ case OP_SET_SOM:
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ free_stack(common, 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP1, 0);
+ break;
+
+ case OP_STAR:
+ case OP_MINSTAR:
+ case OP_PLUS:
+ case OP_MINPLUS:
+ case OP_QUERY:
+ case OP_MINQUERY:
+ case OP_UPTO:
+ case OP_MINUPTO:
+ case OP_EXACT:
+ case OP_POSSTAR:
+ case OP_POSPLUS:
+ case OP_POSQUERY:
+ case OP_POSUPTO:
+ case OP_STARI:
+ case OP_MINSTARI:
+ case OP_PLUSI:
+ case OP_MINPLUSI:
+ case OP_QUERYI:
+ case OP_MINQUERYI:
+ case OP_UPTOI:
+ case OP_MINUPTOI:
+ case OP_EXACTI:
+ case OP_POSSTARI:
+ case OP_POSPLUSI:
+ case OP_POSQUERYI:
+ case OP_POSUPTOI:
+ case OP_NOTSTAR:
+ case OP_NOTMINSTAR:
+ case OP_NOTPLUS:
+ case OP_NOTMINPLUS:
+ case OP_NOTQUERY:
+ case OP_NOTMINQUERY:
+ case OP_NOTUPTO:
+ case OP_NOTMINUPTO:
+ case OP_NOTEXACT:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSUPTO:
+ case OP_NOTSTARI:
+ case OP_NOTMINSTARI:
+ case OP_NOTPLUSI:
+ case OP_NOTMINPLUSI:
+ case OP_NOTQUERYI:
+ case OP_NOTMINQUERYI:
+ case OP_NOTUPTOI:
+ case OP_NOTMINUPTOI:
+ case OP_NOTEXACTI:
+ case OP_NOTPOSSTARI:
+ case OP_NOTPOSPLUSI:
+ case OP_NOTPOSQUERYI:
+ case OP_NOTPOSUPTOI:
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ case OP_TYPEEXACT:
+ case OP_TYPEPOSSTAR:
+ case OP_TYPEPOSPLUS:
+ case OP_TYPEPOSQUERY:
+ case OP_TYPEPOSUPTO:
+ case OP_CLASS:
+ case OP_NCLASS:
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+#endif
+ compile_iterator_backtrackingpath(common, current);
+ break;
+
+ case OP_REF:
+ case OP_REFI:
+ case OP_DNREF:
+ case OP_DNREFI:
+ compile_ref_iterator_backtrackingpath(common, current);
+ break;
+
+ case OP_RECURSE:
+ compile_recurse_backtrackingpath(common, current);
+ break;
+
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ compile_assert_backtrackingpath(common, current);
+ break;
+
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ case OP_BRA:
+ case OP_CBRA:
+ case OP_COND:
+ case OP_SBRA:
+ case OP_SCBRA:
+ case OP_SCOND:
+ compile_bracket_backtrackingpath(common, current);
+ break;
+
+ case OP_BRAZERO:
+ if (current->cc[1] > OP_ASSERTBACK_NOT)
+ compile_bracket_backtrackingpath(common, current);
+ else
+ compile_assert_backtrackingpath(common, current);
+ break;
+
+ case OP_BRAPOS:
+ case OP_CBRAPOS:
+ case OP_SBRAPOS:
+ case OP_SCBRAPOS:
+ case OP_BRAPOSZERO:
+ compile_bracketpos_backtrackingpath(common, current);
+ break;
+
+ case OP_BRAMINZERO:
+ compile_braminzero_backtrackingpath(common, current);
+ break;
+
+ case OP_MARK:
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0));
+ if (common->has_skip_arg)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+ free_stack(common, common->has_skip_arg ? 5 : 1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0);
+ if (common->has_skip_arg)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP2, 0);
+ break;
+
+ case OP_THEN:
+ case OP_THEN_ARG:
+ case OP_PRUNE:
+ case OP_PRUNE_ARG:
+ case OP_SKIP:
+ case OP_SKIP_ARG:
+ compile_control_verb_backtrackingpath(common, current);
+ break;
+
+ case OP_COMMIT:
+ if (!common->local_exit)
+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
+ if (common->quit_label == NULL)
+ add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));
+ else
+ JUMPTO(SLJIT_JUMP, common->quit_label);
+ break;
+
+ case OP_CALLOUT:
+ case OP_FAIL:
+ case OP_ACCEPT:
+ case OP_ASSERT_ACCEPT:
+ set_jumps(current->topbacktracks, LABEL());
+ break;
+
+ case OP_THEN_TRAP:
+ /* A virtual opcode for then traps. */
+ compile_then_trap_backtrackingpath(common, current);
+ break;
+
+ default:
+ SLJIT_ASSERT_STOP();
+ break;
+ }
+ current = current->prev;
+ }
+common->then_trap = save_then_trap;
+}
+
+static SLJIT_INLINE void compile_recurse(compiler_common *common)
+{
+DEFINE_COMPILER;
+pcre_uchar *cc = common->start + common->currententry->start;
+pcre_uchar *ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE);
+pcre_uchar *ccend = bracketend(cc);
+BOOL needs_control_head;
+int framesize = get_framesize(common, cc, NULL, TRUE, &needs_control_head);
+int private_data_size = get_private_data_copy_length(common, ccbegin, ccend, needs_control_head);
+int alternativesize;
+BOOL needs_frame;
+backtrack_common altbacktrack;
+struct sljit_jump *jump;
+
+/* Recurse captures then. */
+common->then_trap = NULL;
+
+SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS);
+needs_frame = framesize >= 0;
+if (!needs_frame)
+ framesize = 0;
+alternativesize = *(cc + GET(cc, 1)) == OP_ALT ? 1 : 0;
+
+SLJIT_ASSERT(common->currententry->entry == NULL && common->recursive_head_ptr != 0);
+common->currententry->entry = LABEL();
+set_jumps(common->currententry->calls, common->currententry->entry);
+
+sljit_emit_fast_enter(compiler, TMP2, 0);
+allocate_stack(common, private_data_size + framesize + alternativesize);
+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(private_data_size + framesize + alternativesize - 1), TMP2, 0);
+copy_private_data(common, ccbegin, ccend, TRUE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head);
+if (needs_control_head)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr, STACK_TOP, 0);
+if (needs_frame)
+ init_frame(common, cc, NULL, framesize + alternativesize - 1, alternativesize, TRUE);
+
+if (alternativesize > 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+
+memset(&altbacktrack, 0, sizeof(backtrack_common));
+common->quit_label = NULL;
+common->accept_label = NULL;
+common->quit = NULL;
+common->accept = NULL;
+altbacktrack.cc = ccbegin;
+cc += GET(cc, 1);
+while (1)
+ {
+ altbacktrack.top = NULL;
+ altbacktrack.topbacktracks = NULL;
+
+ if (altbacktrack.cc != ccbegin)
+ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+
+ compile_matchingpath(common, altbacktrack.cc, cc, &altbacktrack);
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ return;
+
+ add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));
+
+ compile_backtrackingpath(common, altbacktrack.top);
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ return;
+ set_jumps(altbacktrack.topbacktracks, LABEL());
+
+ if (*cc != OP_ALT)
+ break;
+
+ altbacktrack.cc = cc + 1 + LINK_SIZE;
+ cc += GET(cc, 1);
+ }
+
+/* None of them matched. */
+OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);
+jump = JUMP(SLJIT_JUMP);
+
+if (common->quit != NULL)
+ {
+ set_jumps(common->quit, LABEL());
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr);
+ if (needs_frame)
+ {
+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
+ }
+ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);
+ common->quit = NULL;
+ add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));
+ }
+
+set_jumps(common->accept, LABEL());
+OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr);
+if (needs_frame)
+ {
+ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
+ add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw));
+ }
+OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1);
+
+JUMPHERE(jump);
+if (common->quit != NULL)
+ set_jumps(common->quit, LABEL());
+copy_private_data(common, ccbegin, ccend, FALSE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head);
+free_stack(common, private_data_size + framesize + alternativesize);
+if (needs_control_head)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), 2 * sizeof(sljit_sw));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_sw));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr, TMP1, 0);
+ OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP2, 0);
+ }
+else
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_sw));
+ OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head_ptr, TMP2, 0);
+ }
+sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0);
+}
+
+#undef COMPILE_BACKTRACKINGPATH
+#undef CURRENT_AS
+
+void
+PRIV(jit_compile)(const REAL_PCRE *re, PUBL(extra) *extra, int mode)
+{
+struct sljit_compiler *compiler;
+backtrack_common rootbacktrack;
+compiler_common common_data;
+compiler_common *common = &common_data;
+const pcre_uint8 *tables = re->tables;
+pcre_study_data *study;
+int private_data_size;
+pcre_uchar *ccend;
+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;
+struct sljit_label *empty_match_backtrack_label = NULL;
+struct sljit_label *reset_match_label;
+struct sljit_label *quit_label;
+struct sljit_jump *jump;
+struct sljit_jump *minlength_check_failed = NULL;
+struct sljit_jump *reqbyte_notfound = NULL;
+struct sljit_jump *empty_match = NULL;
+
+SLJIT_ASSERT((extra->flags & PCRE_EXTRA_STUDY_DATA) != 0);
+study = extra->study_data;
+
+if (!tables)
+ tables = PRIV(default_tables);
+
+memset(&rootbacktrack, 0, sizeof(backtrack_common));
+memset(common, 0, sizeof(compiler_common));
+rootbacktrack.cc = (pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size;
+
+common->start = rootbacktrack.cc;
+common->read_only_data = NULL;
+common->read_only_data_size = 0;
+common->read_only_data_ptr = NULL;
+common->fcc = tables + fcc_offset;
+common->lcc = (sljit_sw)(tables + lcc_offset);
+common->mode = mode;
+common->might_be_empty = study->minlength == 0;
+common->nltype = NLTYPE_FIXED;
+switch(re->options & PCRE_NEWLINE_BITS)
+ {
+ case 0:
+ /* Compile-time default */
+ switch(NEWLINE)
+ {
+ case -1: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;
+ case -2: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;
+ default: common->newline = NEWLINE; break;
+ }
+ break;
+ case PCRE_NEWLINE_CR: common->newline = CHAR_CR; break;
+ case PCRE_NEWLINE_LF: common->newline = CHAR_NL; break;
+ case PCRE_NEWLINE_CR+
+ PCRE_NEWLINE_LF: common->newline = (CHAR_CR << 8) | CHAR_NL; break;
+ case PCRE_NEWLINE_ANY: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;
+ case PCRE_NEWLINE_ANYCRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;
+ default: return;
+ }
+common->nlmax = READ_CHAR_MAX;
+common->nlmin = 0;
+if ((re->options & PCRE_BSR_ANYCRLF) != 0)
+ common->bsr_nltype = NLTYPE_ANYCRLF;
+else if ((re->options & PCRE_BSR_UNICODE) != 0)
+ common->bsr_nltype = NLTYPE_ANY;
+else
+ {
+#ifdef BSR_ANYCRLF
+ common->bsr_nltype = NLTYPE_ANYCRLF;
+#else
+ common->bsr_nltype = NLTYPE_ANY;
+#endif
+ }
+common->bsr_nlmax = READ_CHAR_MAX;
+common->bsr_nlmin = 0;
+common->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
+common->ctypes = (sljit_sw)(tables + ctypes_offset);
+common->name_table = ((pcre_uchar *)re) + re->name_table_offset;
+common->name_count = re->name_count;
+common->name_entry_size = re->name_entry_size;
+common->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
+#ifdef SUPPORT_UTF
+/* PCRE_UTF[16|32] have the same value as PCRE_UTF8. */
+common->utf = (re->options & PCRE_UTF8) != 0;
+#ifdef SUPPORT_UCP
+common->use_ucp = (re->options & PCRE_UCP) != 0;
+#endif
+if (common->utf)
+ {
+ if (common->nltype == NLTYPE_ANY)
+ common->nlmax = 0x2029;
+ else if (common->nltype == NLTYPE_ANYCRLF)
+ common->nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL;
+ else
+ {
+ /* We only care about the first newline character. */
+ common->nlmax = common->newline & 0xff;
+ }
+
+ if (common->nltype == NLTYPE_FIXED)
+ common->nlmin = common->newline & 0xff;
+ else
+ common->nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL;
+
+ if (common->bsr_nltype == NLTYPE_ANY)
+ common->bsr_nlmax = 0x2029;
+ else
+ common->bsr_nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL;
+ common->bsr_nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL;
+ }
+#endif /* SUPPORT_UTF */
+ccend = bracketend(common->start);
+
+/* Calculate the local space size on the stack. */
+common->ovector_start = LIMIT_MATCH + sizeof(sljit_sw);
+common->optimized_cbracket = (pcre_uint8 *)SLJIT_MALLOC(re->top_bracket + 1);
+if (!common->optimized_cbracket)
+ return;
+#if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 1
+memset(common->optimized_cbracket, 0, re->top_bracket + 1);
+#else
+memset(common->optimized_cbracket, 1, re->top_bracket + 1);
+#endif
+
+SLJIT_ASSERT(*common->start == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET);
+#if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 2
+common->capture_last_ptr = common->ovector_start;
+common->ovector_start += sizeof(sljit_sw);
+#endif
+if (!check_opcode_types(common, common->start, ccend))
+ {
+ SLJIT_FREE(common->optimized_cbracket);
+ return;
+ }
+
+/* Checking flags and updating ovector_start. */
+if (mode == JIT_COMPILE && (re->flags & PCRE_REQCHSET) != 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
+ {
+ common->req_char_ptr = common->ovector_start;
+ common->ovector_start += sizeof(sljit_sw);
+ }
+if (mode != JIT_COMPILE)
+ {
+ common->start_used_ptr = common->ovector_start;
+ common->ovector_start += sizeof(sljit_sw);
+ if (mode == JIT_PARTIAL_SOFT_COMPILE)
+ {
+ common->hit_start = common->ovector_start;
+ common->ovector_start += 2 * sizeof(sljit_sw);
+ }
+ else
+ {
+ SLJIT_ASSERT(mode == JIT_PARTIAL_HARD_COMPILE);
+ common->needs_start_ptr = TRUE;
+ }
+ }
+if ((re->options & PCRE_FIRSTLINE) != 0)
+ {
+ common->first_line_end = common->ovector_start;
+ common->ovector_start += sizeof(sljit_sw);
+ }
+#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD
+common->control_head_ptr = 1;
+#endif
+if (common->control_head_ptr != 0)
+ {
+ common->control_head_ptr = common->ovector_start;
+ common->ovector_start += sizeof(sljit_sw);
+ }
+if (common->needs_start_ptr && common->has_set_som)
+ {
+ /* Saving the real start pointer is necessary. */
+ common->start_ptr = common->ovector_start;
+ common->ovector_start += sizeof(sljit_sw);
+ }
+else
+ common->needs_start_ptr = FALSE;
+
+/* Aligning ovector to even number of sljit words. */
+if ((common->ovector_start & sizeof(sljit_sw)) != 0)
+ common->ovector_start += sizeof(sljit_sw);
+
+if (common->start_ptr == 0)
+ common->start_ptr = OVECTOR(0);
+
+/* Capturing brackets cannot be optimized if callouts are allowed. */
+if (common->capture_last_ptr != 0)
+ memset(common->optimized_cbracket, 0, re->top_bracket + 1);
+
+SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));
+common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw);
+
+total_length = ccend - common->start;
+common->private_data_ptrs = (sljit_si *)SLJIT_MALLOC(total_length * (sizeof(sljit_si) + (common->has_then ? 1 : 0)));
+if (!common->private_data_ptrs)
+ {
+ SLJIT_FREE(common->optimized_cbracket);
+ return;
+ }
+memset(common->private_data_ptrs, 0, total_length * sizeof(sljit_si));
+
+private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw);
+set_private_data_ptrs(common, &private_data_size, ccend);
+if (private_data_size > SLJIT_MAX_LOCAL_SIZE)
+ {
+ SLJIT_FREE(common->private_data_ptrs);
+ SLJIT_FREE(common->optimized_cbracket);
+ return;
+ }
+
+if (common->has_then)
+ {
+ common->then_offsets = (pcre_uint8 *)(common->private_data_ptrs + total_length);
+ memset(common->then_offsets, 0, total_length);
+ set_then_offsets(common, common->start, NULL);
+ }
+
+if (common->read_only_data_size > 0)
+ {
+ common->read_only_data = (sljit_uw *)SLJIT_MALLOC(common->read_only_data_size);
+ if (common->read_only_data == NULL)
+ {
+ SLJIT_FREE(common->optimized_cbracket);
+ SLJIT_FREE(common->private_data_ptrs);
+ return;
+ }
+ common->read_only_data_ptr = common->read_only_data;
+ }
+
+compiler = sljit_create_compiler();
+if (!compiler)
+ {
+ SLJIT_FREE(common->optimized_cbracket);
+ SLJIT_FREE(common->private_data_ptrs);
+ if (common->read_only_data)
+ SLJIT_FREE(common->read_only_data);
+ return;
+ }
+common->compiler = compiler;
+
+/* Main pcre_jit_exec entry. */
+sljit_emit_enter(compiler, 1, 5, 5, private_data_size);
+
+/* Register init. */
+reset_ovector(common, (re->top_bracket + 1) * 2);
+if (common->req_char_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr, SLJIT_SCRATCH_REG1, 0);
+
+OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_SAVED_REG1, 0);
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_SAVED_REG1, 0);
+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
+OP1(SLJIT_MOV_UI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match));
+OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base));
+OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit));
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LIMIT_MATCH, TMP1, 0);
+
+if (mode == JIT_PARTIAL_SOFT_COMPILE)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);
+if (common->mark_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0);
+if (common->control_head_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0);
+
+/* Main part of the matching */
+if ((re->options & PCRE_ANCHORED) == 0)
+ {
+ mainloop_label = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0);
+ continue_match_label = LABEL();
+ /* Forward search if possible. */
+ if ((re->options & PCRE_NO_START_OPTIMIZE) == 0)
+ {
+ if (mode == JIT_COMPILE && fast_forward_first_n_chars(common, (re->options & PCRE_FIRSTLINE) != 0))
+ {
+ /* If read_only_data is reallocated, we might have an allocation failure. */
+ if (common->read_only_data_size > 0 && common->read_only_data == NULL)
+ {
+ sljit_free_compiler(compiler);
+ SLJIT_FREE(common->optimized_cbracket);
+ SLJIT_FREE(common->private_data_ptrs);
+ return;
+ }
+ }
+ else if ((re->flags & PCRE_FIRSTSET) != 0)
+ fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0, (re->options & PCRE_FIRSTLINE) != 0);
+ else if ((re->flags & PCRE_STARTLINE) != 0)
+ fast_forward_newline(common, (re->options & PCRE_FIRSTLINE) != 0);
+ else if ((re->flags & PCRE_STARTLINE) == 0 && study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)
+ fast_forward_start_bits(common, study->start_bits, (re->options & PCRE_FIRSTLINE) != 0);
+ }
+ }
+else
+ continue_match_label = LABEL();
+
+if (mode == JIT_COMPILE && study->minlength > 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
+ {
+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength));
+ minlength_check_failed = CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0);
+ }
+if (common->req_char_ptr != 0)
+ reqbyte_notfound = search_requested_char(common, (pcre_uchar)re->req_char, (re->flags & PCRE_RCH_CASELESS) != 0, (re->flags & PCRE_FIRSTSET) != 0);
+
+/* Store the current STR_PTR in OVECTOR(0). */
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
+/* Copy the limit of allowed recursions. */
+OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LIMIT_MATCH);
+if (common->capture_last_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, -1);
+
+if (common->needs_start_ptr)
+ {
+ SLJIT_ASSERT(common->start_ptr != OVECTOR(0));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr, STR_PTR, 0);
+ }
+else
+ SLJIT_ASSERT(common->start_ptr == OVECTOR(0));
+
+/* Copy the beginning of the string. */
+if (mode == JIT_PARTIAL_SOFT_COMPILE)
+ {
+ jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start + sizeof(sljit_sw), STR_PTR, 0);
+ JUMPHERE(jump);
+ }
+else if (mode == JIT_PARTIAL_HARD_COMPILE)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0);
+
+compile_matchingpath(common, common->start, ccend, &rootbacktrack);
+if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ {
+ sljit_free_compiler(compiler);
+ SLJIT_FREE(common->optimized_cbracket);
+ SLJIT_FREE(common->private_data_ptrs);
+ if (common->read_only_data)
+ SLJIT_FREE(common->read_only_data);
+ return;
+ }
+
+if (common->might_be_empty)
+ {
+ empty_match = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
+ empty_match_found_label = LABEL();
+ }
+
+common->accept_label = LABEL();
+if (common->accept != NULL)
+ set_jumps(common->accept, common->accept_label);
+
+/* This means we have a match. Update the ovector. */
+copy_ovector(common, re->top_bracket + 1);
+common->quit_label = common->forced_quit_label = LABEL();
+if (common->quit != NULL)
+ set_jumps(common->quit, common->quit_label);
+if (common->forced_quit != NULL)
+ set_jumps(common->forced_quit, common->forced_quit_label);
+if (minlength_check_failed != NULL)
+ SET_LABEL(minlength_check_failed, common->forced_quit_label);
+sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);
+
+if (mode != JIT_COMPILE)
+ {
+ common->partialmatchlabel = LABEL();
+ set_jumps(common->partialmatch, common->partialmatchlabel);
+ return_with_partial_match(common, common->quit_label);
+ }
+
+if (common->might_be_empty)
+ empty_match_backtrack_label = LABEL();
+compile_backtrackingpath(common, rootbacktrack.top);
+if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ {
+ sljit_free_compiler(compiler);
+ SLJIT_FREE(common->optimized_cbracket);
+ SLJIT_FREE(common->private_data_ptrs);
+ if (common->read_only_data)
+ SLJIT_FREE(common->read_only_data);
+ return;
+ }
+
+SLJIT_ASSERT(rootbacktrack.prev == NULL);
+reset_match_label = LABEL();
+
+if (mode == JIT_PARTIAL_SOFT_COMPILE)
+ {
+ /* Update hit_start only in the first time. */
+ jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, TMP1, 0);
+ JUMPHERE(jump);
+ }
+
+/* Check we have remaining characters. */
+if ((re->options & PCRE_ANCHORED) == 0 && (re->options & PCRE_FIRSTLINE) != 0)
+ {
+ SLJIT_ASSERT(common->first_line_end != 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end);
+ }
+
+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr);
+
+if ((re->options & PCRE_ANCHORED) == 0)
+ {
+ if (common->ff_newline_shortcut != NULL)
+ {
+ if ((re->options & PCRE_FIRSTLINE) == 0)
+ CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, common->ff_newline_shortcut);
+ /* There cannot be more newlines here. */
+ }
+ else
+ {
+ if ((re->options & PCRE_FIRSTLINE) == 0)
+ CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop_label);
+ else
+ CMPTO(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0, mainloop_label);
+ }
+ }
+
+/* No more remaining characters. */
+if (reqbyte_notfound != NULL)
+ JUMPHERE(reqbyte_notfound);
+
+if (mode == JIT_PARTIAL_SOFT_COMPILE)
+ CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1, common->partialmatchlabel);
+
+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
+JUMPTO(SLJIT_JUMP, common->quit_label);
+
+flush_stubs(common);
+
+if (common->might_be_empty)
+ {
+ JUMPHERE(empty_match);
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_backtrack_label);
+ OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
+ CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found_label);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+ CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found_label);
+ JUMPTO(SLJIT_JUMP, empty_match_backtrack_label);
+ }
+
+common->currententry = common->entries;
+common->local_exit = TRUE;
+quit_label = common->quit_label;
+while (common->currententry != NULL)
+ {
+ /* Might add new entries. */
+ compile_recurse(common);
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ {
+ sljit_free_compiler(compiler);
+ SLJIT_FREE(common->optimized_cbracket);
+ SLJIT_FREE(common->private_data_ptrs);
+ if (common->read_only_data)
+ SLJIT_FREE(common->read_only_data);
+ return;
+ }
+ flush_stubs(common);
+ common->currententry = common->currententry->next;
+ }
+common->local_exit = FALSE;
+common->quit_label = quit_label;
+
+/* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */
+/* This is a (really) rare case. */
+set_jumps(common->stackalloc, LABEL());
+/* RETURN_ADDR is not a saved register. */
+sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0);
+OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
+OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top), STACK_TOP, 0);
+OP2(SLJIT_ADD, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE);
+
+sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize));
+jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
+OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
+OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top));
+OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit));
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
+sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
+
+/* Allocation failed. */
+JUMPHERE(jump);
+/* We break the return address cache here, but this is a really rare case. */
+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT);
+JUMPTO(SLJIT_JUMP, common->quit_label);
+
+/* Call limit reached. */
+set_jumps(common->calllimit, LABEL());
+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT);
+JUMPTO(SLJIT_JUMP, common->quit_label);
+
+if (common->revertframes != NULL)
+ {
+ set_jumps(common->revertframes, LABEL());
+ do_revertframes(common);
+ }
+if (common->wordboundary != NULL)
+ {
+ set_jumps(common->wordboundary, LABEL());
+ check_wordboundary(common);
+ }
+if (common->anynewline != NULL)
+ {
+ set_jumps(common->anynewline, LABEL());
+ check_anynewline(common);
+ }
+if (common->hspace != NULL)
+ {
+ set_jumps(common->hspace, LABEL());
+ check_hspace(common);
+ }
+if (common->vspace != NULL)
+ {
+ set_jumps(common->vspace, LABEL());
+ check_vspace(common);
+ }
+if (common->casefulcmp != NULL)
+ {
+ set_jumps(common->casefulcmp, LABEL());
+ do_casefulcmp(common);
+ }
+if (common->caselesscmp != NULL)
+ {
+ set_jumps(common->caselesscmp, LABEL());
+ do_caselesscmp(common);
+ }
+if (common->reset_match != NULL)
+ {
+ set_jumps(common->reset_match, LABEL());
+ do_reset_match(common, (re->top_bracket + 1) * 2);
+ CMPTO(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0, continue_match_label);
+ OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);
+ JUMPTO(SLJIT_JUMP, reset_match_label);
+ }
+#ifdef SUPPORT_UTF
+#ifdef COMPILE_PCRE8
+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);
+ }
+#endif /* COMPILE_PCRE8 */
+#endif /* SUPPORT_UTF */
+#ifdef SUPPORT_UCP
+if (common->getucd != NULL)
+ {
+ set_jumps(common->getucd, LABEL());
+ do_getucd(common);
+ }
+#endif
+
+SLJIT_ASSERT(common->read_only_data + (common->read_only_data_size >> SLJIT_WORD_SHIFT) == common->read_only_data_ptr);
+SLJIT_FREE(common->optimized_cbracket);
+SLJIT_FREE(common->private_data_ptrs);
+
+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->addr = sljit_get_label_addr(label_addr->label);
+ label_addr = label_addr->next;
+ }
+sljit_free_compiler(compiler);
+if (executable_func == NULL)
+ {
+ if (common->read_only_data)
+ SLJIT_FREE(common->read_only_data);
+ return;
+ }
+
+/* Reuse the function descriptor if possible. */
+if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra->executable_jit != NULL)
+ functions = (executable_functions *)extra->executable_jit;
+else
+ {
+ /* Note: If your memory-checker has flagged the allocation below as a
+ * memory leak, it is probably because you either forgot to call
+ * pcre_free_study() (or pcre16_free_study()) on the pcre_extra (or
+ * pcre16_extra) object, or you called said function after having
+ * cleared the PCRE_EXTRA_EXECUTABLE_JIT bit from the "flags" field
+ * of the object. (The function will only free the JIT data if the
+ * bit remains set, as the bit indicates that the pointer to the data
+ * is valid.)
+ */
+ functions = SLJIT_MALLOC(sizeof(executable_functions));
+ if (functions == NULL)
+ {
+ /* This case is highly unlikely since we just recently
+ freed a lot of memory. Not impossible though. */
+ sljit_free_code(executable_func);
+ if (common->read_only_data)
+ SLJIT_FREE(common->read_only_data);
+ return;
+ }
+ memset(functions, 0, sizeof(executable_functions));
+ functions->top_bracket = (re->top_bracket + 1) * 2;
+ functions->limit_match = (re->flags & PCRE_MLSET) != 0 ? re->limit_match : 0;
+ extra->executable_jit = functions;
+ extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT;
+ }
+
+functions->executable_funcs[mode] = executable_func;
+functions->read_only_data[mode] = common->read_only_data;
+functions->executable_sizes[mode] = executable_size;
+}
+
+static int jit_machine_stack_exec(jit_arguments *arguments, void* executable_func)
+{
+union {
+ void* executable_func;
+ jit_function call_executable_func;
+} convert_executable_func;
+pcre_uint8 local_space[MACHINE_STACK_SIZE];
+struct sljit_stack local_stack;
+
+local_stack.top = (sljit_sw)&local_space;
+local_stack.base = local_stack.top;
+local_stack.limit = local_stack.base + MACHINE_STACK_SIZE;
+local_stack.max_limit = local_stack.limit;
+arguments->stack = &local_stack;
+convert_executable_func.executable_func = executable_func;
+return convert_executable_func.call_executable_func(arguments);
+}
+
+int
+PRIV(jit_exec)(const PUBL(extra) *extra_data, const pcre_uchar *subject,
+ int length, int start_offset, int options, int *offsets, int offset_count)
+{
+executable_functions *functions = (executable_functions *)extra_data->executable_jit;
+union {
+ void* executable_func;
+ jit_function call_executable_func;
+} convert_executable_func;
+jit_arguments arguments;
+int max_offset_count;
+int retval;
+int mode = JIT_COMPILE;
+
+if ((options & PCRE_PARTIAL_HARD) != 0)
+ mode = JIT_PARTIAL_HARD_COMPILE;
+else if ((options & PCRE_PARTIAL_SOFT) != 0)
+ mode = JIT_PARTIAL_SOFT_COMPILE;
+
+if (functions->executable_funcs[mode] == NULL)
+ return PCRE_ERROR_JIT_BADOPTION;
+
+/* Sanity checks should be handled by pcre_exec. */
+arguments.str = subject + start_offset;
+arguments.begin = subject;
+arguments.end = subject + length;
+arguments.mark_ptr = NULL;
+/* JIT decreases this value less frequently than the interpreter. */
+arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (pcre_uint32)(extra_data->match_limit);
+if (functions->limit_match != 0 && functions->limit_match < arguments.limit_match)
+ arguments.limit_match = functions->limit_match;
+arguments.notbol = (options & PCRE_NOTBOL) != 0;
+arguments.noteol = (options & PCRE_NOTEOL) != 0;
+arguments.notempty = (options & PCRE_NOTEMPTY) != 0;
+arguments.notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0;
+arguments.offsets = offsets;
+arguments.callout_data = (extra_data->flags & PCRE_EXTRA_CALLOUT_DATA) != 0 ? extra_data->callout_data : NULL;
+arguments.real_offset_count = offset_count;
+
+/* pcre_exec() rounds offset_count to a multiple of 3, and then uses only 2/3 of
+the output vector for storing captured strings, with the remainder used as
+workspace. We don't need the workspace here. For compatibility, we limit the
+number of captured strings in the same way as pcre_exec(), so that the user
+gets the same result with and without JIT. */
+
+if (offset_count != 2)
+ offset_count = ((offset_count - (offset_count % 3)) * 2) / 3;
+max_offset_count = functions->top_bracket;
+if (offset_count > max_offset_count)
+ offset_count = max_offset_count;
+arguments.offset_count = offset_count;
+
+if (functions->callback)
+ arguments.stack = (struct sljit_stack *)functions->callback(functions->userdata);
+else
+ arguments.stack = (struct sljit_stack *)functions->userdata;
+
+if (arguments.stack == NULL)
+ retval = jit_machine_stack_exec(&arguments, functions->executable_funcs[mode]);
+else
+ {
+ convert_executable_func.executable_func = functions->executable_funcs[mode];
+ retval = convert_executable_func.call_executable_func(&arguments);
+ }
+
+if (retval * 2 > offset_count)
+ retval = 0;
+if ((extra_data->flags & PCRE_EXTRA_MARK) != 0)
+ *(extra_data->mark) = arguments.mark_ptr;
+
+return retval;
+}
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_jit_exec(const pcre *argument_re, const pcre_extra *extra_data,
+ PCRE_SPTR subject, int length, int start_offset, int options,
+ int *offsets, int offset_count, pcre_jit_stack *stack)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_jit_exec(const pcre16 *argument_re, const pcre16_extra *extra_data,
+ PCRE_SPTR16 subject, int length, int start_offset, int options,
+ int *offsets, int offset_count, pcre16_jit_stack *stack)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre32_jit_exec(const pcre32 *argument_re, const pcre32_extra *extra_data,
+ PCRE_SPTR32 subject, int length, int start_offset, int options,
+ int *offsets, int offset_count, pcre32_jit_stack *stack)
+#endif
+{
+pcre_uchar *subject_ptr = (pcre_uchar *)subject;
+executable_functions *functions = (executable_functions *)extra_data->executable_jit;
+union {
+ void* executable_func;
+ jit_function call_executable_func;
+} convert_executable_func;
+jit_arguments arguments;
+int max_offset_count;
+int retval;
+int mode = JIT_COMPILE;
+
+SLJIT_UNUSED_ARG(argument_re);
+
+/* Plausibility checks */
+if ((options & ~PUBLIC_JIT_EXEC_OPTIONS) != 0) return PCRE_ERROR_JIT_BADOPTION;
+
+if ((options & PCRE_PARTIAL_HARD) != 0)
+ mode = JIT_PARTIAL_HARD_COMPILE;
+else if ((options & PCRE_PARTIAL_SOFT) != 0)
+ mode = JIT_PARTIAL_SOFT_COMPILE;
+
+if (functions->executable_funcs[mode] == NULL)
+ return PCRE_ERROR_JIT_BADOPTION;
+
+/* Sanity checks should be handled by pcre_exec. */
+arguments.stack = (struct sljit_stack *)stack;
+arguments.str = subject_ptr + start_offset;
+arguments.begin = subject_ptr;
+arguments.end = subject_ptr + length;
+arguments.mark_ptr = NULL;
+/* JIT decreases this value less frequently than the interpreter. */
+arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (pcre_uint32)(extra_data->match_limit);
+if (functions->limit_match != 0 && functions->limit_match < arguments.limit_match)
+ arguments.limit_match = functions->limit_match;
+arguments.notbol = (options & PCRE_NOTBOL) != 0;
+arguments.noteol = (options & PCRE_NOTEOL) != 0;
+arguments.notempty = (options & PCRE_NOTEMPTY) != 0;
+arguments.notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0;
+arguments.offsets = offsets;
+arguments.callout_data = (extra_data->flags & PCRE_EXTRA_CALLOUT_DATA) != 0 ? extra_data->callout_data : NULL;
+arguments.real_offset_count = offset_count;
+
+/* pcre_exec() rounds offset_count to a multiple of 3, and then uses only 2/3 of
+the output vector for storing captured strings, with the remainder used as
+workspace. We don't need the workspace here. For compatibility, we limit the
+number of captured strings in the same way as pcre_exec(), so that the user
+gets the same result with and without JIT. */
+
+if (offset_count != 2)
+ offset_count = ((offset_count - (offset_count % 3)) * 2) / 3;
+max_offset_count = functions->top_bracket;
+if (offset_count > max_offset_count)
+ offset_count = max_offset_count;
+arguments.offset_count = offset_count;
+
+convert_executable_func.executable_func = functions->executable_funcs[mode];
+retval = convert_executable_func.call_executable_func(&arguments);
+
+if (retval * 2 > offset_count)
+ retval = 0;
+if ((extra_data->flags & PCRE_EXTRA_MARK) != 0)
+ *(extra_data->mark) = arguments.mark_ptr;
+
+return retval;
+}
+
+void
+PRIV(jit_free)(void *executable_funcs)
+{
+int i;
+executable_functions *functions = (executable_functions *)executable_funcs;
+for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)
+ {
+ if (functions->executable_funcs[i] != NULL)
+ sljit_free_code(functions->executable_funcs[i]);
+ if (functions->read_only_data[i] != NULL)
+ SLJIT_FREE(functions->read_only_data[i]);
+ }
+SLJIT_FREE(functions);
+}
+
+int
+PRIV(jit_get_size)(void *executable_funcs)
+{
+int i;
+sljit_uw size = 0;
+sljit_uw *executable_sizes = ((executable_functions *)executable_funcs)->executable_sizes;
+for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)
+ size += executable_sizes[i];
+return (int)size;
+}
+
+const char*
+PRIV(jit_get_target)(void)
+{
+return sljit_get_platform_name();
+}
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DECL pcre_jit_stack *
+pcre_jit_stack_alloc(int startsize, int maxsize)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DECL pcre16_jit_stack *
+pcre16_jit_stack_alloc(int startsize, int maxsize)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DECL pcre32_jit_stack *
+pcre32_jit_stack_alloc(int startsize, int maxsize)
+#endif
+{
+if (startsize < 1 || maxsize < 1)
+ return NULL;
+if (startsize > maxsize)
+ startsize = maxsize;
+startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
+maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
+return (PUBL(jit_stack)*)sljit_allocate_stack(startsize, maxsize);
+}
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DECL void
+pcre_jit_stack_free(pcre_jit_stack *stack)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DECL void
+pcre16_jit_stack_free(pcre16_jit_stack *stack)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DECL void
+pcre32_jit_stack_free(pcre32_jit_stack *stack)
+#endif
+{
+sljit_free_stack((struct sljit_stack *)stack);
+}
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DECL void
+pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DECL void
+pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DECL void
+pcre32_assign_jit_stack(pcre32_extra *extra, pcre32_jit_callback callback, void *userdata)
+#endif
+{
+executable_functions *functions;
+if (extra != NULL &&
+ (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
+ extra->executable_jit != NULL)
+ {
+ functions = (executable_functions *)extra->executable_jit;
+ functions->callback = callback;
+ functions->userdata = userdata;
+ }
+}
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DECL void
+pcre_jit_free_unused_memory(void)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DECL void
+pcre16_jit_free_unused_memory(void)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DECL void
+pcre32_jit_free_unused_memory(void)
+#endif
+{
+sljit_free_unused_memory_exec();
+}
+
+#else /* SUPPORT_JIT */
+
+/* These are dummy functions to avoid linking errors when JIT support is not
+being compiled. */
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DECL pcre_jit_stack *
+pcre_jit_stack_alloc(int startsize, int maxsize)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DECL pcre16_jit_stack *
+pcre16_jit_stack_alloc(int startsize, int maxsize)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DECL pcre32_jit_stack *
+pcre32_jit_stack_alloc(int startsize, int maxsize)
+#endif
+{
+(void)startsize;
+(void)maxsize;
+return NULL;
+}
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DECL void
+pcre_jit_stack_free(pcre_jit_stack *stack)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DECL void
+pcre16_jit_stack_free(pcre16_jit_stack *stack)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DECL void
+pcre32_jit_stack_free(pcre32_jit_stack *stack)
+#endif
+{
+(void)stack;
+}
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DECL void
+pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DECL void
+pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DECL void
+pcre32_assign_jit_stack(pcre32_extra *extra, pcre32_jit_callback callback, void *userdata)
+#endif
+{
+(void)extra;
+(void)callback;
+(void)userdata;
+}
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DECL void
+pcre_jit_free_unused_memory(void)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DECL void
+pcre16_jit_free_unused_memory(void)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DECL void
+pcre32_jit_free_unused_memory(void)
+#endif
+{
+}
+
+#endif
+
+/* End of pcre_jit_compile.c */
diff --git a/plugins/Pcre16/src/pcre_maketables.c b/plugins/Pcre16/src/pcre_maketables.c
new file mode 100644
index 0000000000..a44a6eaa90
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_maketables.c
@@ -0,0 +1,156 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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 external function pcre_maketables(), which builds
+character tables for PCRE in the current locale. The file is compiled on its
+own as part of the PCRE library. However, it is also included in the
+compilation of dftables.c, in which case the macro DFTABLES is defined. */
+
+
+#ifndef DFTABLES
+# ifdef HAVE_CONFIG_H
+# include "config.h"
+# endif
+# include "pcre_internal.h"
+#endif
+
+
+/*************************************************
+* Create PCRE character tables *
+*************************************************/
+
+/* This function builds a set of character tables for use by PCRE and returns
+a pointer to them. They are build using the ctype functions, and consequently
+their contents will depend upon the current locale setting. When compiled as
+part of the library, the store is obtained via PUBL(malloc)(), but when
+compiled inside dftables, use malloc().
+
+Arguments: none
+Returns: pointer to the contiguous block of data
+*/
+
+#if defined COMPILE_PCRE8
+const unsigned char *
+pcre_maketables(void)
+#elif defined COMPILE_PCRE16
+const unsigned char *
+pcre16_maketables(void)
+#elif defined COMPILE_PCRE32
+const unsigned char *
+pcre32_maketables(void)
+#endif
+{
+unsigned char *yield, *p;
+int i;
+
+#ifndef DFTABLES
+yield = (unsigned char*)(PUBL(malloc))(tables_length);
+#else
+yield = (unsigned char*)malloc(tables_length);
+#endif
+
+if (yield == NULL) return NULL;
+p = yield;
+
+/* First comes the lower casing table */
+
+for (i = 0; i < 256; i++) *p++ = tolower(i);
+
+/* Next the case-flipping table */
+
+for (i = 0; i < 256; i++) *p++ = islower(i)? toupper(i) : tolower(i);
+
+/* Then the character class tables. Don't try to be clever and save effort on
+exclusive ones - in some locales things may be different.
+
+Note that the table for "space" includes everything "isspace" gives, including
+VT in the default locale. This makes it work for the POSIX class [:space:].
+From release 8.34 is is also correct for Perl space, because Perl added VT at
+release 5.18.
+
+Note also that it is possible for a character to be alnum or alpha without
+being lower or upper, such as "male and female ordinals" (\xAA and \xBA) in the
+fr_FR locale (at least under Debian Linux's locales as of 12/2005). So we must
+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);
+ }
+p += cbit_length;
+
+/* Finally, the character type table. In this, we used to exclude VT from the
+white space chars, because Perl didn't recognize it as such for \s and for
+comments within regexes. However, Perl changed at release 5.18, so PCRE changed
+at release 8.34. */
+
+for (i = 0; i < 256; i++)
+ {
+ int x = 0;
+ if (isspace(i)) x += ctype_space;
+ if (isalpha(i)) x += ctype_letter;
+ if (isdigit(i)) x += ctype_digit;
+ if (isxdigit(i)) x += ctype_xdigit;
+ if (isalnum(i) || i == '_') x += ctype_word;
+
+ /* Note: strchr includes the terminating zero in the characters it considers.
+ In this instance, that is ok because we want binary zero to be flagged as a
+ meta-character, which in this sense is any character that terminates a run
+ of data characters. */
+
+ if (strchr("\\*+?{^.$|()[", i) != 0) x += ctype_meta;
+ *p++ = x;
+ }
+
+return yield;
+}
+
+/* End of pcre_maketables.c */
diff --git a/plugins/Pcre16/src/pcre_newline.c b/plugins/Pcre16/src/pcre_newline.c
new file mode 100644
index 0000000000..b8f5a4de19
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_newline.c
@@ -0,0 +1,210 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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 internal functions for testing newlines when more than
+one kind of newline is to be recognized. When a newline is found, its length is
+returned. In principle, we could implement several newline "types", each
+referring to a different set of newline characters. At present, PCRE supports
+only NLTYPE_FIXED, which gets handled without these functions, NLTYPE_ANYCRLF,
+and NLTYPE_ANY. The full list of Unicode newline characters is taken from
+http://unicode.org/unicode/reports/tr18/. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+
+
+/*************************************************
+* Check for newline at given position *
+*************************************************/
+
+/* It is guaranteed that the initial value of ptr is less than the end of the
+string that is being processed.
+
+Arguments:
+ ptr pointer to possible newline
+ type the newline type
+ endptr pointer to the end of the string
+ lenptr where to return the length
+ utf TRUE if in utf mode
+
+Returns: TRUE or FALSE
+*/
+
+BOOL
+PRIV(is_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR endptr, int *lenptr,
+ BOOL utf)
+{
+pcre_uint32 c;
+(void)utf;
+#ifdef SUPPORT_UTF
+if (utf)
+ {
+ GETCHAR(c, ptr);
+ }
+else
+#endif /* SUPPORT_UTF */
+ c = *ptr;
+
+/* Note that this function is called only for ANY or ANYCRLF. */
+
+if (type == NLTYPE_ANYCRLF) switch(c)
+ {
+ case CHAR_LF: *lenptr = 1; return TRUE;
+ case CHAR_CR: *lenptr = (ptr < endptr - 1 && ptr[1] == CHAR_LF)? 2 : 1;
+ return TRUE;
+ default: return FALSE;
+ }
+
+/* NLTYPE_ANY */
+
+else switch(c)
+ {
+#ifdef EBCDIC
+ case CHAR_NEL:
+#endif
+ case CHAR_LF:
+ case CHAR_VT:
+ case CHAR_FF: *lenptr = 1; return TRUE;
+
+ case CHAR_CR:
+ *lenptr = (ptr < endptr - 1 && ptr[1] == CHAR_LF)? 2 : 1;
+ return TRUE;
+
+#ifndef EBCDIC
+#ifdef COMPILE_PCRE8
+ case CHAR_NEL: *lenptr = utf? 2 : 1; return TRUE;
+ case 0x2028: /* LS */
+ case 0x2029: *lenptr = 3; return TRUE; /* PS */
+#else /* COMPILE_PCRE16 || COMPILE_PCRE32 */
+ case CHAR_NEL:
+ case 0x2028: /* LS */
+ case 0x2029: *lenptr = 1; return TRUE; /* PS */
+#endif /* COMPILE_PCRE8 */
+#endif /* Not EBCDIC */
+
+ default: return FALSE;
+ }
+}
+
+
+
+/*************************************************
+* Check for newline at previous position *
+*************************************************/
+
+/* It is guaranteed that the initial value of ptr is greater than the start of
+the string that is being processed.
+
+Arguments:
+ ptr pointer to possible newline
+ type the newline type
+ startptr pointer to the start of the string
+ lenptr where to return the length
+ utf TRUE if in utf mode
+
+Returns: TRUE or FALSE
+*/
+
+BOOL
+PRIV(was_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR startptr, int *lenptr,
+ BOOL utf)
+{
+pcre_uint32 c;
+(void)utf;
+ptr--;
+#ifdef SUPPORT_UTF
+if (utf)
+ {
+ BACKCHAR(ptr);
+ GETCHAR(c, ptr);
+ }
+else
+#endif /* SUPPORT_UTF */
+ c = *ptr;
+
+/* Note that this function is called only for ANY or ANYCRLF. */
+
+if (type == NLTYPE_ANYCRLF) switch(c)
+ {
+ case CHAR_LF:
+ *lenptr = (ptr > startptr && ptr[-1] == CHAR_CR)? 2 : 1;
+ return TRUE;
+
+ case CHAR_CR: *lenptr = 1; return TRUE;
+ default: return FALSE;
+ }
+
+/* NLTYPE_ANY */
+
+else switch(c)
+ {
+ case CHAR_LF:
+ *lenptr = (ptr > startptr && ptr[-1] == CHAR_CR)? 2 : 1;
+ return TRUE;
+
+#ifdef EBCDIC
+ case CHAR_NEL:
+#endif
+ case CHAR_VT:
+ case CHAR_FF:
+ case CHAR_CR: *lenptr = 1; return TRUE;
+
+#ifndef EBCDIC
+#ifdef COMPILE_PCRE8
+ case CHAR_NEL: *lenptr = utf? 2 : 1; return TRUE;
+ case 0x2028: /* LS */
+ case 0x2029: *lenptr = 3; return TRUE; /* PS */
+#else /* COMPILE_PCRE16 || COMPILE_PCRE32 */
+ case CHAR_NEL:
+ case 0x2028: /* LS */
+ case 0x2029: *lenptr = 1; return TRUE; /* PS */
+#endif /* COMPILE_PCRE8 */
+#endif /* NotEBCDIC */
+
+ default: return FALSE;
+ }
+}
+
+/* End of pcre_newline.c */
diff --git a/plugins/Pcre16/src/pcre_refcount.c b/plugins/Pcre16/src/pcre_refcount.c
new file mode 100644
index 0000000000..79efa90f21
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_refcount.c
@@ -0,0 +1,92 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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 external function pcre_refcount(), which is an
+auxiliary function that can be used to maintain a reference count in a compiled
+pattern data block. This might be helpful in applications where the block is
+shared by different users. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+
+/*************************************************
+* Maintain reference count *
+*************************************************/
+
+/* The reference count is a 16-bit field, initialized to zero. It is not
+possible to transfer a non-zero count from one host to a different host that
+has a different byte order - though I can't see why anyone in their right mind
+would ever want to do that!
+
+Arguments:
+ argument_re points to compiled code
+ adjust value to add to the count
+
+Returns: the (possibly updated) count value (a non-negative number), or
+ a negative error number
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_refcount(pcre *argument_re, int adjust)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_refcount(pcre16 *argument_re, int adjust)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre32_refcount(pcre32 *argument_re, int adjust)
+#endif
+{
+REAL_PCRE *re = (REAL_PCRE *)argument_re;
+if (re == NULL) return PCRE_ERROR_NULL;
+if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
+if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
+re->ref_count = (-adjust > re->ref_count)? 0 :
+ (adjust + re->ref_count > 65535)? 65535 :
+ re->ref_count + adjust;
+return re->ref_count;
+}
+
+/* End of pcre_refcount.c */
diff --git a/plugins/Pcre16/src/pcre_string_utils.c b/plugins/Pcre16/src/pcre_string_utils.c
new file mode 100644
index 0000000000..25eacc8507
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_string_utils.c
@@ -0,0 +1,211 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2014 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 internal functions for comparing and finding the length
+of strings for different data item sizes. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+#ifndef COMPILE_PCRE8
+
+/*************************************************
+* Compare string utilities *
+*************************************************/
+
+/* The following two functions compares two strings. Basically a strcmp
+for non 8 bit characters.
+
+Arguments:
+ str1 first string
+ str2 second string
+
+Returns: 0 if both string are equal (like strcmp), 1 otherwise
+*/
+
+int
+PRIV(strcmp_uc_uc)(const pcre_uchar *str1, const pcre_uchar *str2)
+{
+pcre_uchar c1;
+pcre_uchar c2;
+
+while (*str1 != '\0' || *str2 != '\0')
+ {
+ c1 = *str1++;
+ c2 = *str2++;
+ if (c1 != c2)
+ return ((c1 > c2) << 1) - 1;
+ }
+/* Both length and characters must be equal. */
+return 0;
+}
+
+#ifdef COMPILE_PCRE32
+
+int
+PRIV(strcmp_uc_uc_utf)(const pcre_uchar *str1, const pcre_uchar *str2)
+{
+pcre_uchar c1;
+pcre_uchar c2;
+
+while (*str1 != '\0' || *str2 != '\0')
+ {
+ c1 = UCHAR21INC(str1);
+ c2 = UCHAR21INC(str2);
+ if (c1 != c2)
+ return ((c1 > c2) << 1) - 1;
+ }
+/* Both length and characters must be equal. */
+return 0;
+}
+
+#endif /* COMPILE_PCRE32 */
+
+int
+PRIV(strcmp_uc_c8)(const pcre_uchar *str1, const char *str2)
+{
+const pcre_uint8 *ustr2 = (pcre_uint8 *)str2;
+pcre_uchar c1;
+pcre_uchar c2;
+
+while (*str1 != '\0' || *ustr2 != '\0')
+ {
+ c1 = *str1++;
+ c2 = (pcre_uchar)*ustr2++;
+ if (c1 != c2)
+ return ((c1 > c2) << 1) - 1;
+ }
+/* Both length and characters must be equal. */
+return 0;
+}
+
+#ifdef COMPILE_PCRE32
+
+int
+PRIV(strcmp_uc_c8_utf)(const pcre_uchar *str1, const char *str2)
+{
+const pcre_uint8 *ustr2 = (pcre_uint8 *)str2;
+pcre_uchar c1;
+pcre_uchar c2;
+
+while (*str1 != '\0' || *ustr2 != '\0')
+ {
+ c1 = UCHAR21INC(str1);
+ c2 = (pcre_uchar)*ustr2++;
+ if (c1 != c2)
+ return ((c1 > c2) << 1) - 1;
+ }
+/* Both length and characters must be equal. */
+return 0;
+}
+
+#endif /* COMPILE_PCRE32 */
+
+/* The following two functions compares two, fixed length
+strings. Basically an strncmp for non 8 bit characters.
+
+Arguments:
+ str1 first string
+ str2 second string
+ num size of the string
+
+Returns: 0 if both string are equal (like strcmp), 1 otherwise
+*/
+
+int
+PRIV(strncmp_uc_uc)(const pcre_uchar *str1, const pcre_uchar *str2, unsigned int num)
+{
+pcre_uchar c1;
+pcre_uchar c2;
+
+while (num-- > 0)
+ {
+ c1 = *str1++;
+ c2 = *str2++;
+ if (c1 != c2)
+ return ((c1 > c2) << 1) - 1;
+ }
+/* Both length and characters must be equal. */
+return 0;
+}
+
+int
+PRIV(strncmp_uc_c8)(const pcre_uchar *str1, const char *str2, unsigned int num)
+{
+const pcre_uint8 *ustr2 = (pcre_uint8 *)str2;
+pcre_uchar c1;
+pcre_uchar c2;
+
+while (num-- > 0)
+ {
+ c1 = *str1++;
+ c2 = (pcre_uchar)*ustr2++;
+ if (c1 != c2)
+ return ((c1 > c2) << 1) - 1;
+ }
+/* Both length and characters must be equal. */
+return 0;
+}
+
+/* The following function returns with the length of
+a zero terminated string. Basically an strlen for non 8 bit characters.
+
+Arguments:
+ str string
+
+Returns: length of the string
+*/
+
+unsigned int
+PRIV(strlen_uc)(const pcre_uchar *str)
+{
+unsigned int len = 0;
+while (*str++ != 0)
+ len++;
+return len;
+}
+
+#endif /* !COMPILE_PCRE8 */
+
+/* End of pcre_string_utils.c */
diff --git a/plugins/Pcre16/src/pcre_study.c b/plugins/Pcre16/src/pcre_study.c
new file mode 100644
index 0000000000..ab9510e20e
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_study.c
@@ -0,0 +1,1626 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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 external function pcre_study(), along with local
+supporting functions. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+#define SET_BIT(c) start_bits[c/8] |= (1 << (c&7))
+
+/* Returns from set_start_bits() */
+
+enum { SSB_FAIL, SSB_DONE, SSB_CONTINUE, SSB_UNKNOWN };
+
+
+
+/*************************************************
+* Find the minimum subject length for a group *
+*************************************************/
+
+/* Scan a parenthesized group and compute the minimum length of subject that
+is needed to match it. This is a lower bound; it does not mean there is a
+string of that length that matches. In UTF8 mode, the result is in characters
+rather than bytes.
+
+Arguments:
+ re compiled pattern block
+ code pointer to start of group (the bracket)
+ startcode pointer to start of the whole pattern's code
+ options the compiling options
+ int RECURSE depth
+
+Returns: the minimum length
+ -1 if \C in UTF-8 mode or (*ACCEPT) was encountered
+ -2 internal error (missing capturing bracket)
+ -3 internal error (opcode not listed)
+*/
+
+static int
+find_minlength(const REAL_PCRE *re, const pcre_uchar *code,
+ const pcre_uchar *startcode, int options, int recurse_depth)
+{
+int length = -1;
+/* PCRE_UTF16 has the same value as PCRE_UTF8. */
+BOOL utf = (options & PCRE_UTF8) != 0;
+BOOL had_recurse = FALSE;
+register int branchlength = 0;
+register pcre_uchar *cc = (pcre_uchar *)code + 1 + LINK_SIZE;
+
+if (*code == OP_CBRA || *code == OP_SCBRA ||
+ *code == OP_CBRAPOS || *code == OP_SCBRAPOS) cc += IMM2_SIZE;
+
+/* 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. */
+
+for (;;)
+ {
+ int d, min;
+ pcre_uchar *cs, *ce;
+ register pcre_uchar op = *cc;
+
+ switch (op)
+ {
+ case OP_COND:
+ case OP_SCOND:
+
+ /* If there is only one branch in a condition, the implied branch has zero
+ length, so we don't add anything. This covers the DEFINE "condition"
+ automatically. */
+
+ cs = cc + GET(cc, 1);
+ if (*cs != OP_ALT)
+ {
+ cc = cs + 1 + LINK_SIZE;
+ break;
+ }
+
+ /* Otherwise we can fall through and treat it the same as any other
+ subpattern. */
+
+ case OP_CBRA:
+ case OP_SCBRA:
+ case OP_BRA:
+ case OP_SBRA:
+ case OP_CBRAPOS:
+ case OP_SCBRAPOS:
+ case OP_BRAPOS:
+ case OP_SBRAPOS:
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ d = find_minlength(re, cc, startcode, options, recurse_depth);
+ if (d < 0) return d;
+ branchlength += d;
+ do cc += GET(cc, 1); while (*cc == OP_ALT);
+ cc += 1 + LINK_SIZE;
+ break;
+
+ /* ACCEPT makes things far too complicated; we have to give up. */
+
+ case OP_ACCEPT:
+ case OP_ASSERT_ACCEPT:
+ return -1;
+
+ /* 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. */
+
+ case OP_ALT:
+ case OP_KET:
+ case OP_KETRMAX:
+ case OP_KETRMIN:
+ case OP_KETRPOS:
+ case OP_END:
+ if (length < 0 || (!had_recurse && branchlength < length))
+ length = branchlength;
+ if (op != OP_ALT) return length;
+ cc += 1 + LINK_SIZE;
+ branchlength = 0;
+ had_recurse = FALSE;
+ break;
+
+ /* Skip over assertive subpatterns */
+
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ do cc += GET(cc, 1); while (*cc == OP_ALT);
+ /* Fall through */
+
+ /* Skip over things that don't match chars */
+
+ case OP_REVERSE:
+ case OP_CREF:
+ case OP_DNCREF:
+ case OP_RREF:
+ case OP_DNRREF:
+ case OP_DEF:
+ case OP_CALLOUT:
+ case OP_SOD:
+ case OP_SOM:
+ case OP_EOD:
+ case OP_EODN:
+ case OP_CIRC:
+ case OP_CIRCM:
+ case OP_DOLL:
+ case OP_DOLLM:
+ case OP_NOT_WORD_BOUNDARY:
+ case OP_WORD_BOUNDARY:
+ cc += PRIV(OP_lengths)[*cc];
+ break;
+
+ /* Skip over a subpattern that has a {0} or {0,x} quantifier */
+
+ case OP_BRAZERO:
+ case OP_BRAMINZERO:
+ case OP_BRAPOSZERO:
+ case OP_SKIPZERO:
+ cc += PRIV(OP_lengths)[*cc];
+ do cc += GET(cc, 1); while (*cc == OP_ALT);
+ cc += 1 + LINK_SIZE;
+ break;
+
+ /* Handle literal characters and + repetitions */
+
+ case OP_CHAR:
+ case OP_CHARI:
+ case OP_NOT:
+ case OP_NOTI:
+ case OP_PLUS:
+ case OP_PLUSI:
+ case OP_MINPLUS:
+ case OP_MINPLUSI:
+ case OP_POSPLUS:
+ case OP_POSPLUSI:
+ case OP_NOTPLUS:
+ case OP_NOTPLUSI:
+ case OP_NOTMINPLUS:
+ case OP_NOTMINPLUSI:
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSPLUSI:
+ branchlength++;
+ cc += 2;
+#ifdef SUPPORT_UTF
+ if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ break;
+
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEPOSPLUS:
+ branchlength++;
+ cc += (cc[1] == OP_PROP || cc[1] == OP_NOTPROP)? 4 : 2;
+ break;
+
+ /* Handle exact repetitions. The count is already in characters, but we
+ need to skip over a multibyte character in UTF8 mode. */
+
+ case OP_EXACT:
+ case OP_EXACTI:
+ case OP_NOTEXACT:
+ case OP_NOTEXACTI:
+ branchlength += GET2(cc,1);
+ cc += 2 + IMM2_SIZE;
+#ifdef SUPPORT_UTF
+ if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ break;
+
+ case OP_TYPEEXACT:
+ branchlength += GET2(cc,1);
+ cc += 2 + IMM2_SIZE + ((cc[1 + IMM2_SIZE] == OP_PROP
+ || cc[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0);
+ break;
+
+ /* Handle single-char non-literal matchers */
+
+ case OP_PROP:
+ case OP_NOTPROP:
+ cc += 2;
+ /* Fall through */
+
+ case OP_NOT_DIGIT:
+ case OP_DIGIT:
+ case OP_NOT_WHITESPACE:
+ case OP_WHITESPACE:
+ case OP_NOT_WORDCHAR:
+ case OP_WORDCHAR:
+ case OP_ANY:
+ case OP_ALLANY:
+ case OP_EXTUNI:
+ case OP_HSPACE:
+ case OP_NOT_HSPACE:
+ case OP_VSPACE:
+ case OP_NOT_VSPACE:
+ branchlength++;
+ cc++;
+ break;
+
+ /* "Any newline" might match two characters, but it also might match just
+ one. */
+
+ case OP_ANYNL:
+ branchlength += 1;
+ cc++;
+ break;
+
+ /* The single-byte matcher means we can't proceed in UTF-8 mode. (In
+ non-UTF-8 mode \C will actually be turned into OP_ALLANY, so won't ever
+ appear, but leave the code, just in case.) */
+
+ case OP_ANYBYTE:
+#ifdef SUPPORT_UTF
+ if (utf) return -1;
+#endif
+ branchlength++;
+ cc++;
+ break;
+
+ /* For repeated character types, we have to test for \p and \P, which have
+ an extra two bytes of parameters. */
+
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ case OP_TYPEPOSSTAR:
+ case OP_TYPEPOSQUERY:
+ if (cc[1] == OP_PROP || cc[1] == OP_NOTPROP) cc += 2;
+ cc += PRIV(OP_lengths)[op];
+ break;
+
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ case OP_TYPEPOSUPTO:
+ if (cc[1 + IMM2_SIZE] == OP_PROP
+ || cc[1 + IMM2_SIZE] == OP_NOTPROP) cc += 2;
+ cc += PRIV(OP_lengths)[op];
+ break;
+
+ /* Check a class for variable quantification */
+
+ case OP_CLASS:
+ case OP_NCLASS:
+#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ case OP_XCLASS:
+ /* The original code caused an unsigned overflow in 64 bit systems,
+ so now we use a conditional statement. */
+ if (op == OP_XCLASS)
+ cc += GET(cc, 1);
+ else
+ cc += PRIV(OP_lengths)[OP_CLASS];
+#else
+ cc += PRIV(OP_lengths)[OP_CLASS];
+#endif
+
+ switch (*cc)
+ {
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ case OP_CRPOSPLUS:
+ branchlength++;
+ /* Fall through */
+
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ case OP_CRPOSSTAR:
+ case OP_CRPOSQUERY:
+ cc++;
+ break;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ case OP_CRPOSRANGE:
+ branchlength += GET2(cc,1);
+ cc += 1 + 2 * IMM2_SIZE;
+ break;
+
+ default:
+ branchlength++;
+ break;
+ }
+ break;
+
+ /* Backreferences and subroutine calls are treated in the same way: we find
+ the minimum length for the subpattern. A recursion, however, causes an
+ a flag to be set that causes the length of this branch to be ignored. The
+ logic is that a recursion can only make sense if there is another
+ alternation that stops the recursing. That will provide the minimum length
+ (when no recursion happens). A backreference within the group that it is
+ referencing behaves in the same way.
+
+ If PCRE_JAVASCRIPT_COMPAT 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. */
+
+ case OP_DNREF: /* Duplicate named pattern back reference */
+ case OP_DNREFI:
+ if ((options & PCRE_JAVASCRIPT_COMPAT) == 0)
+ {
+ int count = GET2(cc, 1+IMM2_SIZE);
+ pcre_uchar *slot = (pcre_uchar *)re +
+ re->name_table_offset + GET2(cc, 1) * re->name_entry_size;
+ d = INT_MAX;
+ while (count-- > 0)
+ {
+ ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(slot, 0));
+ if (cs == NULL) return -2;
+ do ce += GET(ce, 1); while (*ce == OP_ALT);
+ if (cc > cs && cc < ce)
+ {
+ d = 0;
+ had_recurse = TRUE;
+ break;
+ }
+ else
+ {
+ int dd = find_minlength(re, cs, startcode, options, recurse_depth);
+ if (dd < d) d = dd;
+ }
+ slot += re->name_entry_size;
+ }
+ }
+ else d = 0;
+ cc += 1 + 2*IMM2_SIZE;
+ goto REPEAT_BACK_REFERENCE;
+
+ case OP_REF: /* Single back reference */
+ case OP_REFI:
+ if ((options & PCRE_JAVASCRIPT_COMPAT) == 0)
+ {
+ ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(cc, 1));
+ if (cs == NULL) return -2;
+ do ce += GET(ce, 1); while (*ce == OP_ALT);
+ if (cc > cs && cc < ce)
+ {
+ d = 0;
+ had_recurse = TRUE;
+ }
+ else
+ {
+ d = find_minlength(re, cs, startcode, options, recurse_depth);
+ }
+ }
+ else d = 0;
+ cc += 1 + IMM2_SIZE;
+
+ /* Handle repeated back references */
+
+ REPEAT_BACK_REFERENCE:
+ switch (*cc)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ case OP_CRPOSSTAR:
+ case OP_CRPOSQUERY:
+ min = 0;
+ cc++;
+ break;
+
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ case OP_CRPOSPLUS:
+ min = 1;
+ cc++;
+ break;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ case OP_CRPOSRANGE:
+ min = GET2(cc, 1);
+ cc += 1 + 2 * IMM2_SIZE;
+ break;
+
+ default:
+ min = 1;
+ break;
+ }
+
+ branchlength += min * d;
+ break;
+
+ /* We can easily detect direct recursion, but not mutual recursion. This is
+ caught by a recursion depth count. */
+
+ case OP_RECURSE:
+ cs = ce = (pcre_uchar *)startcode + GET(cc, 1);
+ do ce += GET(ce, 1); while (*ce == OP_ALT);
+ if ((cc > cs && cc < ce) || recurse_depth > 10)
+ had_recurse = TRUE;
+ else
+ {
+ branchlength += find_minlength(re, cs, startcode, options,
+ recurse_depth + 1);
+ }
+ cc += 1 + LINK_SIZE;
+ break;
+
+ /* Anything else does not or need not match a character. We can get the
+ item's length from the table, but for those that can match zero occurrences
+ of a character, we must take special action for UTF-8 characters. As it
+ happens, the "NOT" versions of these opcodes are used at present only for
+ ASCII characters, so they could be omitted from this list. However, in
+ future that may change, so we include them here so as not to leave a
+ gotcha for a future maintainer. */
+
+ case OP_UPTO:
+ case OP_UPTOI:
+ case OP_NOTUPTO:
+ case OP_NOTUPTOI:
+ case OP_MINUPTO:
+ case OP_MINUPTOI:
+ case OP_NOTMINUPTO:
+ case OP_NOTMINUPTOI:
+ case OP_POSUPTO:
+ case OP_POSUPTOI:
+ case OP_NOTPOSUPTO:
+ case OP_NOTPOSUPTOI:
+
+ case OP_STAR:
+ case OP_STARI:
+ case OP_NOTSTAR:
+ case OP_NOTSTARI:
+ case OP_MINSTAR:
+ case OP_MINSTARI:
+ case OP_NOTMINSTAR:
+ case OP_NOTMINSTARI:
+ case OP_POSSTAR:
+ case OP_POSSTARI:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSSTARI:
+
+ case OP_QUERY:
+ case OP_QUERYI:
+ case OP_NOTQUERY:
+ case OP_NOTQUERYI:
+ case OP_MINQUERY:
+ case OP_MINQUERYI:
+ case OP_NOTMINQUERY:
+ case OP_NOTMINQUERYI:
+ case OP_POSQUERY:
+ case OP_POSQUERYI:
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSQUERYI:
+
+ cc += PRIV(OP_lengths)[op];
+#ifdef SUPPORT_UTF
+ if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ break;
+
+ /* Skip these, but we need to add in the name length. */
+
+ case OP_MARK:
+ case OP_PRUNE_ARG:
+ case OP_SKIP_ARG:
+ case OP_THEN_ARG:
+ cc += PRIV(OP_lengths)[op] + cc[1];
+ break;
+
+ /* The remaining opcodes are just skipped over. */
+
+ case OP_CLOSE:
+ case OP_COMMIT:
+ case OP_FAIL:
+ case OP_PRUNE:
+ case OP_SET_SOM:
+ case OP_SKIP:
+ case OP_THEN:
+ cc += PRIV(OP_lengths)[op];
+ break;
+
+ /* This should not occur: we list all opcodes explicitly so that when
+ new ones get added they are properly considered. */
+
+ default:
+ return -3;
+ }
+ }
+/* Control never gets here */
+}
+
+
+
+/*************************************************
+* Set a bit and maybe its alternate case *
+*************************************************/
+
+/* Given a character, set its first byte's bit in the table, and also the
+corresponding bit for the other version of a letter if we are caseless. In
+UTF-8 mode, for characters greater than 127, we can only do the caseless thing
+when Unicode property support is available.
+
+Arguments:
+ start_bits points to the bit map
+ p points to the character
+ caseless the caseless flag
+ cd the block with char table pointers
+ utf TRUE for UTF-8 / UTF-16 / UTF-32 mode
+
+Returns: pointer after the character
+*/
+
+static const pcre_uchar *
+set_table_bit(pcre_uint8 *start_bits, const pcre_uchar *p, BOOL caseless,
+ compile_data *cd, BOOL utf)
+{
+pcre_uint32 c = *p;
+
+#ifdef COMPILE_PCRE8
+SET_BIT(c);
+
+#ifdef SUPPORT_UTF
+if (utf && c > 127)
+ {
+ GETCHARINC(c, p);
+#ifdef SUPPORT_UCP
+ if (caseless)
+ {
+ pcre_uchar buff[6];
+ c = UCD_OTHERCASE(c);
+ (void)PRIV(ord2utf)(c, buff);
+ SET_BIT(buff[0]);
+ }
+#endif /* Not SUPPORT_UCP */
+ return p;
+ }
+#else /* Not SUPPORT_UTF */
+(void)(utf); /* Stops warning for unused parameter */
+#endif /* SUPPORT_UTF */
+
+/* Not UTF-8 mode, or character is less than 127. */
+
+if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]);
+return p + 1;
+#endif /* COMPILE_PCRE8 */
+
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+if (c > 0xff)
+ {
+ c = 0xff;
+ caseless = FALSE;
+ }
+SET_BIT(c);
+
+#ifdef SUPPORT_UTF
+if (utf && c > 127)
+ {
+ GETCHARINC(c, p);
+#ifdef SUPPORT_UCP
+ if (caseless)
+ {
+ c = UCD_OTHERCASE(c);
+ if (c > 0xff)
+ c = 0xff;
+ SET_BIT(c);
+ }
+#endif /* SUPPORT_UCP */
+ return p;
+ }
+#else /* Not SUPPORT_UTF */
+(void)(utf); /* Stops warning for unused parameter */
+#endif /* SUPPORT_UTF */
+
+if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]);
+return p + 1;
+#endif
+}
+
+
+
+/*************************************************
+* Set bits for a positive character type *
+*************************************************/
+
+/* This function sets starting bits for a character type. In UTF-8 mode, we can
+only do a direct setting for bytes less than 128, as otherwise there can be
+confusion with bytes in the middle of UTF-8 characters. In a "traditional"
+environment, the tables will only recognize ASCII characters anyway, but in at
+least one Windows environment, some higher bytes bits were set in the tables.
+So we deal with that case by considering the UTF-8 encoding.
+
+Arguments:
+ start_bits the starting bitmap
+ cbit type the type of character wanted
+ table_limit 32 for non-UTF-8; 16 for UTF-8
+ cd the block with char table pointers
+
+Returns: nothing
+*/
+
+static void
+set_type_bits(pcre_uint8 *start_bits, int cbit_type, unsigned int table_limit,
+ compile_data *cd)
+{
+register pcre_uint32 c;
+for (c = 0; c < table_limit; c++) start_bits[c] |= cd->cbits[c+cbit_type];
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+if (table_limit == 32) return;
+for (c = 128; c < 256; c++)
+ {
+ if ((cd->cbits[c/8] & (1 << (c&7))) != 0)
+ {
+ pcre_uchar buff[6];
+ (void)PRIV(ord2utf)(c, buff);
+ SET_BIT(buff[0]);
+ }
+ }
+#endif
+}
+
+
+/*************************************************
+* Set bits for a negative character type *
+*************************************************/
+
+/* This function sets starting bits for a negative character type such as \D.
+In UTF-8 mode, we can only do a direct setting for bytes less than 128, as
+otherwise there can be confusion with bytes in the middle of UTF-8 characters.
+Unlike in the positive case, where we can set appropriate starting bits for
+specific high-valued UTF-8 characters, in this case we have to set the bits for
+all high-valued characters. The lowest is 0xc2, but we overkill by starting at
+0xc0 (192) for simplicity.
+
+Arguments:
+ start_bits the starting bitmap
+ cbit type the type of character wanted
+ table_limit 32 for non-UTF-8; 16 for UTF-8
+ cd the block with char table pointers
+
+Returns: nothing
+*/
+
+static void
+set_nottype_bits(pcre_uint8 *start_bits, int cbit_type, unsigned int table_limit,
+ compile_data *cd)
+{
+register pcre_uint32 c;
+for (c = 0; c < table_limit; c++) start_bits[c] |= ~cd->cbits[c+cbit_type];
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+if (table_limit != 32) for (c = 24; c < 32; c++) start_bits[c] = 0xff;
+#endif
+}
+
+
+
+/*************************************************
+* Create bitmap of starting bytes *
+*************************************************/
+
+/* This function scans a compiled unanchored expression recursively and
+attempts to build a bitmap of the set of possible starting bytes. As time goes
+by, we may be able to get more clever at doing this. The SSB_CONTINUE return is
+useful for parenthesized groups in patterns such as (a*)b where the group
+provides some optional starting bytes but scanning must continue at the outer
+level to find at least one mandatory byte. At the outermost level, this
+function fails unless the result is SSB_DONE.
+
+Arguments:
+ code points to an expression
+ start_bits points to a 32-byte table, initialized to 0
+ utf TRUE if in UTF-8 / UTF-16 / UTF-32 mode
+ cd the block with char table pointers
+
+Returns: SSB_FAIL => Failed to find any starting bytes
+ SSB_DONE => Found mandatory starting bytes
+ SSB_CONTINUE => Found optional starting bytes
+ SSB_UNKNOWN => Hit an unrecognized opcode
+*/
+
+static int
+set_start_bits(const pcre_uchar *code, pcre_uint8 *start_bits, BOOL utf,
+ compile_data *cd)
+{
+register pcre_uint32 c;
+int yield = SSB_DONE;
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+int table_limit = utf? 16:32;
+#else
+int table_limit = 32;
+#endif
+
+#if 0
+/* ========================================================================= */
+/* The following comment and code was inserted in January 1999. In May 2006,
+when it was observed to cause compiler warnings about unused values, I took it
+out again. If anybody is still using OS/2, they will have to put it back
+manually. */
+
+/* This next statement and the later reference to dummy are here in order to
+trick the optimizer of the IBM C compiler for OS/2 into generating correct
+code. Apparently IBM isn't going to fix the problem, and we would rather not
+disable optimization (in this module it actually makes a big difference, and
+the pcre module can use all the optimization it can get). */
+
+volatile int dummy;
+/* ========================================================================= */
+#endif
+
+do
+ {
+ BOOL try_next = TRUE;
+ const pcre_uchar *tcode = code + 1 + LINK_SIZE;
+
+ if (*code == OP_CBRA || *code == OP_SCBRA ||
+ *code == OP_CBRAPOS || *code == OP_SCBRAPOS) tcode += IMM2_SIZE;
+
+ while (try_next) /* Loop for items in this branch */
+ {
+ int rc;
+
+ switch(*tcode)
+ {
+ /* If we reach something we don't understand, it means a new opcode has
+ been created that hasn't been added to this code. Hopefully this problem
+ will be discovered during testing. */
+
+ default:
+ return SSB_UNKNOWN;
+
+ /* Fail for a valid opcode that implies no starting bits. */
+
+ case OP_ACCEPT:
+ case OP_ASSERT_ACCEPT:
+ case OP_ALLANY:
+ case OP_ANY:
+ case OP_ANYBYTE:
+ case OP_CIRC:
+ case OP_CIRCM:
+ case OP_CLOSE:
+ case OP_COMMIT:
+ case OP_COND:
+ case OP_CREF:
+ case OP_DEF:
+ case OP_DNCREF:
+ case OP_DNREF:
+ case OP_DNREFI:
+ case OP_DNRREF:
+ case OP_DOLL:
+ case OP_DOLLM:
+ case OP_END:
+ case OP_EOD:
+ case OP_EODN:
+ case OP_EXTUNI:
+ case OP_FAIL:
+ case OP_MARK:
+ case OP_NOT:
+ case OP_NOTEXACT:
+ case OP_NOTEXACTI:
+ case OP_NOTI:
+ case OP_NOTMINPLUS:
+ case OP_NOTMINPLUSI:
+ case OP_NOTMINQUERY:
+ case OP_NOTMINQUERYI:
+ case OP_NOTMINSTAR:
+ case OP_NOTMINSTARI:
+ case OP_NOTMINUPTO:
+ case OP_NOTMINUPTOI:
+ case OP_NOTPLUS:
+ case OP_NOTPLUSI:
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSPLUSI:
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSQUERYI:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSSTARI:
+ case OP_NOTPOSUPTO:
+ case OP_NOTPOSUPTOI:
+ case OP_NOTPROP:
+ case OP_NOTQUERY:
+ case OP_NOTQUERYI:
+ case OP_NOTSTAR:
+ case OP_NOTSTARI:
+ case OP_NOTUPTO:
+ case OP_NOTUPTOI:
+ case OP_NOT_HSPACE:
+ case OP_NOT_VSPACE:
+ case OP_PROP:
+ case OP_PRUNE:
+ case OP_PRUNE_ARG:
+ case OP_RECURSE:
+ case OP_REF:
+ case OP_REFI:
+ case OP_REVERSE:
+ case OP_RREF:
+ case OP_SCOND:
+ case OP_SET_SOM:
+ case OP_SKIP:
+ case OP_SKIP_ARG:
+ case OP_SOD:
+ case OP_SOM:
+ case OP_THEN:
+ case OP_THEN_ARG:
+ return SSB_FAIL;
+
+ /* We can ignore word boundary tests. */
+
+ case OP_WORD_BOUNDARY:
+ case OP_NOT_WORD_BOUNDARY:
+ tcode++;
+ break;
+
+ /* If we hit a bracket or a positive lookahead assertion, recurse to set
+ bits from within the subpattern. If it can't find anything, we have to
+ give up. If it finds some mandatory character(s), we are done for this
+ branch. Otherwise, carry on scanning after the subpattern. */
+
+ case OP_BRA:
+ case OP_SBRA:
+ case OP_CBRA:
+ case OP_SCBRA:
+ case OP_BRAPOS:
+ case OP_SBRAPOS:
+ case OP_CBRAPOS:
+ case OP_SCBRAPOS:
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ case OP_ASSERT:
+ rc = set_start_bits(tcode, start_bits, utf, cd);
+ if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc;
+ if (rc == SSB_DONE) try_next = FALSE; else
+ {
+ do tcode += GET(tcode, 1); while (*tcode == OP_ALT);
+ tcode += 1 + LINK_SIZE;
+ }
+ break;
+
+ /* If we hit ALT or KET, it means we haven't found anything mandatory in
+ this branch, though we might have found something optional. For ALT, we
+ continue with the next alternative, but we have to arrange that the final
+ result from subpattern is SSB_CONTINUE rather than SSB_DONE. For KET,
+ return SSB_CONTINUE: if this is the top level, that indicates failure,
+ but after a nested subpattern, it causes scanning to continue. */
+
+ case OP_ALT:
+ yield = SSB_CONTINUE;
+ try_next = FALSE;
+ break;
+
+ case OP_KET:
+ case OP_KETRMAX:
+ case OP_KETRMIN:
+ case OP_KETRPOS:
+ return SSB_CONTINUE;
+
+ /* Skip over callout */
+
+ case OP_CALLOUT:
+ tcode += 2 + 2*LINK_SIZE;
+ break;
+
+ /* Skip over lookbehind and negative lookahead assertions */
+
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ do tcode += GET(tcode, 1); while (*tcode == OP_ALT);
+ tcode += 1 + LINK_SIZE;
+ break;
+
+ /* BRAZERO does the bracket, but carries on. */
+
+ case OP_BRAZERO:
+ case OP_BRAMINZERO:
+ case OP_BRAPOSZERO:
+ rc = set_start_bits(++tcode, start_bits, utf, cd);
+ if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc;
+/* =========================================================================
+ See the comment at the head of this function concerning the next line,
+ which was an old fudge for the benefit of OS/2.
+ dummy = 1;
+ ========================================================================= */
+ do tcode += GET(tcode,1); while (*tcode == OP_ALT);
+ tcode += 1 + LINK_SIZE;
+ break;
+
+ /* SKIPZERO skips the bracket. */
+
+ case OP_SKIPZERO:
+ tcode++;
+ do tcode += GET(tcode,1); while (*tcode == OP_ALT);
+ tcode += 1 + LINK_SIZE;
+ break;
+
+ /* Single-char * or ? sets the bit and tries the next item */
+
+ case OP_STAR:
+ case OP_MINSTAR:
+ case OP_POSSTAR:
+ case OP_QUERY:
+ case OP_MINQUERY:
+ case OP_POSQUERY:
+ tcode = set_table_bit(start_bits, tcode + 1, FALSE, cd, utf);
+ break;
+
+ case OP_STARI:
+ case OP_MINSTARI:
+ case OP_POSSTARI:
+ case OP_QUERYI:
+ case OP_MINQUERYI:
+ case OP_POSQUERYI:
+ tcode = set_table_bit(start_bits, tcode + 1, TRUE, cd, utf);
+ break;
+
+ /* Single-char upto sets the bit and tries the next */
+
+ case OP_UPTO:
+ case OP_MINUPTO:
+ case OP_POSUPTO:
+ tcode = set_table_bit(start_bits, tcode + 1 + IMM2_SIZE, FALSE, cd, utf);
+ break;
+
+ case OP_UPTOI:
+ case OP_MINUPTOI:
+ case OP_POSUPTOI:
+ tcode = set_table_bit(start_bits, tcode + 1 + IMM2_SIZE, TRUE, cd, utf);
+ break;
+
+ /* At least one single char sets the bit and stops */
+
+ case OP_EXACT:
+ tcode += IMM2_SIZE;
+ /* Fall through */
+ case OP_CHAR:
+ case OP_PLUS:
+ case OP_MINPLUS:
+ case OP_POSPLUS:
+ (void)set_table_bit(start_bits, tcode + 1, FALSE, cd, utf);
+ try_next = FALSE;
+ break;
+
+ case OP_EXACTI:
+ tcode += IMM2_SIZE;
+ /* Fall through */
+ case OP_CHARI:
+ case OP_PLUSI:
+ case OP_MINPLUSI:
+ case OP_POSPLUSI:
+ (void)set_table_bit(start_bits, tcode + 1, TRUE, cd, utf);
+ try_next = FALSE;
+ break;
+
+ /* Special spacing and line-terminating items. These recognize specific
+ lists of characters. The difference between VSPACE and ANYNL is that the
+ latter can match the two-character CRLF sequence, but that is not
+ relevant for finding the first character, so their code here is
+ identical. */
+
+ case OP_HSPACE:
+ SET_BIT(CHAR_HT);
+ SET_BIT(CHAR_SPACE);
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+#ifdef COMPILE_PCRE8
+ SET_BIT(0xC2); /* For U+00A0 */
+ SET_BIT(0xE1); /* For U+1680, U+180E */
+ SET_BIT(0xE2); /* For U+2000 - U+200A, U+202F, U+205F */
+ SET_BIT(0xE3); /* For U+3000 */
+#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ SET_BIT(0xA0);
+ SET_BIT(0xFF); /* For characters > 255 */
+#endif /* COMPILE_PCRE[8|16|32] */
+ }
+ else
+#endif /* SUPPORT_UTF */
+ {
+#ifndef EBCDIC
+ SET_BIT(0xA0);
+#endif /* Not EBCDIC */
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ SET_BIT(0xFF); /* For characters > 255 */
+#endif /* COMPILE_PCRE[16|32] */
+ }
+ try_next = FALSE;
+ break;
+
+ case OP_ANYNL:
+ case OP_VSPACE:
+ SET_BIT(CHAR_LF);
+ SET_BIT(CHAR_VT);
+ SET_BIT(CHAR_FF);
+ SET_BIT(CHAR_CR);
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+#ifdef COMPILE_PCRE8
+ SET_BIT(0xC2); /* For U+0085 */
+ SET_BIT(0xE2); /* For U+2028, U+2029 */
+#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ SET_BIT(CHAR_NEL);
+ SET_BIT(0xFF); /* For characters > 255 */
+#endif /* COMPILE_PCRE[8|16|32] */
+ }
+ else
+#endif /* SUPPORT_UTF */
+ {
+ SET_BIT(CHAR_NEL);
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ SET_BIT(0xFF); /* For characters > 255 */
+#endif
+ }
+ try_next = FALSE;
+ break;
+
+ /* Single character types set the bits and stop. Note that if PCRE_UCP
+ is set, we do not see these op codes because \d etc are converted to
+ properties. Therefore, these apply in the case when only characters less
+ than 256 are recognized to match the types. */
+
+ case OP_NOT_DIGIT:
+ set_nottype_bits(start_bits, cbit_digit, table_limit, cd);
+ try_next = FALSE;
+ break;
+
+ case OP_DIGIT:
+ set_type_bits(start_bits, cbit_digit, table_limit, cd);
+ try_next = FALSE;
+ break;
+
+ /* The cbit_space table has vertical tab as whitespace; we have to
+ ensure it is set as not whitespace. Luckily, the code value is the same
+ (0x0b) in ASCII and EBCDIC, so we can just adjust the appropriate bit. */
+
+ case OP_NOT_WHITESPACE:
+ set_nottype_bits(start_bits, cbit_space, table_limit, cd);
+ start_bits[1] |= 0x08;
+ try_next = FALSE;
+ break;
+
+ /* The cbit_space table has vertical tab as whitespace; we have to not
+ set it from the table. Luckily, the code value is the same (0x0b) in
+ ASCII and EBCDIC, so we can just adjust the appropriate bit. */
+
+ case OP_WHITESPACE:
+ c = start_bits[1]; /* Save in case it was already set */
+ set_type_bits(start_bits, cbit_space, table_limit, cd);
+ start_bits[1] = (start_bits[1] & ~0x08) | c;
+ try_next = FALSE;
+ break;
+
+ case OP_NOT_WORDCHAR:
+ set_nottype_bits(start_bits, cbit_word, table_limit, cd);
+ try_next = FALSE;
+ break;
+
+ case OP_WORDCHAR:
+ set_type_bits(start_bits, cbit_word, table_limit, cd);
+ try_next = FALSE;
+ break;
+
+ /* One or more character type fudges the pointer and restarts, knowing
+ it will hit a single character type and stop there. */
+
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEPOSPLUS:
+ tcode++;
+ break;
+
+ case OP_TYPEEXACT:
+ tcode += 1 + IMM2_SIZE;
+ break;
+
+ /* Zero or more repeats of character types set the bits and then
+ try again. */
+
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ case OP_TYPEPOSUPTO:
+ tcode += IMM2_SIZE; /* Fall through */
+
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPOSSTAR:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ case OP_TYPEPOSQUERY:
+ switch(tcode[1])
+ {
+ default:
+ case OP_ANY:
+ case OP_ALLANY:
+ return SSB_FAIL;
+
+ case OP_HSPACE:
+ SET_BIT(CHAR_HT);
+ SET_BIT(CHAR_SPACE);
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+#ifdef COMPILE_PCRE8
+ SET_BIT(0xC2); /* For U+00A0 */
+ SET_BIT(0xE1); /* For U+1680, U+180E */
+ SET_BIT(0xE2); /* For U+2000 - U+200A, U+202F, U+205F */
+ SET_BIT(0xE3); /* For U+3000 */
+#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ SET_BIT(0xA0);
+ SET_BIT(0xFF); /* For characters > 255 */
+#endif /* COMPILE_PCRE[8|16|32] */
+ }
+ else
+#endif /* SUPPORT_UTF */
+#ifndef EBCDIC
+ SET_BIT(0xA0);
+#endif /* Not EBCDIC */
+ break;
+
+ case OP_ANYNL:
+ case OP_VSPACE:
+ SET_BIT(CHAR_LF);
+ SET_BIT(CHAR_VT);
+ SET_BIT(CHAR_FF);
+ SET_BIT(CHAR_CR);
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+#ifdef COMPILE_PCRE8
+ SET_BIT(0xC2); /* For U+0085 */
+ SET_BIT(0xE2); /* For U+2028, U+2029 */
+#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ SET_BIT(CHAR_NEL);
+ SET_BIT(0xFF); /* For characters > 255 */
+#endif /* COMPILE_PCRE16 */
+ }
+ else
+#endif /* SUPPORT_UTF */
+ SET_BIT(CHAR_NEL);
+ break;
+
+ case OP_NOT_DIGIT:
+ set_nottype_bits(start_bits, cbit_digit, table_limit, cd);
+ break;
+
+ case OP_DIGIT:
+ set_type_bits(start_bits, cbit_digit, table_limit, cd);
+ break;
+
+ /* The cbit_space table has vertical tab as whitespace; we no longer
+ have to play fancy tricks because Perl added VT to its whitespace at
+ release 5.18. PCRE added it at release 8.34. */
+
+ case OP_NOT_WHITESPACE:
+ set_nottype_bits(start_bits, cbit_space, table_limit, cd);
+ break;
+
+ case OP_WHITESPACE:
+ set_type_bits(start_bits, cbit_space, table_limit, cd);
+ break;
+
+ case OP_NOT_WORDCHAR:
+ set_nottype_bits(start_bits, cbit_word, table_limit, cd);
+ break;
+
+ case OP_WORDCHAR:
+ set_type_bits(start_bits, cbit_word, table_limit, cd);
+ break;
+ }
+
+ tcode += 2;
+ break;
+
+ /* Character class where all the information is in a bit map: set the
+ bits and either carry on or not, according to the repeat count. If it was
+ a negative class, and we are operating with UTF-8 characters, any byte
+ with a value >= 0xc4 is a potentially valid starter because it starts a
+ character with a value > 255. */
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_XCLASS:
+ if ((tcode[1 + LINK_SIZE] & XCL_HASPROP) != 0)
+ return SSB_FAIL;
+ /* All bits are set. */
+ if ((tcode[1 + LINK_SIZE] & XCL_MAP) == 0 && (tcode[1 + LINK_SIZE] & XCL_NOT) != 0)
+ return SSB_FAIL;
+#endif
+ /* Fall through */
+
+ case OP_NCLASS:
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (utf)
+ {
+ start_bits[24] |= 0xf0; /* Bits for 0xc4 - 0xc8 */
+ memset(start_bits+25, 0xff, 7); /* Bits for 0xc9 - 0xff */
+ }
+#endif
+#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+ SET_BIT(0xFF); /* For characters > 255 */
+#endif
+ /* Fall through */
+
+ case OP_CLASS:
+ {
+ pcre_uint8 *map;
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ map = NULL;
+ if (*tcode == OP_XCLASS)
+ {
+ if ((tcode[1 + LINK_SIZE] & XCL_MAP) != 0)
+ map = (pcre_uint8 *)(tcode + 1 + LINK_SIZE + 1);
+ tcode += GET(tcode, 1);
+ }
+ else
+#endif
+ {
+ tcode++;
+ map = (pcre_uint8 *)tcode;
+ tcode += 32 / sizeof(pcre_uchar);
+ }
+
+ /* In UTF-8 mode, the bits in a bit map correspond to character
+ values, not to byte values. However, the bit map we are constructing is
+ for byte values. So we have to do a conversion for characters whose
+ value is > 127. In fact, there are only two possible starting bytes for
+ characters in the range 128 - 255. */
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ if (map != NULL)
+#endif
+ {
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+ if (utf)
+ {
+ for (c = 0; c < 16; c++) start_bits[c] |= map[c];
+ for (c = 128; c < 256; c++)
+ {
+ if ((map[c/8] && (1 << (c&7))) != 0)
+ {
+ int d = (c >> 6) | 0xc0; /* Set bit for this starter */
+ start_bits[d/8] |= (1 << (d&7)); /* and then skip on to the */
+ c = (c & 0xc0) + 0x40 - 1; /* next relevant character. */
+ }
+ }
+ }
+ else
+#endif
+ {
+ /* In non-UTF-8 mode, the two bit maps are completely compatible. */
+ for (c = 0; c < 32; c++) start_bits[c] |= map[c];
+ }
+ }
+
+ /* Advance past the bit map, and act on what follows. For a zero
+ minimum repeat, continue; otherwise stop processing. */
+
+ switch (*tcode)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ case OP_CRPOSSTAR:
+ case OP_CRPOSQUERY:
+ tcode++;
+ break;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ case OP_CRPOSRANGE:
+ if (GET2(tcode, 1) == 0) tcode += 1 + 2 * IMM2_SIZE;
+ else try_next = FALSE;
+ break;
+
+ default:
+ try_next = FALSE;
+ break;
+ }
+ }
+ break; /* End of bitmap class handling */
+
+ } /* End of switch */
+ } /* End of try_next loop */
+
+ code += GET(code, 1); /* Advance to next branch */
+ }
+while (*code == OP_ALT);
+return yield;
+}
+
+
+
+
+
+/*************************************************
+* Study a compiled expression *
+*************************************************/
+
+/* This function is handed a compiled expression that it must study to produce
+information that will speed up the matching. It returns a pcre[16]_extra block
+which then gets handed back to pcre_exec().
+
+Arguments:
+ re points to the compiled expression
+ options contains option bits
+ errorptr points to where to place error messages;
+ set NULL unless error
+
+Returns: pointer to a pcre[16]_extra block, with study_data filled in and
+ the appropriate flags set;
+ NULL on error or if no optimization possible
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN pcre_extra * PCRE_CALL_CONVENTION
+pcre_study(const pcre *external_re, int options, const char **errorptr)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN pcre16_extra * PCRE_CALL_CONVENTION
+pcre16_study(const pcre16 *external_re, int options, const char **errorptr)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN pcre32_extra * PCRE_CALL_CONVENTION
+pcre32_study(const pcre32 *external_re, int options, const char **errorptr)
+#endif
+{
+int min;
+BOOL bits_set = FALSE;
+pcre_uint8 start_bits[32];
+PUBL(extra) *extra = NULL;
+pcre_study_data *study;
+const pcre_uint8 *tables;
+pcre_uchar *code;
+compile_data compile_block;
+const REAL_PCRE *re = (const REAL_PCRE *)external_re;
+
+
+*errorptr = NULL;
+
+if (re == NULL || re->magic_number != MAGIC_NUMBER)
+ {
+ *errorptr = "argument is not a compiled regular expression";
+ return NULL;
+ }
+
+if ((re->flags & PCRE_MODE) == 0)
+ {
+#if defined COMPILE_PCRE8
+ *errorptr = "argument not compiled in 8 bit mode";
+#elif defined COMPILE_PCRE16
+ *errorptr = "argument not compiled in 16 bit mode";
+#elif defined COMPILE_PCRE32
+ *errorptr = "argument not compiled in 32 bit mode";
+#endif
+ return NULL;
+ }
+
+if ((options & ~PUBLIC_STUDY_OPTIONS) != 0)
+ {
+ *errorptr = "unknown or incorrect option bit(s) set";
+ return NULL;
+ }
+
+code = (pcre_uchar *)re + re->name_table_offset +
+ (re->name_count * re->name_entry_size);
+
+/* For an anchored pattern, or an unanchored pattern that has a first char, or
+a multiline pattern that matches only at "line starts", there is no point in
+seeking a list of starting bytes. */
+
+if ((re->options & PCRE_ANCHORED) == 0 &&
+ (re->flags & (PCRE_FIRSTSET|PCRE_STARTLINE)) == 0)
+ {
+ int rc;
+
+ /* Set the character tables in the block that is passed around */
+
+ tables = re->tables;
+
+#if defined COMPILE_PCRE8
+ if (tables == NULL)
+ (void)pcre_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
+ (void *)(&tables));
+#elif defined COMPILE_PCRE16
+ if (tables == NULL)
+ (void)pcre16_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
+ (void *)(&tables));
+#elif defined COMPILE_PCRE32
+ if (tables == NULL)
+ (void)pcre32_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
+ (void *)(&tables));
+#endif
+
+ compile_block.lcc = tables + lcc_offset;
+ compile_block.fcc = tables + fcc_offset;
+ compile_block.cbits = tables + cbits_offset;
+ compile_block.ctypes = tables + ctypes_offset;
+
+ /* See if we can find a fixed set of initial characters for the pattern. */
+
+ memset(start_bits, 0, 32 * sizeof(pcre_uint8));
+ rc = set_start_bits(code, start_bits, (re->options & PCRE_UTF8) != 0,
+ &compile_block);
+ bits_set = rc == SSB_DONE;
+ if (rc == SSB_UNKNOWN)
+ {
+ *errorptr = "internal error: opcode not recognized";
+ return NULL;
+ }
+ }
+
+/* Find the minimum length of subject string. */
+
+switch(min = find_minlength(re, code, code, re->options, 0))
+ {
+ case -2: *errorptr = "internal error: missing capturing bracket"; return NULL;
+ case -3: *errorptr = "internal error: opcode not recognized"; return NULL;
+ default: break;
+ }
+
+/* If a set of starting bytes has been identified, or if the minimum length is
+greater than zero, or if JIT optimization has been requested, or if
+PCRE_STUDY_EXTRA_NEEDED is set, get a pcre[16]_extra block and a
+pcre_study_data block. The study data is put in the latter, which is pointed to
+by the former, which may also get additional data set later by the calling
+program. At the moment, the size of pcre_study_data is fixed. We nevertheless
+save it in a field for returning via the pcre_fullinfo() function so that if it
+becomes variable in the future, we don't have to change that code. */
+
+if (bits_set || min > 0 || (options & (
+#ifdef SUPPORT_JIT
+ PCRE_STUDY_JIT_COMPILE | PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE |
+ PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE |
+#endif
+ PCRE_STUDY_EXTRA_NEEDED)) != 0)
+ {
+ extra = (PUBL(extra) *)(PUBL(malloc))
+ (sizeof(PUBL(extra)) + sizeof(pcre_study_data));
+ if (extra == NULL)
+ {
+ *errorptr = "failed to get memory";
+ return NULL;
+ }
+
+ study = (pcre_study_data *)((char *)extra + sizeof(PUBL(extra)));
+ extra->flags = PCRE_EXTRA_STUDY_DATA;
+ extra->study_data = study;
+
+ study->size = sizeof(pcre_study_data);
+ study->flags = 0;
+
+ /* Set the start bits always, to avoid unset memory errors if the
+ study data is written to a file, but set the flag only if any of the bits
+ are set, to save time looking when none are. */
+
+ if (bits_set)
+ {
+ study->flags |= PCRE_STUDY_MAPPED;
+ memcpy(study->start_bits, start_bits, sizeof(start_bits));
+ }
+ else memset(study->start_bits, 0, 32 * sizeof(pcre_uint8));
+
+#ifdef PCRE_DEBUG
+ if (bits_set)
+ {
+ pcre_uint8 *ptr = start_bits;
+ int i;
+
+ printf("Start bits:\n");
+ for (i = 0; i < 32; i++)
+ printf("%3d: %02x%s", i * 8, *ptr++, ((i + 1) & 0x7) != 0? " " : "\n");
+ }
+#endif
+
+ /* Always set the minlength value in the block, because the JIT compiler
+ makes use of it. However, don't set the bit unless the length is greater than
+ zero - the interpretive pcre_exec() and pcre_dfa_exec() needn't waste time
+ checking the zero case. */
+
+ if (min > 0)
+ {
+ study->flags |= PCRE_STUDY_MINLEN;
+ study->minlength = min;
+ }
+ else study->minlength = 0;
+
+ /* If JIT support was compiled and requested, attempt the JIT compilation.
+ If no starting bytes were found, and the minimum length is zero, and JIT
+ compilation fails, abandon the extra block and return NULL, unless
+ PCRE_STUDY_EXTRA_NEEDED is set. */
+
+#ifdef SUPPORT_JIT
+ extra->executable_jit = NULL;
+ if ((options & PCRE_STUDY_JIT_COMPILE) != 0)
+ PRIV(jit_compile)(re, extra, JIT_COMPILE);
+ if ((options & PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE) != 0)
+ PRIV(jit_compile)(re, extra, JIT_PARTIAL_SOFT_COMPILE);
+ if ((options & PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE) != 0)
+ PRIV(jit_compile)(re, extra, JIT_PARTIAL_HARD_COMPILE);
+
+ if (study->flags == 0 && (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) == 0 &&
+ (options & PCRE_STUDY_EXTRA_NEEDED) == 0)
+ {
+#if defined COMPILE_PCRE8
+ pcre_free_study(extra);
+#elif defined COMPILE_PCRE16
+ pcre16_free_study(extra);
+#elif defined COMPILE_PCRE32
+ pcre32_free_study(extra);
+#endif
+ extra = NULL;
+ }
+#endif
+ }
+
+return extra;
+}
+
+
+/*************************************************
+* Free the study data *
+*************************************************/
+
+/* This function frees the memory that was obtained by pcre_study().
+
+Argument: a pointer to the pcre[16]_extra block
+Returns: nothing
+*/
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN void
+pcre_free_study(pcre_extra *extra)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN void
+pcre16_free_study(pcre16_extra *extra)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN void
+pcre32_free_study(pcre32_extra *extra)
+#endif
+{
+if (extra == NULL)
+ return;
+#ifdef SUPPORT_JIT
+if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
+ extra->executable_jit != NULL)
+ PRIV(jit_free)(extra->executable_jit);
+#endif
+PUBL(free)(extra);
+}
+
+/* End of pcre_study.c */
diff --git a/plugins/Pcre16/src/pcre_tables.c b/plugins/Pcre16/src/pcre_tables.c
new file mode 100644
index 0000000000..f38ab52cbb
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_tables.c
@@ -0,0 +1,658 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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.
+-----------------------------------------------------------------------------
+*/
+
+#ifndef PCRE_INCLUDED
+
+/* This module contains some fixed tables that are used by more than one of the
+PCRE code modules. The tables are also #included by the pcretest program, which
+uses macros to change their names from _pcre_xxx to xxxx, thereby avoiding name
+clashes with the library. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+#endif /* PCRE_INCLUDED */
+
+/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that
+the definition is next to the definition of the opcodes in pcre_internal.h. */
+
+const pcre_uint8 PRIV(OP_lengths)[] = { OP_LENGTHS };
+
+/* Tables of horizontal and vertical whitespace characters, suitable for
+adding to classes. */
+
+const pcre_uint32 PRIV(hspace_list)[] = { HSPACE_LIST };
+const pcre_uint32 PRIV(vspace_list)[] = { VSPACE_LIST };
+
+
+
+/*************************************************
+* Tables for UTF-8 support *
+*************************************************/
+
+/* These are the breakpoints for different numbers of bytes in a UTF-8
+character. */
+
+#if (defined SUPPORT_UTF && defined COMPILE_PCRE8) \
+ || (defined PCRE_INCLUDED && (defined SUPPORT_PCRE16 || defined SUPPORT_PCRE32))
+
+/* These tables are also required by pcretest in 16- or 32-bit mode. */
+
+const int PRIV(utf8_table1)[] =
+ { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
+
+const int PRIV(utf8_table1_size) = sizeof(PRIV(utf8_table1)) / sizeof(int);
+
+/* These are the indicator bits and the mask for the data bits to set in the
+first byte of a character, indexed by the number of additional bytes. */
+
+const int PRIV(utf8_table2)[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
+const int PRIV(utf8_table3)[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
+
+/* Table of the number of extra bytes, indexed by the first byte masked with
+0x3f. The highest number for a valid UTF-8 first byte is in fact 0x3d. */
+
+const pcre_uint8 PRIV(utf8_table4)[] = {
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
+
+#endif /* (SUPPORT_UTF && COMPILE_PCRE8) || (PCRE_INCLUDED && SUPPORT_PCRE[16|32])*/
+
+#ifdef SUPPORT_UTF
+
+/* Table to translate from particular type value to the general value. */
+
+const pcre_uint32 PRIV(ucp_gentype)[] = {
+ ucp_C, ucp_C, ucp_C, ucp_C, ucp_C, /* Cc, Cf, Cn, Co, Cs */
+ ucp_L, ucp_L, ucp_L, ucp_L, ucp_L, /* Ll, Lu, Lm, Lo, Lt */
+ ucp_M, ucp_M, ucp_M, /* Mc, Me, Mn */
+ ucp_N, ucp_N, ucp_N, /* Nd, Nl, No */
+ ucp_P, ucp_P, ucp_P, ucp_P, ucp_P, /* Pc, Pd, Pe, Pf, Pi */
+ ucp_P, ucp_P, /* Ps, Po */
+ ucp_S, ucp_S, ucp_S, ucp_S, /* Sc, Sk, Sm, So */
+ ucp_Z, ucp_Z, ucp_Z /* Zl, Zp, Zs */
+};
+
+/* This table encodes the rules for finding the end of an extended grapheme
+cluster. Every code point has a grapheme break property which is one of the
+ucp_gbXX values defined in ucp.h. The 2-dimensional table is indexed by the
+properties of two adjacent code points. The left property selects a word from
+the table, and the right property selects a bit from that word like this:
+
+ ucp_gbtable[left-property] & (1 << 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:
+
+1. Break at the start and end of text (pretty obviously).
+
+2. Do not break between a CR and LF; otherwise, break before and after
+ controls.
+
+3. Do not break Hangul syllable sequences, the rules for which are:
+
+ L may be followed by L, V, LV or LVT
+ LV or V may be followed by V or T
+ LVT or T may be followed by T
+
+4. Do not break before extending characters.
+
+The next two rules are only for extended grapheme clusters (but that's what we
+are implementing).
+
+5. Do not break before SpacingMarks.
+
+6. Do not break after Prepend characters.
+
+7. Otherwise, break everywhere.
+*/
+
+const pcre_uint32 PRIV(ucp_gbtable[]) = {
+ (1<<ucp_gbLF), /* 0 CR */
+ 0, /* 1 LF */
+ 0, /* 2 Control */
+ (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark), /* 3 Extend */
+ (1<<ucp_gbExtend)|(1<<ucp_gbPrepend)| /* 4 Prepend */
+ (1<<ucp_gbSpacingMark)|(1<<ucp_gbL)|
+ (1<<ucp_gbV)|(1<<ucp_gbT)|(1<<ucp_gbLV)|
+ (1<<ucp_gbLVT)|(1<<ucp_gbOther),
+
+ (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark), /* 5 SpacingMark */
+ (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbL)| /* 6 L */
+ (1<<ucp_gbL)|(1<<ucp_gbV)|(1<<ucp_gbLV)|(1<<ucp_gbLVT),
+
+ (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbV)| /* 7 V */
+ (1<<ucp_gbT),
+
+ (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbT), /* 8 T */
+ (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbV)| /* 9 LV */
+ (1<<ucp_gbT),
+
+ (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbT), /* 10 LVT */
+ (1<<ucp_gbRegionalIndicator), /* 11 RegionalIndicator */
+ (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark) /* 12 Other */
+};
+
+#ifdef SUPPORT_JIT
+/* This table reverses PRIV(ucp_gentype). We can save the cost
+of a memory load. */
+
+const int PRIV(ucp_typerange)[] = {
+ ucp_Cc, ucp_Cs,
+ ucp_Ll, ucp_Lu,
+ ucp_Mc, ucp_Mn,
+ ucp_Nd, ucp_No,
+ ucp_Pc, ucp_Ps,
+ ucp_Sc, ucp_So,
+ ucp_Zl, ucp_Zs,
+};
+#endif /* SUPPORT_JIT */
+
+/* The pcre_utt[] table below translates Unicode property names into type and
+code values. It is searched by binary chop, so must be in collating sequence of
+name. Originally, the table contained pointers to the name strings in the first
+field of each entry. However, that leads to a large number of relocations when
+a shared library is dynamically loaded. A significant reduction is made by
+putting all the names into a single, large string and then using offsets in the
+table itself. Maintenance is more error-prone, but frequent changes to this
+data are unlikely.
+
+July 2008: There is now a script called maint/GenerateUtt.py that can be used
+to generate this data automatically instead of maintaining it by hand.
+
+The script was updated in March 2009 to generate a new EBCDIC-compliant
+version. Like all other character and string literals that are compared against
+the regular expression pattern, we must use STR_ macros instead of literal
+strings to make sure that UTF-8 support works on EBCDIC platforms. */
+
+#define STRING_Any0 STR_A STR_n STR_y "\0"
+#define STRING_Arabic0 STR_A STR_r STR_a STR_b STR_i STR_c "\0"
+#define STRING_Armenian0 STR_A STR_r STR_m STR_e STR_n STR_i STR_a STR_n "\0"
+#define STRING_Avestan0 STR_A STR_v STR_e STR_s STR_t STR_a STR_n "\0"
+#define STRING_Balinese0 STR_B STR_a STR_l STR_i STR_n STR_e STR_s STR_e "\0"
+#define STRING_Bamum0 STR_B STR_a STR_m STR_u STR_m "\0"
+#define STRING_Batak0 STR_B STR_a STR_t STR_a STR_k "\0"
+#define STRING_Bengali0 STR_B STR_e STR_n STR_g STR_a STR_l STR_i "\0"
+#define STRING_Bopomofo0 STR_B STR_o STR_p STR_o STR_m STR_o STR_f STR_o "\0"
+#define STRING_Brahmi0 STR_B STR_r STR_a STR_h STR_m STR_i "\0"
+#define STRING_Braille0 STR_B STR_r STR_a STR_i STR_l STR_l STR_e "\0"
+#define STRING_Buginese0 STR_B STR_u STR_g STR_i STR_n STR_e STR_s STR_e "\0"
+#define STRING_Buhid0 STR_B STR_u STR_h STR_i STR_d "\0"
+#define STRING_C0 STR_C "\0"
+#define STRING_Canadian_Aboriginal0 STR_C STR_a STR_n STR_a STR_d STR_i STR_a STR_n STR_UNDERSCORE STR_A STR_b STR_o STR_r STR_i STR_g STR_i STR_n STR_a STR_l "\0"
+#define STRING_Carian0 STR_C STR_a STR_r STR_i STR_a STR_n "\0"
+#define STRING_Cc0 STR_C STR_c "\0"
+#define STRING_Cf0 STR_C STR_f "\0"
+#define STRING_Chakma0 STR_C STR_h STR_a STR_k STR_m STR_a "\0"
+#define STRING_Cham0 STR_C STR_h STR_a STR_m "\0"
+#define STRING_Cherokee0 STR_C STR_h STR_e STR_r STR_o STR_k STR_e STR_e "\0"
+#define STRING_Cn0 STR_C STR_n "\0"
+#define STRING_Co0 STR_C STR_o "\0"
+#define STRING_Common0 STR_C STR_o STR_m STR_m STR_o STR_n "\0"
+#define STRING_Coptic0 STR_C STR_o STR_p STR_t STR_i STR_c "\0"
+#define STRING_Cs0 STR_C STR_s "\0"
+#define STRING_Cuneiform0 STR_C STR_u STR_n STR_e STR_i STR_f STR_o STR_r STR_m "\0"
+#define STRING_Cypriot0 STR_C STR_y STR_p STR_r STR_i STR_o STR_t "\0"
+#define STRING_Cyrillic0 STR_C STR_y STR_r STR_i STR_l STR_l STR_i STR_c "\0"
+#define STRING_Deseret0 STR_D STR_e STR_s STR_e STR_r STR_e STR_t "\0"
+#define STRING_Devanagari0 STR_D STR_e STR_v STR_a STR_n STR_a STR_g STR_a STR_r STR_i "\0"
+#define STRING_Egyptian_Hieroglyphs0 STR_E STR_g STR_y STR_p STR_t STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
+#define STRING_Ethiopic0 STR_E STR_t STR_h STR_i STR_o STR_p STR_i STR_c "\0"
+#define STRING_Georgian0 STR_G STR_e STR_o STR_r STR_g STR_i STR_a STR_n "\0"
+#define STRING_Glagolitic0 STR_G STR_l STR_a STR_g STR_o STR_l STR_i STR_t STR_i STR_c "\0"
+#define STRING_Gothic0 STR_G STR_o STR_t STR_h STR_i STR_c "\0"
+#define STRING_Greek0 STR_G STR_r STR_e STR_e STR_k "\0"
+#define STRING_Gujarati0 STR_G STR_u STR_j STR_a STR_r STR_a STR_t STR_i "\0"
+#define STRING_Gurmukhi0 STR_G STR_u STR_r STR_m STR_u STR_k STR_h STR_i "\0"
+#define STRING_Han0 STR_H STR_a STR_n "\0"
+#define STRING_Hangul0 STR_H STR_a STR_n STR_g STR_u STR_l "\0"
+#define STRING_Hanunoo0 STR_H STR_a STR_n STR_u STR_n STR_o STR_o "\0"
+#define STRING_Hebrew0 STR_H STR_e STR_b STR_r STR_e STR_w "\0"
+#define STRING_Hiragana0 STR_H STR_i STR_r STR_a STR_g STR_a STR_n STR_a "\0"
+#define STRING_Imperial_Aramaic0 STR_I STR_m STR_p STR_e STR_r STR_i STR_a STR_l STR_UNDERSCORE STR_A STR_r STR_a STR_m STR_a STR_i STR_c "\0"
+#define STRING_Inherited0 STR_I STR_n STR_h STR_e STR_r STR_i STR_t STR_e STR_d "\0"
+#define STRING_Inscriptional_Pahlavi0 STR_I STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_UNDERSCORE STR_P STR_a STR_h STR_l STR_a STR_v STR_i "\0"
+#define STRING_Inscriptional_Parthian0 STR_I STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_UNDERSCORE STR_P STR_a STR_r STR_t STR_h STR_i STR_a STR_n "\0"
+#define STRING_Javanese0 STR_J STR_a STR_v STR_a STR_n STR_e STR_s STR_e "\0"
+#define STRING_Kaithi0 STR_K STR_a STR_i STR_t STR_h STR_i "\0"
+#define STRING_Kannada0 STR_K STR_a STR_n STR_n STR_a STR_d STR_a "\0"
+#define STRING_Katakana0 STR_K STR_a STR_t STR_a STR_k STR_a STR_n STR_a "\0"
+#define STRING_Kayah_Li0 STR_K STR_a STR_y STR_a STR_h STR_UNDERSCORE STR_L STR_i "\0"
+#define STRING_Kharoshthi0 STR_K STR_h STR_a STR_r STR_o STR_s STR_h STR_t STR_h STR_i "\0"
+#define STRING_Khmer0 STR_K STR_h STR_m STR_e STR_r "\0"
+#define STRING_L0 STR_L "\0"
+#define STRING_L_AMPERSAND0 STR_L STR_AMPERSAND "\0"
+#define STRING_Lao0 STR_L STR_a STR_o "\0"
+#define STRING_Latin0 STR_L STR_a STR_t STR_i STR_n "\0"
+#define STRING_Lepcha0 STR_L STR_e STR_p STR_c STR_h STR_a "\0"
+#define STRING_Limbu0 STR_L STR_i STR_m STR_b STR_u "\0"
+#define STRING_Linear_B0 STR_L STR_i STR_n STR_e STR_a STR_r STR_UNDERSCORE STR_B "\0"
+#define STRING_Lisu0 STR_L STR_i STR_s STR_u "\0"
+#define STRING_Ll0 STR_L STR_l "\0"
+#define STRING_Lm0 STR_L STR_m "\0"
+#define STRING_Lo0 STR_L STR_o "\0"
+#define STRING_Lt0 STR_L STR_t "\0"
+#define STRING_Lu0 STR_L STR_u "\0"
+#define STRING_Lycian0 STR_L STR_y STR_c STR_i STR_a STR_n "\0"
+#define STRING_Lydian0 STR_L STR_y STR_d STR_i STR_a STR_n "\0"
+#define STRING_M0 STR_M "\0"
+#define STRING_Malayalam0 STR_M STR_a STR_l STR_a STR_y STR_a STR_l STR_a STR_m "\0"
+#define STRING_Mandaic0 STR_M STR_a STR_n STR_d STR_a STR_i STR_c "\0"
+#define STRING_Mc0 STR_M STR_c "\0"
+#define STRING_Me0 STR_M STR_e "\0"
+#define STRING_Meetei_Mayek0 STR_M STR_e STR_e STR_t STR_e STR_i STR_UNDERSCORE STR_M STR_a STR_y STR_e STR_k "\0"
+#define STRING_Meroitic_Cursive0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_C STR_u STR_r STR_s STR_i STR_v STR_e "\0"
+#define STRING_Meroitic_Hieroglyphs0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
+#define STRING_Miao0 STR_M STR_i STR_a STR_o "\0"
+#define STRING_Mn0 STR_M STR_n "\0"
+#define STRING_Mongolian0 STR_M STR_o STR_n STR_g STR_o STR_l STR_i STR_a STR_n "\0"
+#define STRING_Myanmar0 STR_M STR_y STR_a STR_n STR_m STR_a STR_r "\0"
+#define STRING_N0 STR_N "\0"
+#define STRING_Nd0 STR_N STR_d "\0"
+#define STRING_New_Tai_Lue0 STR_N STR_e STR_w STR_UNDERSCORE STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_u STR_e "\0"
+#define STRING_Nko0 STR_N STR_k STR_o "\0"
+#define STRING_Nl0 STR_N STR_l "\0"
+#define STRING_No0 STR_N STR_o "\0"
+#define STRING_Ogham0 STR_O STR_g STR_h STR_a STR_m "\0"
+#define STRING_Ol_Chiki0 STR_O STR_l STR_UNDERSCORE STR_C STR_h STR_i STR_k STR_i "\0"
+#define STRING_Old_Italic0 STR_O STR_l STR_d STR_UNDERSCORE STR_I STR_t STR_a STR_l STR_i STR_c "\0"
+#define STRING_Old_Persian0 STR_O STR_l STR_d STR_UNDERSCORE STR_P STR_e STR_r STR_s STR_i STR_a STR_n "\0"
+#define STRING_Old_South_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_S STR_o STR_u STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0"
+#define STRING_Old_Turkic0 STR_O STR_l STR_d STR_UNDERSCORE STR_T STR_u STR_r STR_k STR_i STR_c "\0"
+#define STRING_Oriya0 STR_O STR_r STR_i STR_y STR_a "\0"
+#define STRING_Osmanya0 STR_O STR_s STR_m STR_a STR_n STR_y STR_a "\0"
+#define STRING_P0 STR_P "\0"
+#define STRING_Pc0 STR_P STR_c "\0"
+#define STRING_Pd0 STR_P STR_d "\0"
+#define STRING_Pe0 STR_P STR_e "\0"
+#define STRING_Pf0 STR_P STR_f "\0"
+#define STRING_Phags_Pa0 STR_P STR_h STR_a STR_g STR_s STR_UNDERSCORE STR_P STR_a "\0"
+#define STRING_Phoenician0 STR_P STR_h STR_o STR_e STR_n STR_i STR_c STR_i STR_a STR_n "\0"
+#define STRING_Pi0 STR_P STR_i "\0"
+#define STRING_Po0 STR_P STR_o "\0"
+#define STRING_Ps0 STR_P STR_s "\0"
+#define STRING_Rejang0 STR_R STR_e STR_j STR_a STR_n STR_g "\0"
+#define STRING_Runic0 STR_R STR_u STR_n STR_i STR_c "\0"
+#define STRING_S0 STR_S "\0"
+#define STRING_Samaritan0 STR_S STR_a STR_m STR_a STR_r STR_i STR_t STR_a STR_n "\0"
+#define STRING_Saurashtra0 STR_S STR_a STR_u STR_r STR_a STR_s STR_h STR_t STR_r STR_a "\0"
+#define STRING_Sc0 STR_S STR_c "\0"
+#define STRING_Sharada0 STR_S STR_h STR_a STR_r STR_a STR_d STR_a "\0"
+#define STRING_Shavian0 STR_S STR_h STR_a STR_v STR_i STR_a STR_n "\0"
+#define STRING_Sinhala0 STR_S STR_i STR_n STR_h STR_a STR_l STR_a "\0"
+#define STRING_Sk0 STR_S STR_k "\0"
+#define STRING_Sm0 STR_S STR_m "\0"
+#define STRING_So0 STR_S STR_o "\0"
+#define STRING_Sora_Sompeng0 STR_S STR_o STR_r STR_a STR_UNDERSCORE STR_S STR_o STR_m STR_p STR_e STR_n STR_g "\0"
+#define STRING_Sundanese0 STR_S STR_u STR_n STR_d STR_a STR_n STR_e STR_s STR_e "\0"
+#define STRING_Syloti_Nagri0 STR_S STR_y STR_l STR_o STR_t STR_i STR_UNDERSCORE STR_N STR_a STR_g STR_r STR_i "\0"
+#define STRING_Syriac0 STR_S STR_y STR_r STR_i STR_a STR_c "\0"
+#define STRING_Tagalog0 STR_T STR_a STR_g STR_a STR_l STR_o STR_g "\0"
+#define STRING_Tagbanwa0 STR_T STR_a STR_g STR_b STR_a STR_n STR_w STR_a "\0"
+#define STRING_Tai_Le0 STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_e "\0"
+#define STRING_Tai_Tham0 STR_T STR_a STR_i STR_UNDERSCORE STR_T STR_h STR_a STR_m "\0"
+#define STRING_Tai_Viet0 STR_T STR_a STR_i STR_UNDERSCORE STR_V STR_i STR_e STR_t "\0"
+#define STRING_Takri0 STR_T STR_a STR_k STR_r STR_i "\0"
+#define STRING_Tamil0 STR_T STR_a STR_m STR_i STR_l "\0"
+#define STRING_Telugu0 STR_T STR_e STR_l STR_u STR_g STR_u "\0"
+#define STRING_Thaana0 STR_T STR_h STR_a STR_a STR_n STR_a "\0"
+#define STRING_Thai0 STR_T STR_h STR_a STR_i "\0"
+#define STRING_Tibetan0 STR_T STR_i STR_b STR_e STR_t STR_a STR_n "\0"
+#define STRING_Tifinagh0 STR_T STR_i STR_f STR_i STR_n STR_a STR_g STR_h "\0"
+#define STRING_Ugaritic0 STR_U STR_g STR_a STR_r STR_i STR_t STR_i STR_c "\0"
+#define STRING_Vai0 STR_V STR_a STR_i "\0"
+#define STRING_Xan0 STR_X STR_a STR_n "\0"
+#define STRING_Xps0 STR_X STR_p STR_s "\0"
+#define STRING_Xsp0 STR_X STR_s STR_p "\0"
+#define STRING_Xuc0 STR_X STR_u STR_c "\0"
+#define STRING_Xwd0 STR_X STR_w STR_d "\0"
+#define STRING_Yi0 STR_Y STR_i "\0"
+#define STRING_Z0 STR_Z "\0"
+#define STRING_Zl0 STR_Z STR_l "\0"
+#define STRING_Zp0 STR_Z STR_p "\0"
+#define STRING_Zs0 STR_Z STR_s "\0"
+
+const char PRIV(utt_names)[] =
+ STRING_Any0
+ STRING_Arabic0
+ STRING_Armenian0
+ STRING_Avestan0
+ STRING_Balinese0
+ STRING_Bamum0
+ STRING_Batak0
+ STRING_Bengali0
+ STRING_Bopomofo0
+ STRING_Brahmi0
+ STRING_Braille0
+ STRING_Buginese0
+ STRING_Buhid0
+ STRING_C0
+ STRING_Canadian_Aboriginal0
+ STRING_Carian0
+ STRING_Cc0
+ STRING_Cf0
+ STRING_Chakma0
+ STRING_Cham0
+ STRING_Cherokee0
+ STRING_Cn0
+ STRING_Co0
+ STRING_Common0
+ STRING_Coptic0
+ STRING_Cs0
+ STRING_Cuneiform0
+ STRING_Cypriot0
+ STRING_Cyrillic0
+ STRING_Deseret0
+ STRING_Devanagari0
+ STRING_Egyptian_Hieroglyphs0
+ STRING_Ethiopic0
+ STRING_Georgian0
+ STRING_Glagolitic0
+ STRING_Gothic0
+ STRING_Greek0
+ STRING_Gujarati0
+ STRING_Gurmukhi0
+ STRING_Han0
+ STRING_Hangul0
+ STRING_Hanunoo0
+ STRING_Hebrew0
+ STRING_Hiragana0
+ STRING_Imperial_Aramaic0
+ STRING_Inherited0
+ STRING_Inscriptional_Pahlavi0
+ STRING_Inscriptional_Parthian0
+ STRING_Javanese0
+ STRING_Kaithi0
+ STRING_Kannada0
+ STRING_Katakana0
+ STRING_Kayah_Li0
+ STRING_Kharoshthi0
+ STRING_Khmer0
+ STRING_L0
+ STRING_L_AMPERSAND0
+ STRING_Lao0
+ STRING_Latin0
+ STRING_Lepcha0
+ STRING_Limbu0
+ STRING_Linear_B0
+ STRING_Lisu0
+ STRING_Ll0
+ STRING_Lm0
+ STRING_Lo0
+ STRING_Lt0
+ STRING_Lu0
+ STRING_Lycian0
+ STRING_Lydian0
+ STRING_M0
+ STRING_Malayalam0
+ STRING_Mandaic0
+ STRING_Mc0
+ STRING_Me0
+ STRING_Meetei_Mayek0
+ STRING_Meroitic_Cursive0
+ STRING_Meroitic_Hieroglyphs0
+ STRING_Miao0
+ STRING_Mn0
+ STRING_Mongolian0
+ STRING_Myanmar0
+ STRING_N0
+ STRING_Nd0
+ STRING_New_Tai_Lue0
+ STRING_Nko0
+ STRING_Nl0
+ STRING_No0
+ STRING_Ogham0
+ STRING_Ol_Chiki0
+ STRING_Old_Italic0
+ STRING_Old_Persian0
+ STRING_Old_South_Arabian0
+ STRING_Old_Turkic0
+ STRING_Oriya0
+ STRING_Osmanya0
+ STRING_P0
+ STRING_Pc0
+ STRING_Pd0
+ STRING_Pe0
+ STRING_Pf0
+ STRING_Phags_Pa0
+ STRING_Phoenician0
+ STRING_Pi0
+ STRING_Po0
+ STRING_Ps0
+ STRING_Rejang0
+ STRING_Runic0
+ STRING_S0
+ STRING_Samaritan0
+ STRING_Saurashtra0
+ STRING_Sc0
+ STRING_Sharada0
+ STRING_Shavian0
+ STRING_Sinhala0
+ STRING_Sk0
+ STRING_Sm0
+ STRING_So0
+ STRING_Sora_Sompeng0
+ STRING_Sundanese0
+ STRING_Syloti_Nagri0
+ STRING_Syriac0
+ STRING_Tagalog0
+ STRING_Tagbanwa0
+ STRING_Tai_Le0
+ STRING_Tai_Tham0
+ STRING_Tai_Viet0
+ STRING_Takri0
+ STRING_Tamil0
+ STRING_Telugu0
+ STRING_Thaana0
+ STRING_Thai0
+ STRING_Tibetan0
+ STRING_Tifinagh0
+ STRING_Ugaritic0
+ STRING_Vai0
+ STRING_Xan0
+ STRING_Xps0
+ STRING_Xsp0
+ STRING_Xuc0
+ STRING_Xwd0
+ STRING_Yi0
+ STRING_Z0
+ STRING_Zl0
+ STRING_Zp0
+ STRING_Zs0;
+
+const ucp_type_table PRIV(utt)[] = {
+ { 0, PT_ANY, 0 },
+ { 4, PT_SC, ucp_Arabic },
+ { 11, PT_SC, ucp_Armenian },
+ { 20, PT_SC, ucp_Avestan },
+ { 28, PT_SC, ucp_Balinese },
+ { 37, PT_SC, ucp_Bamum },
+ { 43, PT_SC, ucp_Batak },
+ { 49, PT_SC, ucp_Bengali },
+ { 57, PT_SC, ucp_Bopomofo },
+ { 66, PT_SC, ucp_Brahmi },
+ { 73, PT_SC, ucp_Braille },
+ { 81, PT_SC, ucp_Buginese },
+ { 90, PT_SC, ucp_Buhid },
+ { 96, PT_GC, ucp_C },
+ { 98, PT_SC, ucp_Canadian_Aboriginal },
+ { 118, PT_SC, ucp_Carian },
+ { 125, PT_PC, ucp_Cc },
+ { 128, PT_PC, ucp_Cf },
+ { 131, PT_SC, ucp_Chakma },
+ { 138, PT_SC, ucp_Cham },
+ { 143, PT_SC, ucp_Cherokee },
+ { 152, PT_PC, ucp_Cn },
+ { 155, PT_PC, ucp_Co },
+ { 158, PT_SC, ucp_Common },
+ { 165, PT_SC, ucp_Coptic },
+ { 172, PT_PC, ucp_Cs },
+ { 175, PT_SC, ucp_Cuneiform },
+ { 185, PT_SC, ucp_Cypriot },
+ { 193, PT_SC, ucp_Cyrillic },
+ { 202, PT_SC, ucp_Deseret },
+ { 210, PT_SC, ucp_Devanagari },
+ { 221, PT_SC, ucp_Egyptian_Hieroglyphs },
+ { 242, PT_SC, ucp_Ethiopic },
+ { 251, PT_SC, ucp_Georgian },
+ { 260, PT_SC, ucp_Glagolitic },
+ { 271, PT_SC, ucp_Gothic },
+ { 278, PT_SC, ucp_Greek },
+ { 284, PT_SC, ucp_Gujarati },
+ { 293, PT_SC, ucp_Gurmukhi },
+ { 302, PT_SC, ucp_Han },
+ { 306, PT_SC, ucp_Hangul },
+ { 313, PT_SC, ucp_Hanunoo },
+ { 321, PT_SC, ucp_Hebrew },
+ { 328, PT_SC, ucp_Hiragana },
+ { 337, PT_SC, ucp_Imperial_Aramaic },
+ { 354, PT_SC, ucp_Inherited },
+ { 364, PT_SC, ucp_Inscriptional_Pahlavi },
+ { 386, PT_SC, ucp_Inscriptional_Parthian },
+ { 409, PT_SC, ucp_Javanese },
+ { 418, PT_SC, ucp_Kaithi },
+ { 425, PT_SC, ucp_Kannada },
+ { 433, PT_SC, ucp_Katakana },
+ { 442, PT_SC, ucp_Kayah_Li },
+ { 451, PT_SC, ucp_Kharoshthi },
+ { 462, PT_SC, ucp_Khmer },
+ { 468, PT_GC, ucp_L },
+ { 470, PT_LAMP, 0 },
+ { 473, PT_SC, ucp_Lao },
+ { 477, PT_SC, ucp_Latin },
+ { 483, PT_SC, ucp_Lepcha },
+ { 490, PT_SC, ucp_Limbu },
+ { 496, PT_SC, ucp_Linear_B },
+ { 505, PT_SC, ucp_Lisu },
+ { 510, PT_PC, ucp_Ll },
+ { 513, PT_PC, ucp_Lm },
+ { 516, PT_PC, ucp_Lo },
+ { 519, PT_PC, ucp_Lt },
+ { 522, PT_PC, ucp_Lu },
+ { 525, PT_SC, ucp_Lycian },
+ { 532, PT_SC, ucp_Lydian },
+ { 539, PT_GC, ucp_M },
+ { 541, PT_SC, ucp_Malayalam },
+ { 551, PT_SC, ucp_Mandaic },
+ { 559, PT_PC, ucp_Mc },
+ { 562, PT_PC, ucp_Me },
+ { 565, PT_SC, ucp_Meetei_Mayek },
+ { 578, PT_SC, ucp_Meroitic_Cursive },
+ { 595, PT_SC, ucp_Meroitic_Hieroglyphs },
+ { 616, PT_SC, ucp_Miao },
+ { 621, PT_PC, ucp_Mn },
+ { 624, PT_SC, ucp_Mongolian },
+ { 634, PT_SC, ucp_Myanmar },
+ { 642, PT_GC, ucp_N },
+ { 644, PT_PC, ucp_Nd },
+ { 647, PT_SC, ucp_New_Tai_Lue },
+ { 659, PT_SC, ucp_Nko },
+ { 663, PT_PC, ucp_Nl },
+ { 666, PT_PC, ucp_No },
+ { 669, PT_SC, ucp_Ogham },
+ { 675, PT_SC, ucp_Ol_Chiki },
+ { 684, PT_SC, ucp_Old_Italic },
+ { 695, PT_SC, ucp_Old_Persian },
+ { 707, PT_SC, ucp_Old_South_Arabian },
+ { 725, PT_SC, ucp_Old_Turkic },
+ { 736, PT_SC, ucp_Oriya },
+ { 742, PT_SC, ucp_Osmanya },
+ { 750, PT_GC, ucp_P },
+ { 752, PT_PC, ucp_Pc },
+ { 755, PT_PC, ucp_Pd },
+ { 758, PT_PC, ucp_Pe },
+ { 761, PT_PC, ucp_Pf },
+ { 764, PT_SC, ucp_Phags_Pa },
+ { 773, PT_SC, ucp_Phoenician },
+ { 784, PT_PC, ucp_Pi },
+ { 787, PT_PC, ucp_Po },
+ { 790, PT_PC, ucp_Ps },
+ { 793, PT_SC, ucp_Rejang },
+ { 800, PT_SC, ucp_Runic },
+ { 806, PT_GC, ucp_S },
+ { 808, PT_SC, ucp_Samaritan },
+ { 818, PT_SC, ucp_Saurashtra },
+ { 829, PT_PC, ucp_Sc },
+ { 832, PT_SC, ucp_Sharada },
+ { 840, PT_SC, ucp_Shavian },
+ { 848, PT_SC, ucp_Sinhala },
+ { 856, PT_PC, ucp_Sk },
+ { 859, PT_PC, ucp_Sm },
+ { 862, PT_PC, ucp_So },
+ { 865, PT_SC, ucp_Sora_Sompeng },
+ { 878, PT_SC, ucp_Sundanese },
+ { 888, PT_SC, ucp_Syloti_Nagri },
+ { 901, PT_SC, ucp_Syriac },
+ { 908, PT_SC, ucp_Tagalog },
+ { 916, PT_SC, ucp_Tagbanwa },
+ { 925, PT_SC, ucp_Tai_Le },
+ { 932, PT_SC, ucp_Tai_Tham },
+ { 941, PT_SC, ucp_Tai_Viet },
+ { 950, PT_SC, ucp_Takri },
+ { 956, PT_SC, ucp_Tamil },
+ { 962, PT_SC, ucp_Telugu },
+ { 969, PT_SC, ucp_Thaana },
+ { 976, PT_SC, ucp_Thai },
+ { 981, PT_SC, ucp_Tibetan },
+ { 989, PT_SC, ucp_Tifinagh },
+ { 998, PT_SC, ucp_Ugaritic },
+ { 1007, PT_SC, ucp_Vai },
+ { 1011, PT_ALNUM, 0 },
+ { 1015, PT_PXSPACE, 0 },
+ { 1019, PT_SPACE, 0 },
+ { 1023, PT_UCNC, 0 },
+ { 1027, PT_WORD, 0 },
+ { 1031, PT_SC, ucp_Yi },
+ { 1034, PT_GC, ucp_Z },
+ { 1036, PT_PC, ucp_Zl },
+ { 1039, PT_PC, ucp_Zp },
+ { 1042, PT_PC, ucp_Zs }
+};
+
+const int PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);
+
+#endif /* SUPPORT_UTF */
+
+/* End of pcre_tables.c */
diff --git a/plugins/Pcre16/src/pcre_ucd.c b/plugins/Pcre16/src/pcre_ucd.c
new file mode 100644
index 0000000000..46ea70c44c
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_ucd.c
@@ -0,0 +1,3297 @@
+/* This module is generated by the maint/MultiStage2.py script.
+Do not modify it by hand. Instead modify the script and run it
+to regenerate this code.
+
+As well as being part of the PCRE library, this module is #included
+by the pcretest program, which redefines the PRIV macro to change
+table names from _pcre_xxx to xxxx, thereby avoiding name clashes
+with the library. At present, just one of these tables is actually
+needed. */
+
+#ifndef PCRE_INCLUDED
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+#endif /* PCRE_INCLUDED */
+
+/* Unicode character database. */
+/* This file was autogenerated by the MultiStage2.py script. */
+/* Total size: 65688 bytes, block size: 128. */
+
+/* The tables herein are needed only when UCP support is built
+into PCRE. This module should not be referenced otherwise, so
+it should not matter whether it is compiled or not. However
+a comment was received about space saving - maybe the guy linked
+all the modules rather than using a library - so we include a
+condition to cut out the tables when not needed. But don't leave
+a totally empty module because some compilers barf at that.
+Instead, just supply small dummy tables. */
+
+#ifndef SUPPORT_UCP
+const ucd_record PRIV(ucd_records)[] = {{0,0,0,0,0 }};
+const pcre_uint8 PRIV(ucd_stage1)[] = {0};
+const pcre_uint16 PRIV(ucd_stage2)[] = {0};
+const pcre_uint32 PRIV(ucd_caseless_sets)[] = {0};
+#else
+
+/* When recompiling tables with a new Unicode version, please check the
+types in this structure definition from pcre_internal.h (the actual
+field names will be different):
+
+typedef struct {
+pcre_uint8 property_0;
+pcre_uint8 property_1;
+pcre_uint8 property_2;
+pcre_uint8 property_3;
+pcre_int32 property_4;
+} ucd_record;
+*/
+
+
+const pcre_uint32 PRIV(ucd_caseless_sets)[] = {
+ NOTACHAR,
+ 0x0053, 0x0073, 0x017f, NOTACHAR,
+ 0x01c4, 0x01c5, 0x01c6, NOTACHAR,
+ 0x01c7, 0x01c8, 0x01c9, NOTACHAR,
+ 0x01ca, 0x01cb, 0x01cc, NOTACHAR,
+ 0x01f1, 0x01f2, 0x01f3, NOTACHAR,
+ 0x0345, 0x0399, 0x03b9, 0x1fbe, NOTACHAR,
+ 0x00b5, 0x039c, 0x03bc, NOTACHAR,
+ 0x03a3, 0x03c2, 0x03c3, NOTACHAR,
+ 0x0392, 0x03b2, 0x03d0, NOTACHAR,
+ 0x0398, 0x03b8, 0x03d1, 0x03f4, NOTACHAR,
+ 0x03a6, 0x03c6, 0x03d5, NOTACHAR,
+ 0x03a0, 0x03c0, 0x03d6, NOTACHAR,
+ 0x039a, 0x03ba, 0x03f0, NOTACHAR,
+ 0x03a1, 0x03c1, 0x03f1, NOTACHAR,
+ 0x0395, 0x03b5, 0x03f5, NOTACHAR,
+ 0x1e60, 0x1e61, 0x1e9b, NOTACHAR,
+ 0x03a9, 0x03c9, 0x2126, NOTACHAR,
+ 0x004b, 0x006b, 0x212a, NOTACHAR,
+ 0x00c5, 0x00e5, 0x212b, NOTACHAR,
+};
+
+/* When #included in pcretest, we don't need this large table. */
+
+#ifndef PCRE_INCLUDED
+
+const ucd_record PRIV(ucd_records)[] = { /* 5016 bytes, record size 8 */
+ { 9, 0, 2, 0, 0, }, /* 0 */
+ { 9, 0, 1, 0, 0, }, /* 1 */
+ { 9, 0, 0, 0, 0, }, /* 2 */
+ { 9, 29, 12, 0, 0, }, /* 3 */
+ { 9, 21, 12, 0, 0, }, /* 4 */
+ { 9, 23, 12, 0, 0, }, /* 5 */
+ { 9, 22, 12, 0, 0, }, /* 6 */
+ { 9, 18, 12, 0, 0, }, /* 7 */
+ { 9, 25, 12, 0, 0, }, /* 8 */
+ { 9, 17, 12, 0, 0, }, /* 9 */
+ { 9, 13, 12, 0, 0, }, /* 10 */
+ { 33, 9, 12, 0, 32, }, /* 11 */
+ { 33, 9, 12, 71, 32, }, /* 12 */
+ { 33, 9, 12, 1, 32, }, /* 13 */
+ { 9, 24, 12, 0, 0, }, /* 14 */
+ { 9, 16, 12, 0, 0, }, /* 15 */
+ { 33, 5, 12, 0, -32, }, /* 16 */
+ { 33, 5, 12, 71, -32, }, /* 17 */
+ { 33, 5, 12, 1, -32, }, /* 18 */
+ { 9, 26, 12, 0, 0, }, /* 19 */
+ { 33, 7, 12, 0, 0, }, /* 20 */
+ { 9, 20, 12, 0, 0, }, /* 21 */
+ { 9, 1, 2, 0, 0, }, /* 22 */
+ { 9, 15, 12, 0, 0, }, /* 23 */
+ { 9, 5, 12, 26, 775, }, /* 24 */
+ { 9, 19, 12, 0, 0, }, /* 25 */
+ { 33, 9, 12, 75, 32, }, /* 26 */
+ { 33, 5, 12, 0, 7615, }, /* 27 */
+ { 33, 5, 12, 75, -32, }, /* 28 */
+ { 33, 5, 12, 0, 121, }, /* 29 */
+ { 33, 9, 12, 0, 1, }, /* 30 */
+ { 33, 5, 12, 0, -1, }, /* 31 */
+ { 33, 9, 12, 0, 0, }, /* 32 */
+ { 33, 5, 12, 0, 0, }, /* 33 */
+ { 33, 9, 12, 0, -121, }, /* 34 */
+ { 33, 5, 12, 1, -268, }, /* 35 */
+ { 33, 5, 12, 0, 195, }, /* 36 */
+ { 33, 9, 12, 0, 210, }, /* 37 */
+ { 33, 9, 12, 0, 206, }, /* 38 */
+ { 33, 9, 12, 0, 205, }, /* 39 */
+ { 33, 9, 12, 0, 79, }, /* 40 */
+ { 33, 9, 12, 0, 202, }, /* 41 */
+ { 33, 9, 12, 0, 203, }, /* 42 */
+ { 33, 9, 12, 0, 207, }, /* 43 */
+ { 33, 5, 12, 0, 97, }, /* 44 */
+ { 33, 9, 12, 0, 211, }, /* 45 */
+ { 33, 9, 12, 0, 209, }, /* 46 */
+ { 33, 5, 12, 0, 163, }, /* 47 */
+ { 33, 9, 12, 0, 213, }, /* 48 */
+ { 33, 5, 12, 0, 130, }, /* 49 */
+ { 33, 9, 12, 0, 214, }, /* 50 */
+ { 33, 9, 12, 0, 218, }, /* 51 */
+ { 33, 9, 12, 0, 217, }, /* 52 */
+ { 33, 9, 12, 0, 219, }, /* 53 */
+ { 33, 5, 12, 0, 56, }, /* 54 */
+ { 33, 9, 12, 5, 2, }, /* 55 */
+ { 33, 8, 12, 5, 1, }, /* 56 */
+ { 33, 5, 12, 5, -2, }, /* 57 */
+ { 33, 9, 12, 9, 2, }, /* 58 */
+ { 33, 8, 12, 9, 1, }, /* 59 */
+ { 33, 5, 12, 9, -2, }, /* 60 */
+ { 33, 9, 12, 13, 2, }, /* 61 */
+ { 33, 8, 12, 13, 1, }, /* 62 */
+ { 33, 5, 12, 13, -2, }, /* 63 */
+ { 33, 5, 12, 0, -79, }, /* 64 */
+ { 33, 9, 12, 17, 2, }, /* 65 */
+ { 33, 8, 12, 17, 1, }, /* 66 */
+ { 33, 5, 12, 17, -2, }, /* 67 */
+ { 33, 9, 12, 0, -97, }, /* 68 */
+ { 33, 9, 12, 0, -56, }, /* 69 */
+ { 33, 9, 12, 0, -130, }, /* 70 */
+ { 33, 9, 12, 0, 10795, }, /* 71 */
+ { 33, 9, 12, 0, -163, }, /* 72 */
+ { 33, 9, 12, 0, 10792, }, /* 73 */
+ { 33, 5, 12, 0, 10815, }, /* 74 */
+ { 33, 9, 12, 0, -195, }, /* 75 */
+ { 33, 9, 12, 0, 69, }, /* 76 */
+ { 33, 9, 12, 0, 71, }, /* 77 */
+ { 33, 5, 12, 0, 10783, }, /* 78 */
+ { 33, 5, 12, 0, 10780, }, /* 79 */
+ { 33, 5, 12, 0, 10782, }, /* 80 */
+ { 33, 5, 12, 0, -210, }, /* 81 */
+ { 33, 5, 12, 0, -206, }, /* 82 */
+ { 33, 5, 12, 0, -205, }, /* 83 */
+ { 33, 5, 12, 0, -202, }, /* 84 */
+ { 33, 5, 12, 0, -203, }, /* 85 */
+ { 33, 5, 12, 0, -207, }, /* 86 */
+ { 33, 5, 12, 0, 42280, }, /* 87 */
+ { 33, 5, 12, 0, 42308, }, /* 88 */
+ { 33, 5, 12, 0, -209, }, /* 89 */
+ { 33, 5, 12, 0, -211, }, /* 90 */
+ { 33, 5, 12, 0, 10743, }, /* 91 */
+ { 33, 5, 12, 0, 10749, }, /* 92 */
+ { 33, 5, 12, 0, -213, }, /* 93 */
+ { 33, 5, 12, 0, -214, }, /* 94 */
+ { 33, 5, 12, 0, 10727, }, /* 95 */
+ { 33, 5, 12, 0, -218, }, /* 96 */
+ { 33, 5, 12, 0, -69, }, /* 97 */
+ { 33, 5, 12, 0, -217, }, /* 98 */
+ { 33, 5, 12, 0, -71, }, /* 99 */
+ { 33, 5, 12, 0, -219, }, /* 100 */
+ { 33, 6, 12, 0, 0, }, /* 101 */
+ { 9, 6, 12, 0, 0, }, /* 102 */
+ { 3, 24, 12, 0, 0, }, /* 103 */
+ { 27, 12, 3, 0, 0, }, /* 104 */
+ { 27, 12, 3, 21, 116, }, /* 105 */
+ { 19, 9, 12, 0, 1, }, /* 106 */
+ { 19, 5, 12, 0, -1, }, /* 107 */
+ { 19, 24, 12, 0, 0, }, /* 108 */
+ { 9, 2, 12, 0, 0, }, /* 109 */
+ { 19, 6, 12, 0, 0, }, /* 110 */
+ { 19, 5, 12, 0, 130, }, /* 111 */
+ { 19, 9, 12, 0, 38, }, /* 112 */
+ { 19, 9, 12, 0, 37, }, /* 113 */
+ { 19, 9, 12, 0, 64, }, /* 114 */
+ { 19, 9, 12, 0, 63, }, /* 115 */
+ { 19, 5, 12, 0, 0, }, /* 116 */
+ { 19, 9, 12, 0, 32, }, /* 117 */
+ { 19, 9, 12, 34, 32, }, /* 118 */
+ { 19, 9, 12, 59, 32, }, /* 119 */
+ { 19, 9, 12, 38, 32, }, /* 120 */
+ { 19, 9, 12, 21, 32, }, /* 121 */
+ { 19, 9, 12, 51, 32, }, /* 122 */
+ { 19, 9, 12, 26, 32, }, /* 123 */
+ { 19, 9, 12, 47, 32, }, /* 124 */
+ { 19, 9, 12, 55, 32, }, /* 125 */
+ { 19, 9, 12, 30, 32, }, /* 126 */
+ { 19, 9, 12, 43, 32, }, /* 127 */
+ { 19, 9, 12, 67, 32, }, /* 128 */
+ { 19, 5, 12, 0, -38, }, /* 129 */
+ { 19, 5, 12, 0, -37, }, /* 130 */
+ { 19, 5, 12, 0, -32, }, /* 131 */
+ { 19, 5, 12, 34, -32, }, /* 132 */
+ { 19, 5, 12, 59, -32, }, /* 133 */
+ { 19, 5, 12, 38, -32, }, /* 134 */
+ { 19, 5, 12, 21, -116, }, /* 135 */
+ { 19, 5, 12, 51, -32, }, /* 136 */
+ { 19, 5, 12, 26, -775, }, /* 137 */
+ { 19, 5, 12, 47, -32, }, /* 138 */
+ { 19, 5, 12, 55, -32, }, /* 139 */
+ { 19, 5, 12, 30, 1, }, /* 140 */
+ { 19, 5, 12, 30, -32, }, /* 141 */
+ { 19, 5, 12, 43, -32, }, /* 142 */
+ { 19, 5, 12, 67, -32, }, /* 143 */
+ { 19, 5, 12, 0, -64, }, /* 144 */
+ { 19, 5, 12, 0, -63, }, /* 145 */
+ { 19, 9, 12, 0, 8, }, /* 146 */
+ { 19, 5, 12, 34, -30, }, /* 147 */
+ { 19, 5, 12, 38, -25, }, /* 148 */
+ { 19, 9, 12, 0, 0, }, /* 149 */
+ { 19, 5, 12, 43, -15, }, /* 150 */
+ { 19, 5, 12, 47, -22, }, /* 151 */
+ { 19, 5, 12, 0, -8, }, /* 152 */
+ { 10, 9, 12, 0, 1, }, /* 153 */
+ { 10, 5, 12, 0, -1, }, /* 154 */
+ { 19, 5, 12, 51, -54, }, /* 155 */
+ { 19, 5, 12, 55, -48, }, /* 156 */
+ { 19, 5, 12, 0, 7, }, /* 157 */
+ { 19, 9, 12, 38, -60, }, /* 158 */
+ { 19, 5, 12, 59, -64, }, /* 159 */
+ { 19, 25, 12, 0, 0, }, /* 160 */
+ { 19, 9, 12, 0, -7, }, /* 161 */
+ { 19, 9, 12, 0, -130, }, /* 162 */
+ { 12, 9, 12, 0, 80, }, /* 163 */
+ { 12, 9, 12, 0, 32, }, /* 164 */
+ { 12, 5, 12, 0, -32, }, /* 165 */
+ { 12, 5, 12, 0, -80, }, /* 166 */
+ { 12, 9, 12, 0, 1, }, /* 167 */
+ { 12, 5, 12, 0, -1, }, /* 168 */
+ { 12, 26, 12, 0, 0, }, /* 169 */
+ { 12, 12, 3, 0, 0, }, /* 170 */
+ { 12, 11, 3, 0, 0, }, /* 171 */
+ { 12, 9, 12, 0, 15, }, /* 172 */
+ { 12, 5, 12, 0, -15, }, /* 173 */
+ { 1, 9, 12, 0, 48, }, /* 174 */
+ { 1, 6, 12, 0, 0, }, /* 175 */
+ { 1, 21, 12, 0, 0, }, /* 176 */
+ { 1, 5, 12, 0, -48, }, /* 177 */
+ { 1, 5, 12, 0, 0, }, /* 178 */
+ { 1, 17, 12, 0, 0, }, /* 179 */
+ { 1, 23, 12, 0, 0, }, /* 180 */
+ { 25, 12, 3, 0, 0, }, /* 181 */
+ { 25, 17, 12, 0, 0, }, /* 182 */
+ { 25, 21, 12, 0, 0, }, /* 183 */
+ { 25, 7, 12, 0, 0, }, /* 184 */
+ { 0, 1, 2, 0, 0, }, /* 185 */
+ { 0, 25, 12, 0, 0, }, /* 186 */
+ { 0, 21, 12, 0, 0, }, /* 187 */
+ { 0, 23, 12, 0, 0, }, /* 188 */
+ { 0, 26, 12, 0, 0, }, /* 189 */
+ { 0, 12, 3, 0, 0, }, /* 190 */
+ { 0, 7, 12, 0, 0, }, /* 191 */
+ { 0, 6, 12, 0, 0, }, /* 192 */
+ { 0, 13, 12, 0, 0, }, /* 193 */
+ { 49, 21, 12, 0, 0, }, /* 194 */
+ { 49, 1, 2, 0, 0, }, /* 195 */
+ { 49, 7, 12, 0, 0, }, /* 196 */
+ { 49, 12, 3, 0, 0, }, /* 197 */
+ { 55, 7, 12, 0, 0, }, /* 198 */
+ { 55, 12, 3, 0, 0, }, /* 199 */
+ { 63, 13, 12, 0, 0, }, /* 200 */
+ { 63, 7, 12, 0, 0, }, /* 201 */
+ { 63, 12, 3, 0, 0, }, /* 202 */
+ { 63, 6, 12, 0, 0, }, /* 203 */
+ { 63, 26, 12, 0, 0, }, /* 204 */
+ { 63, 21, 12, 0, 0, }, /* 205 */
+ { 89, 7, 12, 0, 0, }, /* 206 */
+ { 89, 12, 3, 0, 0, }, /* 207 */
+ { 89, 6, 12, 0, 0, }, /* 208 */
+ { 89, 21, 12, 0, 0, }, /* 209 */
+ { 94, 7, 12, 0, 0, }, /* 210 */
+ { 94, 12, 3, 0, 0, }, /* 211 */
+ { 94, 21, 12, 0, 0, }, /* 212 */
+ { 14, 12, 3, 0, 0, }, /* 213 */
+ { 14, 10, 5, 0, 0, }, /* 214 */
+ { 14, 7, 12, 0, 0, }, /* 215 */
+ { 14, 13, 12, 0, 0, }, /* 216 */
+ { 14, 21, 12, 0, 0, }, /* 217 */
+ { 14, 6, 12, 0, 0, }, /* 218 */
+ { 2, 12, 3, 0, 0, }, /* 219 */
+ { 2, 10, 5, 0, 0, }, /* 220 */
+ { 2, 7, 12, 0, 0, }, /* 221 */
+ { 2, 10, 3, 0, 0, }, /* 222 */
+ { 2, 13, 12, 0, 0, }, /* 223 */
+ { 2, 23, 12, 0, 0, }, /* 224 */
+ { 2, 15, 12, 0, 0, }, /* 225 */
+ { 2, 26, 12, 0, 0, }, /* 226 */
+ { 21, 12, 3, 0, 0, }, /* 227 */
+ { 21, 10, 5, 0, 0, }, /* 228 */
+ { 21, 7, 12, 0, 0, }, /* 229 */
+ { 21, 13, 12, 0, 0, }, /* 230 */
+ { 20, 12, 3, 0, 0, }, /* 231 */
+ { 20, 10, 5, 0, 0, }, /* 232 */
+ { 20, 7, 12, 0, 0, }, /* 233 */
+ { 20, 13, 12, 0, 0, }, /* 234 */
+ { 20, 21, 12, 0, 0, }, /* 235 */
+ { 20, 23, 12, 0, 0, }, /* 236 */
+ { 43, 12, 3, 0, 0, }, /* 237 */
+ { 43, 10, 5, 0, 0, }, /* 238 */
+ { 43, 7, 12, 0, 0, }, /* 239 */
+ { 43, 10, 3, 0, 0, }, /* 240 */
+ { 43, 13, 12, 0, 0, }, /* 241 */
+ { 43, 26, 12, 0, 0, }, /* 242 */
+ { 43, 15, 12, 0, 0, }, /* 243 */
+ { 53, 12, 3, 0, 0, }, /* 244 */
+ { 53, 7, 12, 0, 0, }, /* 245 */
+ { 53, 10, 3, 0, 0, }, /* 246 */
+ { 53, 10, 5, 0, 0, }, /* 247 */
+ { 53, 13, 12, 0, 0, }, /* 248 */
+ { 53, 15, 12, 0, 0, }, /* 249 */
+ { 53, 26, 12, 0, 0, }, /* 250 */
+ { 53, 23, 12, 0, 0, }, /* 251 */
+ { 54, 10, 5, 0, 0, }, /* 252 */
+ { 54, 7, 12, 0, 0, }, /* 253 */
+ { 54, 12, 3, 0, 0, }, /* 254 */
+ { 54, 13, 12, 0, 0, }, /* 255 */
+ { 54, 15, 12, 0, 0, }, /* 256 */
+ { 54, 26, 12, 0, 0, }, /* 257 */
+ { 28, 10, 5, 0, 0, }, /* 258 */
+ { 28, 7, 12, 0, 0, }, /* 259 */
+ { 28, 12, 3, 0, 0, }, /* 260 */
+ { 28, 10, 3, 0, 0, }, /* 261 */
+ { 28, 13, 12, 0, 0, }, /* 262 */
+ { 36, 10, 5, 0, 0, }, /* 263 */
+ { 36, 7, 12, 0, 0, }, /* 264 */
+ { 36, 10, 3, 0, 0, }, /* 265 */
+ { 36, 12, 3, 0, 0, }, /* 266 */
+ { 36, 13, 12, 0, 0, }, /* 267 */
+ { 36, 15, 12, 0, 0, }, /* 268 */
+ { 36, 26, 12, 0, 0, }, /* 269 */
+ { 47, 10, 5, 0, 0, }, /* 270 */
+ { 47, 7, 12, 0, 0, }, /* 271 */
+ { 47, 12, 3, 0, 0, }, /* 272 */
+ { 47, 10, 3, 0, 0, }, /* 273 */
+ { 47, 21, 12, 0, 0, }, /* 274 */
+ { 56, 7, 12, 0, 0, }, /* 275 */
+ { 56, 12, 3, 0, 0, }, /* 276 */
+ { 56, 7, 5, 0, 0, }, /* 277 */
+ { 56, 6, 12, 0, 0, }, /* 278 */
+ { 56, 21, 12, 0, 0, }, /* 279 */
+ { 56, 13, 12, 0, 0, }, /* 280 */
+ { 32, 7, 12, 0, 0, }, /* 281 */
+ { 32, 12, 3, 0, 0, }, /* 282 */
+ { 32, 7, 5, 0, 0, }, /* 283 */
+ { 32, 6, 12, 0, 0, }, /* 284 */
+ { 32, 13, 12, 0, 0, }, /* 285 */
+ { 57, 7, 12, 0, 0, }, /* 286 */
+ { 57, 26, 12, 0, 0, }, /* 287 */
+ { 57, 21, 12, 0, 0, }, /* 288 */
+ { 57, 12, 3, 0, 0, }, /* 289 */
+ { 57, 13, 12, 0, 0, }, /* 290 */
+ { 57, 15, 12, 0, 0, }, /* 291 */
+ { 57, 22, 12, 0, 0, }, /* 292 */
+ { 57, 18, 12, 0, 0, }, /* 293 */
+ { 57, 10, 5, 0, 0, }, /* 294 */
+ { 38, 7, 12, 0, 0, }, /* 295 */
+ { 38, 10, 12, 0, 0, }, /* 296 */
+ { 38, 12, 3, 0, 0, }, /* 297 */
+ { 38, 10, 5, 0, 0, }, /* 298 */
+ { 38, 13, 12, 0, 0, }, /* 299 */
+ { 38, 21, 12, 0, 0, }, /* 300 */
+ { 38, 26, 12, 0, 0, }, /* 301 */
+ { 16, 9, 12, 0, 7264, }, /* 302 */
+ { 16, 7, 12, 0, 0, }, /* 303 */
+ { 16, 6, 12, 0, 0, }, /* 304 */
+ { 23, 7, 6, 0, 0, }, /* 305 */
+ { 23, 7, 7, 0, 0, }, /* 306 */
+ { 23, 7, 8, 0, 0, }, /* 307 */
+ { 15, 7, 12, 0, 0, }, /* 308 */
+ { 15, 12, 3, 0, 0, }, /* 309 */
+ { 15, 21, 12, 0, 0, }, /* 310 */
+ { 15, 15, 12, 0, 0, }, /* 311 */
+ { 15, 26, 12, 0, 0, }, /* 312 */
+ { 8, 7, 12, 0, 0, }, /* 313 */
+ { 7, 17, 12, 0, 0, }, /* 314 */
+ { 7, 7, 12, 0, 0, }, /* 315 */
+ { 7, 21, 12, 0, 0, }, /* 316 */
+ { 40, 29, 12, 0, 0, }, /* 317 */
+ { 40, 7, 12, 0, 0, }, /* 318 */
+ { 40, 22, 12, 0, 0, }, /* 319 */
+ { 40, 18, 12, 0, 0, }, /* 320 */
+ { 45, 7, 12, 0, 0, }, /* 321 */
+ { 45, 14, 12, 0, 0, }, /* 322 */
+ { 50, 7, 12, 0, 0, }, /* 323 */
+ { 50, 12, 3, 0, 0, }, /* 324 */
+ { 24, 7, 12, 0, 0, }, /* 325 */
+ { 24, 12, 3, 0, 0, }, /* 326 */
+ { 6, 7, 12, 0, 0, }, /* 327 */
+ { 6, 12, 3, 0, 0, }, /* 328 */
+ { 51, 7, 12, 0, 0, }, /* 329 */
+ { 51, 12, 3, 0, 0, }, /* 330 */
+ { 31, 7, 12, 0, 0, }, /* 331 */
+ { 31, 12, 3, 0, 0, }, /* 332 */
+ { 31, 10, 5, 0, 0, }, /* 333 */
+ { 31, 21, 12, 0, 0, }, /* 334 */
+ { 31, 6, 12, 0, 0, }, /* 335 */
+ { 31, 23, 12, 0, 0, }, /* 336 */
+ { 31, 13, 12, 0, 0, }, /* 337 */
+ { 31, 15, 12, 0, 0, }, /* 338 */
+ { 37, 21, 12, 0, 0, }, /* 339 */
+ { 37, 17, 12, 0, 0, }, /* 340 */
+ { 37, 12, 3, 0, 0, }, /* 341 */
+ { 37, 1, 2, 0, 0, }, /* 342 */
+ { 37, 13, 12, 0, 0, }, /* 343 */
+ { 37, 7, 12, 0, 0, }, /* 344 */
+ { 37, 6, 12, 0, 0, }, /* 345 */
+ { 34, 7, 12, 0, 0, }, /* 346 */
+ { 34, 12, 3, 0, 0, }, /* 347 */
+ { 34, 10, 5, 0, 0, }, /* 348 */
+ { 34, 26, 12, 0, 0, }, /* 349 */
+ { 34, 21, 12, 0, 0, }, /* 350 */
+ { 34, 13, 12, 0, 0, }, /* 351 */
+ { 52, 7, 12, 0, 0, }, /* 352 */
+ { 39, 7, 12, 0, 0, }, /* 353 */
+ { 39, 10, 12, 0, 0, }, /* 354 */
+ { 39, 10, 5, 0, 0, }, /* 355 */
+ { 39, 13, 12, 0, 0, }, /* 356 */
+ { 39, 15, 12, 0, 0, }, /* 357 */
+ { 39, 26, 12, 0, 0, }, /* 358 */
+ { 31, 26, 12, 0, 0, }, /* 359 */
+ { 5, 7, 12, 0, 0, }, /* 360 */
+ { 5, 12, 3, 0, 0, }, /* 361 */
+ { 5, 10, 5, 0, 0, }, /* 362 */
+ { 5, 21, 12, 0, 0, }, /* 363 */
+ { 90, 7, 12, 0, 0, }, /* 364 */
+ { 90, 10, 5, 0, 0, }, /* 365 */
+ { 90, 12, 3, 0, 0, }, /* 366 */
+ { 90, 10, 12, 0, 0, }, /* 367 */
+ { 90, 13, 12, 0, 0, }, /* 368 */
+ { 90, 21, 12, 0, 0, }, /* 369 */
+ { 90, 6, 12, 0, 0, }, /* 370 */
+ { 61, 12, 3, 0, 0, }, /* 371 */
+ { 61, 10, 5, 0, 0, }, /* 372 */
+ { 61, 7, 12, 0, 0, }, /* 373 */
+ { 61, 13, 12, 0, 0, }, /* 374 */
+ { 61, 21, 12, 0, 0, }, /* 375 */
+ { 61, 26, 12, 0, 0, }, /* 376 */
+ { 75, 12, 3, 0, 0, }, /* 377 */
+ { 75, 10, 5, 0, 0, }, /* 378 */
+ { 75, 7, 12, 0, 0, }, /* 379 */
+ { 75, 13, 12, 0, 0, }, /* 380 */
+ { 92, 7, 12, 0, 0, }, /* 381 */
+ { 92, 12, 3, 0, 0, }, /* 382 */
+ { 92, 10, 5, 0, 0, }, /* 383 */
+ { 92, 21, 12, 0, 0, }, /* 384 */
+ { 69, 7, 12, 0, 0, }, /* 385 */
+ { 69, 10, 5, 0, 0, }, /* 386 */
+ { 69, 12, 3, 0, 0, }, /* 387 */
+ { 69, 21, 12, 0, 0, }, /* 388 */
+ { 69, 13, 12, 0, 0, }, /* 389 */
+ { 72, 13, 12, 0, 0, }, /* 390 */
+ { 72, 7, 12, 0, 0, }, /* 391 */
+ { 72, 6, 12, 0, 0, }, /* 392 */
+ { 72, 21, 12, 0, 0, }, /* 393 */
+ { 75, 21, 12, 0, 0, }, /* 394 */
+ { 9, 10, 5, 0, 0, }, /* 395 */
+ { 9, 7, 12, 0, 0, }, /* 396 */
+ { 12, 5, 12, 0, 0, }, /* 397 */
+ { 12, 6, 12, 0, 0, }, /* 398 */
+ { 33, 5, 12, 0, 35332, }, /* 399 */
+ { 33, 5, 12, 0, 3814, }, /* 400 */
+ { 33, 9, 12, 63, 1, }, /* 401 */
+ { 33, 5, 12, 63, -1, }, /* 402 */
+ { 33, 5, 12, 63, -58, }, /* 403 */
+ { 33, 9, 12, 0, -7615, }, /* 404 */
+ { 19, 5, 12, 0, 8, }, /* 405 */
+ { 19, 9, 12, 0, -8, }, /* 406 */
+ { 19, 5, 12, 0, 74, }, /* 407 */
+ { 19, 5, 12, 0, 86, }, /* 408 */
+ { 19, 5, 12, 0, 100, }, /* 409 */
+ { 19, 5, 12, 0, 128, }, /* 410 */
+ { 19, 5, 12, 0, 112, }, /* 411 */
+ { 19, 5, 12, 0, 126, }, /* 412 */
+ { 19, 8, 12, 0, -8, }, /* 413 */
+ { 19, 5, 12, 0, 9, }, /* 414 */
+ { 19, 9, 12, 0, -74, }, /* 415 */
+ { 19, 8, 12, 0, -9, }, /* 416 */
+ { 19, 5, 12, 21, -7173, }, /* 417 */
+ { 19, 9, 12, 0, -86, }, /* 418 */
+ { 19, 9, 12, 0, -100, }, /* 419 */
+ { 19, 9, 12, 0, -112, }, /* 420 */
+ { 19, 9, 12, 0, -128, }, /* 421 */
+ { 19, 9, 12, 0, -126, }, /* 422 */
+ { 27, 1, 3, 0, 0, }, /* 423 */
+ { 9, 27, 2, 0, 0, }, /* 424 */
+ { 9, 28, 2, 0, 0, }, /* 425 */
+ { 9, 2, 2, 0, 0, }, /* 426 */
+ { 27, 11, 3, 0, 0, }, /* 427 */
+ { 9, 9, 12, 0, 0, }, /* 428 */
+ { 9, 5, 12, 0, 0, }, /* 429 */
+ { 19, 9, 12, 67, -7517, }, /* 430 */
+ { 33, 9, 12, 71, -8383, }, /* 431 */
+ { 33, 9, 12, 75, -8262, }, /* 432 */
+ { 33, 9, 12, 0, 28, }, /* 433 */
+ { 33, 5, 12, 0, -28, }, /* 434 */
+ { 33, 14, 12, 0, 16, }, /* 435 */
+ { 33, 14, 12, 0, -16, }, /* 436 */
+ { 33, 14, 12, 0, 0, }, /* 437 */
+ { 9, 26, 12, 0, 26, }, /* 438 */
+ { 9, 26, 12, 0, -26, }, /* 439 */
+ { 4, 26, 12, 0, 0, }, /* 440 */
+ { 17, 9, 12, 0, 48, }, /* 441 */
+ { 17, 5, 12, 0, -48, }, /* 442 */
+ { 33, 9, 12, 0, -10743, }, /* 443 */
+ { 33, 9, 12, 0, -3814, }, /* 444 */
+ { 33, 9, 12, 0, -10727, }, /* 445 */
+ { 33, 5, 12, 0, -10795, }, /* 446 */
+ { 33, 5, 12, 0, -10792, }, /* 447 */
+ { 33, 9, 12, 0, -10780, }, /* 448 */
+ { 33, 9, 12, 0, -10749, }, /* 449 */
+ { 33, 9, 12, 0, -10783, }, /* 450 */
+ { 33, 9, 12, 0, -10782, }, /* 451 */
+ { 33, 9, 12, 0, -10815, }, /* 452 */
+ { 10, 5, 12, 0, 0, }, /* 453 */
+ { 10, 26, 12, 0, 0, }, /* 454 */
+ { 10, 12, 3, 0, 0, }, /* 455 */
+ { 10, 21, 12, 0, 0, }, /* 456 */
+ { 10, 15, 12, 0, 0, }, /* 457 */
+ { 16, 5, 12, 0, -7264, }, /* 458 */
+ { 58, 7, 12, 0, 0, }, /* 459 */
+ { 58, 6, 12, 0, 0, }, /* 460 */
+ { 58, 21, 12, 0, 0, }, /* 461 */
+ { 58, 12, 3, 0, 0, }, /* 462 */
+ { 22, 26, 12, 0, 0, }, /* 463 */
+ { 22, 6, 12, 0, 0, }, /* 464 */
+ { 22, 14, 12, 0, 0, }, /* 465 */
+ { 23, 10, 3, 0, 0, }, /* 466 */
+ { 26, 7, 12, 0, 0, }, /* 467 */
+ { 26, 6, 12, 0, 0, }, /* 468 */
+ { 29, 7, 12, 0, 0, }, /* 469 */
+ { 29, 6, 12, 0, 0, }, /* 470 */
+ { 3, 7, 12, 0, 0, }, /* 471 */
+ { 23, 7, 12, 0, 0, }, /* 472 */
+ { 23, 26, 12, 0, 0, }, /* 473 */
+ { 29, 26, 12, 0, 0, }, /* 474 */
+ { 22, 7, 12, 0, 0, }, /* 475 */
+ { 60, 7, 12, 0, 0, }, /* 476 */
+ { 60, 6, 12, 0, 0, }, /* 477 */
+ { 60, 26, 12, 0, 0, }, /* 478 */
+ { 85, 7, 12, 0, 0, }, /* 479 */
+ { 85, 6, 12, 0, 0, }, /* 480 */
+ { 85, 21, 12, 0, 0, }, /* 481 */
+ { 76, 7, 12, 0, 0, }, /* 482 */
+ { 76, 6, 12, 0, 0, }, /* 483 */
+ { 76, 21, 12, 0, 0, }, /* 484 */
+ { 76, 13, 12, 0, 0, }, /* 485 */
+ { 12, 7, 12, 0, 0, }, /* 486 */
+ { 12, 21, 12, 0, 0, }, /* 487 */
+ { 78, 7, 12, 0, 0, }, /* 488 */
+ { 78, 14, 12, 0, 0, }, /* 489 */
+ { 78, 12, 3, 0, 0, }, /* 490 */
+ { 78, 21, 12, 0, 0, }, /* 491 */
+ { 33, 9, 12, 0, -35332, }, /* 492 */
+ { 33, 9, 12, 0, -42280, }, /* 493 */
+ { 33, 9, 12, 0, -42308, }, /* 494 */
+ { 48, 7, 12, 0, 0, }, /* 495 */
+ { 48, 12, 3, 0, 0, }, /* 496 */
+ { 48, 10, 5, 0, 0, }, /* 497 */
+ { 48, 26, 12, 0, 0, }, /* 498 */
+ { 64, 7, 12, 0, 0, }, /* 499 */
+ { 64, 21, 12, 0, 0, }, /* 500 */
+ { 74, 10, 5, 0, 0, }, /* 501 */
+ { 74, 7, 12, 0, 0, }, /* 502 */
+ { 74, 12, 3, 0, 0, }, /* 503 */
+ { 74, 21, 12, 0, 0, }, /* 504 */
+ { 74, 13, 12, 0, 0, }, /* 505 */
+ { 68, 13, 12, 0, 0, }, /* 506 */
+ { 68, 7, 12, 0, 0, }, /* 507 */
+ { 68, 12, 3, 0, 0, }, /* 508 */
+ { 68, 21, 12, 0, 0, }, /* 509 */
+ { 73, 7, 12, 0, 0, }, /* 510 */
+ { 73, 12, 3, 0, 0, }, /* 511 */
+ { 73, 10, 5, 0, 0, }, /* 512 */
+ { 73, 21, 12, 0, 0, }, /* 513 */
+ { 83, 12, 3, 0, 0, }, /* 514 */
+ { 83, 10, 5, 0, 0, }, /* 515 */
+ { 83, 7, 12, 0, 0, }, /* 516 */
+ { 83, 21, 12, 0, 0, }, /* 517 */
+ { 83, 13, 12, 0, 0, }, /* 518 */
+ { 67, 7, 12, 0, 0, }, /* 519 */
+ { 67, 12, 3, 0, 0, }, /* 520 */
+ { 67, 10, 5, 0, 0, }, /* 521 */
+ { 67, 13, 12, 0, 0, }, /* 522 */
+ { 67, 21, 12, 0, 0, }, /* 523 */
+ { 38, 6, 12, 0, 0, }, /* 524 */
+ { 91, 7, 12, 0, 0, }, /* 525 */
+ { 91, 12, 3, 0, 0, }, /* 526 */
+ { 91, 6, 12, 0, 0, }, /* 527 */
+ { 91, 21, 12, 0, 0, }, /* 528 */
+ { 86, 7, 12, 0, 0, }, /* 529 */
+ { 86, 10, 5, 0, 0, }, /* 530 */
+ { 86, 12, 3, 0, 0, }, /* 531 */
+ { 86, 21, 12, 0, 0, }, /* 532 */
+ { 86, 6, 12, 0, 0, }, /* 533 */
+ { 86, 13, 12, 0, 0, }, /* 534 */
+ { 23, 7, 9, 0, 0, }, /* 535 */
+ { 23, 7, 10, 0, 0, }, /* 536 */
+ { 9, 4, 2, 0, 0, }, /* 537 */
+ { 9, 3, 12, 0, 0, }, /* 538 */
+ { 25, 25, 12, 0, 0, }, /* 539 */
+ { 0, 24, 12, 0, 0, }, /* 540 */
+ { 9, 6, 3, 0, 0, }, /* 541 */
+ { 35, 7, 12, 0, 0, }, /* 542 */
+ { 19, 14, 12, 0, 0, }, /* 543 */
+ { 19, 15, 12, 0, 0, }, /* 544 */
+ { 19, 26, 12, 0, 0, }, /* 545 */
+ { 70, 7, 12, 0, 0, }, /* 546 */
+ { 66, 7, 12, 0, 0, }, /* 547 */
+ { 41, 7, 12, 0, 0, }, /* 548 */
+ { 41, 15, 12, 0, 0, }, /* 549 */
+ { 18, 7, 12, 0, 0, }, /* 550 */
+ { 18, 14, 12, 0, 0, }, /* 551 */
+ { 59, 7, 12, 0, 0, }, /* 552 */
+ { 59, 21, 12, 0, 0, }, /* 553 */
+ { 42, 7, 12, 0, 0, }, /* 554 */
+ { 42, 21, 12, 0, 0, }, /* 555 */
+ { 42, 14, 12, 0, 0, }, /* 556 */
+ { 13, 9, 12, 0, 40, }, /* 557 */
+ { 13, 5, 12, 0, -40, }, /* 558 */
+ { 46, 7, 12, 0, 0, }, /* 559 */
+ { 44, 7, 12, 0, 0, }, /* 560 */
+ { 44, 13, 12, 0, 0, }, /* 561 */
+ { 11, 7, 12, 0, 0, }, /* 562 */
+ { 80, 7, 12, 0, 0, }, /* 563 */
+ { 80, 21, 12, 0, 0, }, /* 564 */
+ { 80, 15, 12, 0, 0, }, /* 565 */
+ { 65, 7, 12, 0, 0, }, /* 566 */
+ { 65, 15, 12, 0, 0, }, /* 567 */
+ { 65, 21, 12, 0, 0, }, /* 568 */
+ { 71, 7, 12, 0, 0, }, /* 569 */
+ { 71, 21, 12, 0, 0, }, /* 570 */
+ { 97, 7, 12, 0, 0, }, /* 571 */
+ { 96, 7, 12, 0, 0, }, /* 572 */
+ { 30, 7, 12, 0, 0, }, /* 573 */
+ { 30, 12, 3, 0, 0, }, /* 574 */
+ { 30, 15, 12, 0, 0, }, /* 575 */
+ { 30, 21, 12, 0, 0, }, /* 576 */
+ { 87, 7, 12, 0, 0, }, /* 577 */
+ { 87, 15, 12, 0, 0, }, /* 578 */
+ { 87, 21, 12, 0, 0, }, /* 579 */
+ { 77, 7, 12, 0, 0, }, /* 580 */
+ { 77, 21, 12, 0, 0, }, /* 581 */
+ { 82, 7, 12, 0, 0, }, /* 582 */
+ { 82, 15, 12, 0, 0, }, /* 583 */
+ { 81, 7, 12, 0, 0, }, /* 584 */
+ { 81, 15, 12, 0, 0, }, /* 585 */
+ { 88, 7, 12, 0, 0, }, /* 586 */
+ { 0, 15, 12, 0, 0, }, /* 587 */
+ { 93, 10, 5, 0, 0, }, /* 588 */
+ { 93, 12, 3, 0, 0, }, /* 589 */
+ { 93, 7, 12, 0, 0, }, /* 590 */
+ { 93, 21, 12, 0, 0, }, /* 591 */
+ { 93, 15, 12, 0, 0, }, /* 592 */
+ { 93, 13, 12, 0, 0, }, /* 593 */
+ { 84, 12, 3, 0, 0, }, /* 594 */
+ { 84, 10, 5, 0, 0, }, /* 595 */
+ { 84, 7, 12, 0, 0, }, /* 596 */
+ { 84, 21, 12, 0, 0, }, /* 597 */
+ { 84, 1, 2, 0, 0, }, /* 598 */
+ { 100, 7, 12, 0, 0, }, /* 599 */
+ { 100, 13, 12, 0, 0, }, /* 600 */
+ { 95, 12, 3, 0, 0, }, /* 601 */
+ { 95, 7, 12, 0, 0, }, /* 602 */
+ { 95, 10, 5, 0, 0, }, /* 603 */
+ { 95, 13, 12, 0, 0, }, /* 604 */
+ { 95, 21, 12, 0, 0, }, /* 605 */
+ { 99, 12, 3, 0, 0, }, /* 606 */
+ { 99, 10, 5, 0, 0, }, /* 607 */
+ { 99, 7, 12, 0, 0, }, /* 608 */
+ { 99, 21, 12, 0, 0, }, /* 609 */
+ { 99, 13, 12, 0, 0, }, /* 610 */
+ { 101, 7, 12, 0, 0, }, /* 611 */
+ { 101, 12, 3, 0, 0, }, /* 612 */
+ { 101, 10, 5, 0, 0, }, /* 613 */
+ { 101, 13, 12, 0, 0, }, /* 614 */
+ { 62, 7, 12, 0, 0, }, /* 615 */
+ { 62, 14, 12, 0, 0, }, /* 616 */
+ { 62, 21, 12, 0, 0, }, /* 617 */
+ { 79, 7, 12, 0, 0, }, /* 618 */
+ { 98, 7, 12, 0, 0, }, /* 619 */
+ { 98, 10, 5, 0, 0, }, /* 620 */
+ { 98, 12, 3, 0, 0, }, /* 621 */
+ { 98, 6, 12, 0, 0, }, /* 622 */
+ { 9, 10, 3, 0, 0, }, /* 623 */
+ { 19, 12, 3, 0, 0, }, /* 624 */
+ { 9, 26, 11, 0, 0, }, /* 625 */
+ { 26, 26, 12, 0, 0, }, /* 626 */
+};
+
+const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* U+0000 */
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* U+0800 */
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 41, 41, 42, 43, 44, 45, /* U+1000 */
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, /* U+1800 */
+ 62, 63, 64, 65, 66, 66, 67, 68, 69, 70, 71, 72, 73, 71, 74, 75, /* U+2000 */
+ 76, 76, 66, 77, 66, 66, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, /* U+2800 */
+ 88, 89, 90, 91, 92, 93, 94, 71, 95, 95, 95, 95, 95, 95, 95, 95, /* U+3000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+3800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+4000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 96, 95, 95, 95, 95, /* U+4800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+5000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+5800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+6000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+6800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+7000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+7800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+8000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+8800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+9000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 97, /* U+9800 */
+ 98, 99, 99, 99, 99, 99, 99, 99, 99,100,101,101,102,103,104,105, /* U+A000 */
+106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,114, /* U+A800 */
+115,116,117,118,119,120,114,115,116,117,118,119,120,114,115,116, /* U+B000 */
+117,118,119,120,114,115,116,117,118,119,120,114,115,116,117,118, /* U+B800 */
+119,120,114,115,116,117,118,119,120,114,115,116,117,118,119,120, /* U+C000 */
+114,115,116,117,118,119,120,114,115,116,117,118,119,120,114,115, /* U+C800 */
+116,117,118,119,120,114,115,116,117,118,119,120,114,115,116,121, /* U+D000 */
+122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, /* U+D800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+E000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+E800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F000 */
+123,123, 95, 95,124,125,126,127,128,128,129,130,131,132,133,134, /* U+F800 */
+135,136,137,138, 79,139,140,141,142,143, 79, 79, 79, 79, 79, 79, /* U+10000 */
+144, 79,145,146,147, 79,148, 79,149, 79, 79, 79,150, 79, 79, 79, /* U+10800 */
+151,152,153,154, 79, 79, 79, 79, 79, 79, 79, 79, 79,155, 79, 79, /* U+11000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+11800 */
+156,156,156,156,156,156,157, 79,158, 79, 79, 79, 79, 79, 79, 79, /* U+12000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+12800 */
+159,159,159,159,159,159,159,159,160, 79, 79, 79, 79, 79, 79, 79, /* U+13000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+13800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+14000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+14800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+15000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+15800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+16000 */
+161,161,161,161,162, 79, 79, 79, 79, 79, 79, 79, 79, 79,163,164, /* U+16800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+17000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+17800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+18000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+18800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+19000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+19800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1A000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1A800 */
+165, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1B000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1B800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1C000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1C800 */
+ 71,166,167,168,169, 79,170, 79,171,172,173,174,175,176,177,178, /* U+1D000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1D800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1E000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,179,180, 79, 79, /* U+1E800 */
+181,182,183,184,185, 79,186,187,188,189,190,191,192,193,194, 79, /* U+1F000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+1F800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+20000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+20800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+21000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+21800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+22000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+22800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+23000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+23800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+24000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+24800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+25000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+25800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+26000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+26800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+27000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+27800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+28000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+28800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+29000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+29800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,195, 95, 95, /* U+2A000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+2A800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,196, 95, /* U+2B000 */
+197, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2B800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2C000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2C800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2D000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2D800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2E000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2E800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2F000 */
+ 95, 95, 95, 95,197, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+2F800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+30000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+30800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+31000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+31800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+32000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+32800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+33000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+33800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+34000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+34800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+35000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+35800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+36000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+36800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+37000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+37800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+38000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+38800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+39000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+39800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3A000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3A800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3B000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3B800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3C000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3C800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3D000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3D800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3E000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3E800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3F000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+3F800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+40000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+40800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+41000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+41800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+42000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+42800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+43000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+43800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+44000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+44800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+45000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+45800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+46000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+46800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+47000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+47800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+48000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+48800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+49000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+49800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4A000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4A800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4B000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4B800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4C000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4C800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4D000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4D800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4E000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4E800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4F000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+4F800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+50000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+50800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+51000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+51800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+52000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+52800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+53000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+53800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+54000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+54800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+55000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+55800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+56000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+56800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+57000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+57800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+58000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+58800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+59000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+59800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5A000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5A800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5B000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5B800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5C000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5C800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5D000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5D800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5E000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5E800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5F000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+5F800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+60000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+60800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+61000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+61800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+62000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+62800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+63000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+63800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+64000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+64800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+65000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+65800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+66000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+66800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+67000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+67800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+68000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+68800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+69000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+69800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6A000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6A800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6B000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6B800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6C000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6C800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6D000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6D800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6E000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6E800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6F000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+6F800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+70000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+70800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+71000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+71800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+72000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+72800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+73000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+73800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+74000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+74800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+75000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+75800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+76000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+76800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+77000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+77800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+78000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+78800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+79000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+79800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7A000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7A800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7B000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7B800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7C000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7C800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7D000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7D800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7E000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7E800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7F000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+7F800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+80000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+80800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+81000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+81800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+82000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+82800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+83000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+83800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+84000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+84800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+85000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+85800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+86000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+86800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+87000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+87800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+88000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+88800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+89000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+89800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8A000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8A800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8B000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8B800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8C000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8C800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8D000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8D800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8E000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8E800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8F000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+8F800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+90000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+90800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+91000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+91800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+92000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+92800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+93000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+93800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+94000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+94800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+95000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+95800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+96000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+96800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+97000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+97800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+98000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+98800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+99000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+99800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9A000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9A800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9B000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9B800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9C000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9C800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9D000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9D800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9E000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9E800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9F000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+9F800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A0000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A0800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A1000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A1800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A2000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A2800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A3000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A3800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A4000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A4800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A5000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A5800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A6000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A6800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A7000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A7800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A8000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A8800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A9000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+A9800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AA000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AA800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AB000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AB800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AC000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AC800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AD000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AD800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AE000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AE800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AF000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+AF800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B0000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B0800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B1000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B1800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B2000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B2800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B3000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B3800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B4000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B4800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B5000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B5800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B6000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B6800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B7000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B7800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B8000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B8800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B9000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+B9800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BA000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BA800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BB000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BB800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BC000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BC800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BD000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BD800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BE000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BE800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BF000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+BF800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C0000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C0800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C1000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C1800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C2000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C2800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C3000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C3800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C4000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C4800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C5000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C5800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C6000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C6800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C7000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C7800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C8000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C8800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C9000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+C9800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CA000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CA800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CB000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CB800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CC000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CC800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CD000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CD800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CE000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CE800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CF000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+CF800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D0000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D0800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D1000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D1800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D2000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D2800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D3000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D3800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D4000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D4800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D5000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D5800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D6000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D6800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D7000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D7800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D8000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D8800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D9000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+D9800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DA000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DA800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DB000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DB800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DC000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DC800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DD000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DD800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DE000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DE800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DF000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+DF800 */
+198,199,200,201,199,199,199,199,199,199,199,199,199,199,199,199, /* U+E0000 */
+199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, /* U+E0800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E1000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E1800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E2000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E2800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E3000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E3800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E4000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E4800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E5000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E5800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E6000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E6800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E7000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E7800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E8000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E8800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E9000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+E9800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EA000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EA800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EB000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EB800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EC000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EC800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+ED000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+ED800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EE000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EE800 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EF000 */
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, /* U+EF800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F0000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F0800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F1000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F1800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F2000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F2800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F3000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F3800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F4000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F4800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F5000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F5800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F6000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F6800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F7000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F7800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F8000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F8800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F9000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F9800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FA000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FA800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FB000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FB800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FC000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FC800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FD000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FD800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FE000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FE800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FF000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,202, /* U+FF800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+100000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+100800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+101000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+101800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+102000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+102800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+103000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+103800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+104000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+104800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+105000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+105800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+106000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+106800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+107000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+107800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+108000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+108800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+109000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+109800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10A000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10A800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10B000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10B800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10C000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10C800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10D000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10D800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10E000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10E800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10F000 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,202, /* U+10F800 */
+};
+
+const pcre_uint16 PRIV(ucd_stage2)[] = { /* 51968 bytes, block = 128 */
+/* block 0 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, 4, 4, 4, 5, 4, 4, 4, 6, 7, 4, 8, 4, 9, 4, 4,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 4, 8, 8, 8, 4,
+ 4, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 11, 11, 11, 11,
+ 11, 11, 11, 13, 11, 11, 11, 11, 11, 11, 11, 6, 4, 7, 14, 15,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 16, 16, 16, 16,
+ 16, 16, 16, 18, 16, 16, 16, 16, 16, 16, 16, 6, 8, 7, 8, 0,
+
+/* block 1 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, 4, 5, 5, 5, 5, 19, 4, 14, 19, 20, 21, 8, 22, 19, 14,
+ 19, 8, 23, 23, 14, 24, 4, 4, 14, 23, 20, 25, 23, 23, 23, 4,
+ 11, 11, 11, 11, 11, 26, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 8, 11, 11, 11, 11, 11, 11, 11, 27,
+ 16, 16, 16, 16, 16, 28, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 8, 16, 16, 16, 16, 16, 16, 16, 29,
+
+/* block 2 */
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 32, 33, 30, 31, 30, 31, 30, 31, 33, 30, 31, 30, 31, 30, 31, 30,
+ 31, 30, 31, 30, 31, 30, 31, 30, 31, 33, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 34, 30, 31, 30, 31, 30, 31, 35,
+
+/* block 3 */
+ 36, 37, 30, 31, 30, 31, 38, 30, 31, 39, 39, 30, 31, 33, 40, 41,
+ 42, 30, 31, 39, 43, 44, 45, 46, 30, 31, 47, 33, 45, 48, 49, 50,
+ 30, 31, 30, 31, 30, 31, 51, 30, 31, 51, 33, 33, 30, 31, 51, 30,
+ 31, 52, 52, 30, 31, 30, 31, 53, 30, 31, 33, 20, 30, 31, 33, 54,
+ 20, 20, 20, 20, 55, 56, 57, 58, 59, 60, 61, 62, 63, 30, 31, 30,
+ 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 64, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 33, 65, 66, 67, 30, 31, 68, 69, 30, 31, 30, 31, 30, 31, 30, 31,
+
+/* block 4 */
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 70, 33, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 33, 33, 33, 33, 33, 33, 71, 30, 31, 72, 73, 74,
+ 74, 30, 31, 75, 76, 77, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 78, 79, 80, 81, 82, 33, 83, 83, 33, 84, 33, 85, 33, 33, 33, 33,
+ 83, 33, 33, 86, 33, 87, 88, 33, 89, 90, 33, 91, 33, 33, 33, 90,
+ 33, 92, 93, 33, 33, 94, 33, 33, 33, 33, 33, 33, 33, 95, 33, 33,
+
+/* block 5 */
+ 96, 33, 33, 96, 33, 33, 33, 33, 96, 97, 98, 98, 99, 33, 33, 33,
+ 33, 33,100, 33, 20, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+101,101,101,101,101,101,101,101,101,102,102,102,102,102,102,102,
+102,102, 14, 14, 14, 14,102,102,102,102,102,102,102,102,102,102,
+102,102, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+101,101,101,101,101, 14, 14, 14, 14, 14,103,103,102, 14,102, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+
+/* block 6 */
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,105,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+106,107,106,107,102,108,106,107,109,109,110,111,111,111, 4,109,
+
+/* block 7 */
+109,109,109,109,108, 14,112, 4,113,113,113,109,114,109,115,115,
+116,117,118,117,117,119,117,117,120,121,122,117,123,117,117,117,
+124,125,109,126,117,117,127,117,117,128,117,117,129,130,130,130,
+116,131,132,131,131,133,131,131,134,135,136,131,137,131,131,131,
+138,139,140,141,131,131,142,131,131,143,131,131,144,145,145,146,
+147,148,149,149,149,150,151,152,106,107,106,107,106,107,106,107,
+106,107,153,154,153,154,153,154,153,154,153,154,153,154,153,154,
+155,156,157,116,158,159,160,106,107,161,106,107,116,162,162,162,
+
+/* block 8 */
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
+164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
+165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
+165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
+166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,
+167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168,
+167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168,
+
+/* block 9 */
+167,168,169,170,170,104,104,170,171,171,167,168,167,168,167,168,
+167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168,
+167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168,
+167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168,
+172,167,168,167,168,167,168,167,168,167,168,167,168,167,168,173,
+167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168,
+167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168,
+167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168,
+
+/* block 10 */
+167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168,
+167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168,
+167,168,167,168,167,168,167,168,109,109,109,109,109,109,109,109,
+109,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,
+174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,
+174,174,174,174,174,174,174,109,109,175,176,176,176,176,176,176,
+109,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
+
+/* block 11 */
+177,177,177,177,177,177,177,178,109, 4,179,109,109,109,109,180,
+109,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
+181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
+181,181,181,181,181,181,181,181,181,181,181,181,181,181,182,181,
+183,181,181,183,181,181,183,181,109,109,109,109,109,109,109,109,
+184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
+184,184,184,184,184,184,184,184,184,184,184,109,109,109,109,109,
+184,184,184,183,183,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 12 */
+185,185,185,185,185,109,186,186,186,187,187,188, 4,187,189,189,
+190,190,190,190,190,190,190,190,190,190,190, 4,185,109,187, 4,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+102,191,191,191,191,191,191,191,191,191,191,104,104,104,104,104,
+104,104,104,104,104,104,190,190,190,190,190,190,190,190,190,190,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,187,187,187,187,191,191,
+104,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+
+/* block 13 */
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,187,191,190,190,190,190,190,190,190, 22,189,190,
+190,190,190,190,190,192,192,190,190,189,190,190,190,190,191,191,
+193,193,193,193,193,193,193,193,193,193,191,191,191,189,189,191,
+
+/* block 14 */
+194,194,194,194,194,194,194,194,194,194,194,194,194,194,109,195,
+196,197,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
+197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
+197,197,197,197,197,197,197,197,197,197,197,109,109,196,196,196,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+
+/* block 15 */
+198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,
+198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,
+198,198,198,198,198,198,199,199,199,199,199,199,199,199,199,199,
+199,198,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+200,200,200,200,200,200,200,200,200,200,201,201,201,201,201,201,
+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
+201,201,201,201,201,201,201,201,201,201,201,202,202,202,202,202,
+202,202,202,202,203,203,204,205,205,205,203,109,109,109,109,109,
+
+/* block 16 */
+206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,
+206,206,206,206,206,206,207,207,207,207,208,207,207,207,207,207,
+207,207,207,207,208,207,207,207,208,207,207,207,207,207,109,109,
+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,109,
+210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,
+210,210,210,210,210,210,210,210,210,211,211,211,109,109,212,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 17 */
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+191,109,191,191,191,191,191,191,191,191,191,191,191,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,190,190,190,190,190,190,190,190,190,190,190,190,
+190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,109,
+
+/* block 18 */
+213,213,213,214,215,215,215,215,215,215,215,215,215,215,215,215,
+215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,
+215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,
+215,215,215,215,215,215,215,215,215,215,213,214,213,215,214,214,
+214,213,213,213,213,213,213,213,213,214,214,214,214,213,214,214,
+215,104,104,213,213,213,213,213,215,215,215,215,215,215,215,215,
+215,215,213,213, 4, 4,216,216,216,216,216,216,216,216,216,216,
+217,218,215,215,215,215,215,215,109,215,215,215,215,215,215,215,
+
+/* block 19 */
+109,219,220,220,109,221,221,221,221,221,221,221,221,109,109,221,
+221,109,109,221,221,221,221,221,221,221,221,221,221,221,221,221,
+221,221,221,221,221,221,221,221,221,109,221,221,221,221,221,221,
+221,109,221,109,109,109,221,221,221,221,109,109,219,221,222,220,
+220,219,219,219,219,109,109,220,220,109,109,220,220,219,221,109,
+109,109,109,109,109,109,109,222,109,109,109,109,221,221,109,221,
+221,221,219,219,109,109,223,223,223,223,223,223,223,223,223,223,
+221,221,224,224,225,225,225,225,225,225,226,224,109,109,109,109,
+
+/* block 20 */
+109,227,227,228,109,229,229,229,229,229,229,109,109,109,109,229,
+229,109,109,229,229,229,229,229,229,229,229,229,229,229,229,229,
+229,229,229,229,229,229,229,229,229,109,229,229,229,229,229,229,
+229,109,229,229,109,229,229,109,229,229,109,109,227,109,228,228,
+228,227,227,109,109,109,109,227,227,109,109,227,227,227,109,109,
+109,227,109,109,109,109,109,109,109,229,229,229,229,109,229,109,
+109,109,109,109,109,109,230,230,230,230,230,230,230,230,230,230,
+227,227,229,229,229,227,109,109,109,109,109,109,109,109,109,109,
+
+/* block 21 */
+109,231,231,232,109,233,233,233,233,233,233,233,233,233,109,233,
+233,233,109,233,233,233,233,233,233,233,233,233,233,233,233,233,
+233,233,233,233,233,233,233,233,233,109,233,233,233,233,233,233,
+233,109,233,233,109,233,233,233,233,233,109,109,231,233,232,232,
+232,231,231,231,231,231,109,231,231,232,109,232,232,231,109,109,
+233,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+233,233,231,231,109,109,234,234,234,234,234,234,234,234,234,234,
+235,236,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 22 */
+109,237,238,238,109,239,239,239,239,239,239,239,239,109,109,239,
+239,109,109,239,239,239,239,239,239,239,239,239,239,239,239,239,
+239,239,239,239,239,239,239,239,239,109,239,239,239,239,239,239,
+239,109,239,239,109,239,239,239,239,239,109,109,237,239,240,237,
+238,237,237,237,237,109,109,238,238,109,109,238,238,237,109,109,
+109,109,109,109,109,109,237,240,109,109,109,109,239,239,109,239,
+239,239,237,237,109,109,241,241,241,241,241,241,241,241,241,241,
+242,239,243,243,243,243,243,243,109,109,109,109,109,109,109,109,
+
+/* block 23 */
+109,109,244,245,109,245,245,245,245,245,245,109,109,109,245,245,
+245,109,245,245,245,245,109,109,109,245,245,109,245,109,245,245,
+109,109,109,245,245,109,109,109,245,245,245,109,109,109,245,245,
+245,245,245,245,245,245,245,245,245,245,109,109,109,109,246,247,
+244,247,247,109,109,109,247,247,247,109,247,247,247,244,109,109,
+245,109,109,109,109,109,109,246,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,248,248,248,248,248,248,248,248,248,248,
+249,249,249,250,250,250,250,250,250,251,250,109,109,109,109,109,
+
+/* block 24 */
+109,252,252,252,109,253,253,253,253,253,253,253,253,109,253,253,
+253,109,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,109,253,253,253,253,253,253,
+253,253,253,253,109,253,253,253,253,253,109,109,109,253,254,254,
+254,252,252,252,252,109,254,254,254,109,254,254,254,254,109,109,
+109,109,109,109,109,254,254,109,253,253,109,109,109,109,109,109,
+253,253,254,254,109,109,255,255,255,255,255,255,255,255,255,255,
+109,109,109,109,109,109,109,109,256,256,256,256,256,256,256,257,
+
+/* block 25 */
+109,109,258,258,109,259,259,259,259,259,259,259,259,109,259,259,
+259,109,259,259,259,259,259,259,259,259,259,259,259,259,259,259,
+259,259,259,259,259,259,259,259,259,109,259,259,259,259,259,259,
+259,259,259,259,109,259,259,259,259,259,109,109,260,259,258,260,
+258,258,261,258,258,109,260,258,258,109,258,258,260,260,109,109,
+109,109,109,109,109,261,261,109,109,109,109,109,109,109,259,109,
+259,259,260,260,109,109,262,262,262,262,262,262,262,262,262,262,
+109,259,259,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 26 */
+109,109,263,263,109,264,264,264,264,264,264,264,264,109,264,264,
+264,109,264,264,264,264,264,264,264,264,264,264,264,264,264,264,
+264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,
+264,264,264,264,264,264,264,264,264,264,264,109,109,264,265,263,
+263,266,266,266,266,109,263,263,263,109,263,263,263,266,264,109,
+109,109,109,109,109,109,109,265,109,109,109,109,109,109,109,109,
+264,264,266,266,109,109,267,267,267,267,267,267,267,267,267,267,
+268,268,268,268,268,268,109,109,109,269,264,264,264,264,264,264,
+
+/* block 27 */
+109,109,270,270,109,271,271,271,271,271,271,271,271,271,271,271,
+271,271,271,271,271,271,271,109,109,109,271,271,271,271,271,271,
+271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,
+271,271,109,271,271,271,271,271,271,271,271,271,109,271,109,109,
+271,271,271,271,271,271,271,109,109,109,272,109,109,109,109,273,
+270,270,272,272,272,109,272,109,270,270,270,270,270,270,270,273,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,270,270,274,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 28 */
+109,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,
+275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,
+275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,
+275,276,275,277,276,276,276,276,276,276,276,109,109,109,109, 5,
+275,275,275,275,275,275,278,276,276,276,276,276,276,276,276,279,
+280,280,280,280,280,280,280,280,280,280,279,279,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 29 */
+109,281,281,109,281,109,109,281,281,109,281,109,109,281,109,109,
+109,109,109,109,281,281,281,281,109,281,281,281,281,281,281,281,
+109,281,281,281,109,281,109,281,109,109,281,281,109,281,281,281,
+281,282,281,283,282,282,282,282,282,282,109,282,282,281,109,109,
+281,281,281,281,281,109,284,109,282,282,282,282,282,282,109,109,
+285,285,285,285,285,285,285,285,285,285,109,109,281,281,281,281,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 30 */
+286,287,287,287,288,288,288,288,288,288,288,288,288,288,288,288,
+288,288,288,287,288,287,287,287,289,289,287,287,287,287,287,287,
+290,290,290,290,290,290,290,290,290,290,291,291,291,291,291,291,
+291,291,291,291,287,289,287,289,287,289,292,293,292,293,294,294,
+286,286,286,286,286,286,286,286,109,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,109,109,109,
+109,289,289,289,289,289,289,289,289,289,289,289,289,289,289,294,
+
+/* block 31 */
+289,289,289,289,289,288,289,289,286,286,286,286,286,289,289,289,
+289,289,289,289,289,289,289,289,109,289,289,289,289,289,289,289,
+289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,
+289,289,289,289,289,289,289,289,289,289,289,289,289,109,287,287,
+287,287,287,287,287,287,289,287,287,287,287,287,287,109,287,287,
+288,288,288,288,288, 19, 19, 19, 19,288,288,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 32 */
+295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,
+295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,
+295,295,295,295,295,295,295,295,295,295,295,296,296,297,297,297,
+297,298,297,297,297,297,297,297,296,297,297,298,298,297,297,295,
+299,299,299,299,299,299,299,299,299,299,300,300,300,300,300,300,
+295,295,295,295,295,295,298,298,297,297,295,295,295,295,297,297,
+297,295,296,296,296,295,295,296,296,296,296,296,296,296,295,295,
+295,297,297,297,297,295,295,295,295,295,295,295,295,295,295,295,
+
+/* block 33 */
+295,295,297,296,298,297,297,296,296,296,296,296,296,297,295,296,
+299,299,299,299,299,299,299,299,299,299,296,296,296,297,301,301,
+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,
+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,
+302,302,302,302,302,302,109,302,109,109,109,109,109,302,109,109,
+303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,
+303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,
+303,303,303,303,303,303,303,303,303,303,303, 4,304,303,303,303,
+
+/* block 34 */
+305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,
+305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,
+305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,
+305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,
+305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,
+305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,
+306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,
+306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,
+
+/* block 35 */
+306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,
+306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,
+306,306,306,306,306,306,306,306,307,307,307,307,307,307,307,307,
+307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,
+307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,
+307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,
+307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,
+307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,
+
+/* block 36 */
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,308,308,109,308,308,308,308,109,109,
+308,308,308,308,308,308,308,109,308,109,308,308,308,308,109,109,
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+
+/* block 37 */
+308,308,308,308,308,308,308,308,308,109,308,308,308,308,109,109,
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,109,308,308,308,308,109,109,308,308,308,308,308,308,308,109,
+308,109,308,308,308,308,109,109,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,109,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+
+/* block 38 */
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,109,308,308,308,308,109,109,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,308,308,308,308,109,109,309,309,309,
+310,310,310,310,310,310,310,310,310,311,311,311,311,311,311,311,
+311,311,311,311,311,311,311,311,311,311,311,311,311,109,109,109,
+
+/* block 39 */
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+312,312,312,312,312,312,312,312,312,312,109,109,109,109,109,109,
+313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,
+313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,
+313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,
+313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,
+313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,
+313,313,313,313,313,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 40 */
+314,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+
+/* block 41 */
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+
+/* block 42 */
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,316,316,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+
+/* block 43 */
+317,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,
+318,318,318,318,318,318,318,318,318,318,318,319,320,109,109,109,
+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,
+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,
+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,
+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,
+321,321,321,321,321,321,321,321,321,321,321, 4, 4, 4,322,322,
+322,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 44 */
+323,323,323,323,323,323,323,323,323,323,323,323,323,109,323,323,
+323,323,324,324,324,109,109,109,109,109,109,109,109,109,109,109,
+325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,
+325,325,326,326,326, 4, 4,109,109,109,109,109,109,109,109,109,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,328,328,109,109,109,109,109,109,109,109,109,109,109,109,
+329,329,329,329,329,329,329,329,329,329,329,329,329,109,329,329,
+329,109,330,330,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 45 */
+331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,
+331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,
+331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,
+331,331,331,331,332,332,333,332,332,332,332,332,332,332,333,333,
+333,333,333,333,333,333,332,333,333,332,332,332,332,332,332,332,
+332,332,332,332,334,334,334,335,334,334,334,336,331,332,109,109,
+337,337,337,337,337,337,337,337,337,337,109,109,109,109,109,109,
+338,338,338,338,338,338,338,338,338,338,109,109,109,109,109,109,
+
+/* block 46 */
+339,339, 4, 4,339, 4,340,339,339,339,339,341,341,341,342,109,
+343,343,343,343,343,343,343,343,343,343,109,109,109,109,109,109,
+344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,
+344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,
+344,344,344,345,344,344,344,344,344,344,344,344,344,344,344,344,
+344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,
+344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,
+344,344,344,344,344,344,344,344,109,109,109,109,109,109,109,109,
+
+/* block 47 */
+344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,
+344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,
+344,344,344,344,344,344,344,344,344,341,344,109,109,109,109,109,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,109,109,109,109,109,109,109,109,109,109,
+
+/* block 48 */
+346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,
+346,346,346,346,346,346,346,346,346,346,346,346,346,109,109,109,
+347,347,347,348,348,348,348,347,347,348,348,348,109,109,109,109,
+348,348,347,348,348,348,348,348,348,347,347,347,109,109,109,109,
+349,109,109,109,350,350,351,351,351,351,351,351,351,351,351,351,
+352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,
+352,352,352,352,352,352,352,352,352,352,352,352,352,352,109,109,
+352,352,352,352,352,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 49 */
+353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,
+353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,
+353,353,353,353,353,353,353,353,353,353,353,353,109,109,109,109,
+354,354,354,354,354,355,355,355,354,354,355,354,354,354,354,354,
+354,353,353,353,353,353,353,353,354,354,109,109,109,109,109,109,
+356,356,356,356,356,356,356,356,356,356,357,109,109,109,358,358,
+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
+
+/* block 50 */
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,361,361,362,362,361,109,109,363,363,
+364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,
+364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,
+364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,
+364,364,364,364,364,365,366,365,366,366,366,366,366,366,366,109,
+366,367,366,367,367,366,366,366,366,366,366,366,366,365,365,365,
+365,365,365,366,366,366,366,366,366,366,366,366,366,109,109,366,
+
+/* block 51 */
+368,368,368,368,368,368,368,368,368,368,109,109,109,109,109,109,
+368,368,368,368,368,368,368,368,368,368,109,109,109,109,109,109,
+369,369,369,369,369,369,369,370,369,369,369,369,369,369,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 52 */
+371,371,371,371,372,373,373,373,373,373,373,373,373,373,373,373,
+373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
+373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
+373,373,373,373,371,372,371,371,371,371,371,372,371,372,372,372,
+372,372,371,372,372,373,373,373,373,373,373,373,109,109,109,109,
+374,374,374,374,374,374,374,374,374,374,375,375,375,375,375,375,
+375,376,376,376,376,376,376,376,376,376,376,371,371,371,371,371,
+371,371,371,371,376,376,376,376,376,376,376,376,376,109,109,109,
+
+/* block 53 */
+377,377,378,379,379,379,379,379,379,379,379,379,379,379,379,379,
+379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,
+379,378,377,377,377,377,378,378,377,377,378,377,378,378,379,379,
+380,380,380,380,380,380,380,380,380,380,379,379,379,379,379,379,
+381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,
+381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,
+381,381,381,381,381,381,382,383,382,382,383,383,383,382,383,382,
+382,382,383,383,109,109,109,109,109,109,109,109,384,384,384,384,
+
+/* block 54 */
+385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,
+385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,
+385,385,385,385,386,386,386,386,386,386,386,386,387,387,387,387,
+387,387,387,387,386,386,387,387,109,109,109,388,388,388,388,388,
+389,389,389,389,389,389,389,389,389,389,109,109,109,385,385,385,
+390,390,390,390,390,390,390,390,390,390,391,391,391,391,391,391,
+391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,
+391,391,391,391,391,391,391,391,392,392,392,392,392,392,393,393,
+
+/* block 55 */
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+394,394,394,394,394,394,394,394,109,109,109,109,109,109,109,109,
+104,104,104, 4,104,104,104,104,104,104,104,104,104,104,104,104,
+104,395,104,104,104,104,104,104,104,396,396,396,396,104,396,396,
+396,396,395,395,104,396,396,109,109,109,109,109,109,109,109,109,
+
+/* block 56 */
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33,116,116,116,116,116,397,101,101,101,101,
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
+101,101,101,101,101,101,101,101,101,101,101,101,101,110,110,110,
+110,110,101,101,101,101,110,110,110,110,110, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33,398,399, 33, 33, 33,400, 33, 33,
+
+/* block 57 */
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,101,101,101,101,101,
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,110,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,104,104,104,104,
+
+/* block 58 */
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+401,402, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+
+/* block 59 */
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 33, 33, 33, 33, 33,403, 33, 33,404, 33,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+
+/* block 60 */
+405,405,405,405,405,405,405,405,406,406,406,406,406,406,406,406,
+405,405,405,405,405,405,109,109,406,406,406,406,406,406,109,109,
+405,405,405,405,405,405,405,405,406,406,406,406,406,406,406,406,
+405,405,405,405,405,405,405,405,406,406,406,406,406,406,406,406,
+405,405,405,405,405,405,109,109,406,406,406,406,406,406,109,109,
+116,405,116,405,116,405,116,405,109,406,109,406,109,406,109,406,
+405,405,405,405,405,405,405,405,406,406,406,406,406,406,406,406,
+407,407,408,408,408,408,409,409,410,410,411,411,412,412,109,109,
+
+/* block 61 */
+405,405,405,405,405,405,405,405,413,413,413,413,413,413,413,413,
+405,405,405,405,405,405,405,405,413,413,413,413,413,413,413,413,
+405,405,405,405,405,405,405,405,413,413,413,413,413,413,413,413,
+405,405,116,414,116,109,116,116,406,406,415,415,416,108,417,108,
+108,108,116,414,116,109,116,116,418,418,418,418,416,108,108,108,
+405,405,116,116,109,109,116,116,406,406,419,419,109,108,108,108,
+405,405,116,116,116,157,116,116,406,406,420,420,161,108,108,108,
+109,109,116,414,116,109,116,116,421,421,422,422,416,108,108,109,
+
+/* block 62 */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 22,423,423, 22, 22,
+ 9, 9, 9, 9, 9, 9, 4, 4, 21, 25, 6, 21, 21, 25, 6, 21,
+ 4, 4, 4, 4, 4, 4, 4, 4,424,425, 22, 22, 22, 22, 22, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 21, 25, 4, 4, 4, 4, 15,
+ 15, 4, 4, 4, 8, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 8, 4, 15, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3,
+ 22, 22, 22, 22, 22,426, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23,101,109,109, 23, 23, 23, 23, 23, 23, 8, 8, 8, 6, 7,101,
+
+/* block 63 */
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 8, 8, 8, 6, 7,109,
+101,101,101,101,101,101,101,101,101,101,101,101,101,109,109,109,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+104,104,104,104,104,104,104,104,104,104,104,104,104,427,427,427,
+427,104,427,427,427,104,104,104,104,104,104,104,104,104,104,104,
+104,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 64 */
+ 19, 19,428, 19, 19, 19, 19,428, 19, 19,429,428,428,428,429,429,
+428,428,428,429, 19,428, 19, 19, 8,428,428,428,428,428, 19, 19,
+ 19, 19, 19, 19,428, 19,430, 19,428, 19,431,432,428,428, 19,429,
+428,428,433,428,429,396,396,396,396,429, 19, 19,429,429,428,428,
+ 8, 8, 8, 8, 8,428,429,429,429,429, 19, 8, 19, 19,434, 19,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,
+436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
+
+/* block 65 */
+437,437,437, 30, 31,437,437,437,437, 23,109,109,109,109,109,109,
+ 8, 8, 8, 8, 8, 19, 19, 19, 19, 19, 8, 8, 19, 19, 19, 19,
+ 8, 19, 19, 8, 19, 19, 8, 19, 19, 19, 19, 19, 19, 19, 8, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 8, 8,
+ 19, 19, 8, 19, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+
+/* block 66 */
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+
+/* block 67 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 6, 7, 6, 7, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 8, 8, 19, 19, 19, 19, 19, 19, 19, 6, 7, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 8, 19, 19, 19,
+
+/* block 68 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 8, 8, 8, 8,
+ 8, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 69 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+
+/* block 70 */
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19,438,438,438,438,438,438,438,438,438,438,
+438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,
+439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
+439,439,439,439,439,439,439,439,439,439, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+
+/* block 71 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+
+/* block 72 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 8, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 8, 8, 8, 8, 8, 8, 8, 8,
+
+/* block 73 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 8,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+
+/* block 74 */
+109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 6, 7, 6, 7, 6, 7, 6, 7,
+ 6, 7, 6, 7, 6, 7, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+
+/* block 75 */
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 8, 8, 8, 8, 8, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+
+/* block 76 */
+440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,
+440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,
+440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,
+440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,
+440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,
+440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,
+440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,
+440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,
+
+/* block 77 */
+ 8, 8, 8, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6,
+ 7, 6, 7, 6, 7, 6, 7, 6, 7, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 6, 7, 6, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 7, 8, 8,
+
+/* block 78 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 19, 19, 8, 8, 8, 8, 8, 8,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 79 */
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 80 */
+441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,
+441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,
+441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,109,
+442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,
+442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,
+442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,109,
+ 30, 31,443,444,445,446,447, 30, 31, 30, 31, 30, 31,448,449,450,
+451, 33, 30, 31, 33, 30, 31, 33, 33, 33, 33, 33,101,101,452,452,
+
+/* block 81 */
+153,154,153,154,153,154,153,154,153,154,153,154,153,154,153,154,
+153,154,153,154,153,154,153,154,153,154,153,154,153,154,153,154,
+153,154,153,154,153,154,153,154,153,154,153,154,153,154,153,154,
+153,154,153,154,153,154,153,154,153,154,153,154,153,154,153,154,
+153,154,153,154,153,154,153,154,153,154,153,154,153,154,153,154,
+153,154,153,154,153,154,153,154,153,154,153,154,153,154,153,154,
+153,154,153,154,453,454,454,454,454,454,454,153,154,153,154,455,
+455,455,153,154,109,109,109,109,109,456,456,456,456,457,456,456,
+
+/* block 82 */
+458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,
+458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,
+458,458,458,458,458,458,109,458,109,109,109,109,109,458,109,109,
+459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,
+459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,
+459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,
+459,459,459,459,459,459,459,459,109,109,109,109,109,109,109,460,
+461,109,109,109,109,109,109,109,109,109,109,109,109,109,109,462,
+
+/* block 83 */
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,109,109,109,109,109,109,109,109,109,
+308,308,308,308,308,308,308,109,308,308,308,308,308,308,308,109,
+308,308,308,308,308,308,308,109,308,308,308,308,308,308,308,109,
+308,308,308,308,308,308,308,109,308,308,308,308,308,308,308,109,
+308,308,308,308,308,308,308,109,308,308,308,308,308,308,308,109,
+170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,
+170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,
+
+/* block 84 */
+ 4, 4, 21, 25, 21, 25, 4, 4, 4, 21, 25, 4, 21, 25, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 9, 4, 4, 9, 4, 21, 25, 4, 4,
+ 21, 25, 6, 7, 6, 7, 6, 7, 6, 7, 4, 4, 4, 4, 4,102,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 85 */
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,109,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 86 */
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+
+/* block 87 */
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,
+
+/* block 88 */
+ 3, 4, 4, 4, 19,464,396,465, 6, 7, 6, 7, 6, 7, 6, 7,
+ 6, 7, 19, 19, 6, 7, 6, 7, 6, 7, 6, 7, 9, 6, 7, 7,
+ 19,465,465,465,465,465,465,465,465,465,104,104,104,104,466,466,
+ 9,102,102,102,102,102, 19, 19,465,465,465,464,396, 4, 19, 19,
+109,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
+467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
+467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
+467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
+
+/* block 89 */
+467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
+467,467,467,467,467,467,467,109,109,104,104, 14, 14,468,468,467,
+ 9,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,
+469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,
+469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,
+469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,
+469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,
+469,469,469,469,469,469,469,469,469,469,469, 4,102,470,470,469,
+
+/* block 90 */
+109,109,109,109,109,471,471,471,471,471,471,471,471,471,471,471,
+471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,
+471,471,471,471,471,471,471,471,471,471,471,471,471,471,109,109,
+109,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+
+/* block 91 */
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,109,
+ 19, 19, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,
+471,471,471,471,471,471,471,471,471,471,471,109,109,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109,109,109,
+469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,
+
+/* block 92 */
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,109,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 23, 23, 23, 23, 23, 23, 23, 23,
+ 19, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, 19,
+
+/* block 93 */
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,
+474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,
+474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,109,
+
+/* block 94 */
+474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,
+474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,
+474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,
+474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,
+474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,
+474,474,474,474,474,474,474,474, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+
+/* block 95 */
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+
+/* block 96 */
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,109,109,109,109,109,109,109,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+
+/* block 97 */
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 98 */
+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+476,476,476,476,476,477,476,476,476,476,476,476,476,476,476,476,
+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+
+/* block 99 */
+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+
+/* block 100 */
+476,476,476,476,476,476,476,476,476,476,476,476,476,109,109,109,
+478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
+478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
+478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
+478,478,478,478,478,478,478,109,109,109,109,109,109,109,109,109,
+479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,
+479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,
+479,479,479,479,479,479,479,479,480,480,480,480,480,480,481,481,
+
+/* block 101 */
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+
+/* block 102 */
+482,482,482,482,482,482,482,482,482,482,482,482,483,484,484,484,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+485,485,485,485,485,485,485,485,485,485,482,482,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168,
+167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168,
+167,168,167,168,167,168,167,168,167,168,167,168,167,168,486,170,
+171,171,171,487,170,170,170,170,170,170,170,170,170,170,487,398,
+
+/* block 103 */
+167,168,167,168,167,168,167,168,167,168,167,168,167,168,167,168,
+167,168,167,168,167,168,167,168,109,109,109,109,109,109,109,170,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,489,489,489,489,489,489,489,489,489,489,
+490,490,491,491,491,491,491,491,109,109,109,109,109,109,109,109,
+
+/* block 104 */
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14,102,102,102,102,102,102,102,102,102,
+ 14, 14, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 33, 33, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+101, 33, 33, 33, 33, 33, 33, 33, 33, 30, 31, 30, 31,492, 30, 31,
+
+/* block 105 */
+ 30, 31, 30, 31, 30, 31, 30, 31,102, 14, 14, 30, 31,493, 33,109,
+ 30, 31, 30, 31,109,109,109,109,109,109,109,109,109,109,109,109,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,494,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,101,101, 33, 20, 20, 20, 20, 20,
+
+/* block 106 */
+495,495,496,495,495,495,496,495,495,495,495,496,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,497,497,496,496,497,498,498,498,498,109,109,109,109,
+ 23, 23, 23, 23, 23, 23, 19, 19, 5, 19,109,109,109,109,109,109,
+499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,
+499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,
+499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,
+499,499,499,499,500,500,500,500,109,109,109,109,109,109,109,109,
+
+/* block 107 */
+501,501,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
+502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
+502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
+502,502,502,502,501,501,501,501,501,501,501,501,501,501,501,501,
+501,501,501,501,503,109,109,109,109,109,109,109,109,109,504,504,
+505,505,505,505,505,505,505,505,505,505,109,109,109,109,109,109,
+213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
+213,213,215,215,215,215,215,215,217,217,217,215,109,109,109,109,
+
+/* block 108 */
+506,506,506,506,506,506,506,506,506,506,507,507,507,507,507,507,
+507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
+507,507,507,507,507,507,508,508,508,508,508,508,508,508,509,509,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,511,511,511,511,511,511,511,511,511,
+511,511,512,512,109,109,109,109,109,109,109,109,109,109,109,513,
+305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,
+305,305,305,305,305,305,305,305,305,305,305,305,305,109,109,109,
+
+/* block 109 */
+514,514,514,515,516,516,516,516,516,516,516,516,516,516,516,516,
+516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
+516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
+516,516,516,514,515,515,514,514,514,514,515,515,514,515,515,515,
+515,517,517,517,517,517,517,517,517,517,517,517,517,517,109,102,
+518,518,518,518,518,518,518,518,518,518,109,109,109,109,517,517,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 110 */
+519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
+519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
+519,519,519,519,519,519,519,519,519,520,520,520,520,520,520,521,
+521,520,520,521,521,520,520,109,109,109,109,109,109,109,109,109,
+519,519,519,520,519,519,519,519,519,519,519,519,520,521,109,109,
+522,522,522,522,522,522,522,522,522,522,109,109,523,523,523,523,
+295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,
+524,295,295,295,295,295,295,301,301,301,295,296,109,109,109,109,
+
+/* block 111 */
+525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,
+525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,
+525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,
+526,525,526,526,526,525,525,526,526,525,525,525,525,525,526,526,
+525,526,525,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,525,525,527,528,528,
+529,529,529,529,529,529,529,529,529,529,529,530,531,531,530,530,
+532,532,529,533,533,530,531,109,109,109,109,109,109,109,109,109,
+
+/* block 112 */
+109,308,308,308,308,308,308,109,109,308,308,308,308,308,308,109,
+109,308,308,308,308,308,308,109,109,109,109,109,109,109,109,109,
+308,308,308,308,308,308,308,109,308,308,308,308,308,308,308,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 113 */
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,
+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,
+529,529,529,530,530,531,530,530,531,530,530,532,530,531,109,109,
+534,534,534,534,534,534,534,534,534,534,109,109,109,109,109,109,
+
+/* block 114 */
+535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+
+/* block 115 */
+536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536,
+
+/* block 116 */
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+
+/* block 117 */
+536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536,
+
+/* block 118 */
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+
+/* block 119 */
+536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536,
+
+/* block 120 */
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+535,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,535,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,535,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+
+/* block 121 */
+536,536,536,536,536,536,536,536,535,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,109,109,109,109,109,109,109,109,109,109,109,109,
+306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,
+306,306,306,306,306,306,306,109,109,109,109,307,307,307,307,307,
+307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,
+307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,
+307,307,307,307,307,307,307,307,307,307,307,307,109,109,109,109,
+
+/* block 122 */
+537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,
+537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,
+537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,
+537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,
+537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,
+537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,
+537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,
+537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,
+
+/* block 123 */
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+
+/* block 124 */
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,109,109,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+
+/* block 125 */
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 126 */
+ 33, 33, 33, 33, 33, 33, 33,109,109,109,109,109,109,109,109,109,
+109,109,109,178,178,178,178,178,109,109,109,109,109,184,181,184,
+184,184,184,184,184,184,184,184,184,539,184,184,184,184,184,184,
+184,184,184,184,184,184,184,109,184,184,184,184,184,109,184,109,
+184,184,109,184,184,109,184,184,184,184,184,184,184,184,184,184,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+
+/* block 127 */
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,540,540,540,540,540,540,540,540,540,540,540,540,540,540,
+540,540,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+
+/* block 128 */
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+
+/* block 129 */
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191, 6, 7,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+
+/* block 130 */
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+109,109,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+191,191,191,191,191,191,191,191,191,191,191,191,188, 19,109,109,
+
+/* block 131 */
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+ 4, 4, 4, 4, 4, 4, 4, 6, 7, 4,109,109,109,109,109,109,
+104,104,104,104,104,104,104,109,109,109,109,109,109,109,109,109,
+ 4, 9, 9, 15, 15, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6,
+ 7, 6, 7, 6, 7, 4, 4, 6, 7, 4, 4, 4, 4, 15, 15, 15,
+ 4, 4, 4,109, 4, 4, 4, 4, 9, 6, 7, 6, 7, 6, 7, 4,
+ 4, 4, 8, 9, 8, 8, 8,109, 4, 5, 4, 4,109,109,109,109,
+191,191,191,191,191,109,191,191,191,191,191,191,191,191,191,191,
+
+/* block 132 */
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,109,109, 22,
+
+/* block 133 */
+109, 4, 4, 4, 5, 4, 4, 4, 6, 7, 4, 8, 4, 9, 4, 4,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 4, 8, 8, 8, 4,
+ 4, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 6, 4, 7, 14, 15,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 6, 8, 7, 8, 6,
+ 7, 4, 6, 7, 4, 4,469,469,469,469,469,469,469,469,469,469,
+102,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,
+
+/* block 134 */
+469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,
+469,469,469,469,469,469,469,469,469,469,469,469,469,469,541,541,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,109,
+109,109,472,472,472,472,472,472,109,109,472,472,472,472,472,472,
+109,109,472,472,472,472,472,472,109,109,472,472,472,109,109,109,
+ 5, 5, 8, 14, 19, 5, 5,109, 19, 8, 8, 8, 8, 19, 19,109,
+426,426,426,426,426,426,426,426,426, 22, 22, 22, 19, 19,109,109,
+
+/* block 135 */
+542,542,542,542,542,542,542,542,542,542,542,542,109,542,542,542,
+542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,
+542,542,542,542,542,542,542,109,542,542,542,542,542,542,542,542,
+542,542,542,542,542,542,542,542,542,542,542,109,542,542,109,542,
+542,542,542,542,542,542,542,542,542,542,542,542,542,542,109,109,
+542,542,542,542,542,542,542,542,542,542,542,542,542,542,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 136 */
+542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,
+542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,
+542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,
+542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,
+542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,
+542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,
+542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,
+542,542,542,542,542,542,542,542,542,542,542,109,109,109,109,109,
+
+/* block 137 */
+ 4, 4, 4,109,109,109,109, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23,109,109,109, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,
+543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,
+543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,
+543,543,543,543,543,544,544,544,544,545,545,545,545,545,545,545,
+
+/* block 138 */
+545,545,545,545,545,545,545,545,545,545,544,109,109,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,104,109,109,
+
+/* block 139 */
+546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,
+546,546,546,546,546,546,546,546,546,546,546,546,546,109,109,109,
+547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,
+547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,
+547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,
+547,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 140 */
+548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,
+548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,109,
+549,549,549,549,109,109,109,109,109,109,109,109,109,109,109,109,
+550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
+550,551,550,550,550,550,550,550,550,550,551,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 141 */
+552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
+552,552,552,552,552,552,552,552,552,552,552,552,552,552,109,553,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,109,109,109,109,554,554,554,554,554,554,554,554,
+555,556,556,556,556,556,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 142 */
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,558,558,558,558,558,558,558,558,
+558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,
+558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,
+559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
+559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
+559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
+
+/* block 143 */
+560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,
+560,560,560,560,560,560,560,560,560,560,560,560,560,560,109,109,
+561,561,561,561,561,561,561,561,561,561,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 144 */
+562,562,562,562,562,562,109,109,562,109,562,562,562,562,562,562,
+562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,
+562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,
+562,562,562,562,562,562,109,562,562,109,109,109,562,109,109,562,
+563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,
+563,563,563,563,563,563,109,564,565,565,565,565,565,565,565,565,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 145 */
+566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,
+566,566,566,566,566,566,567,567,567,567,567,567,109,109,109,568,
+569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,
+569,569,569,569,569,569,569,569,569,569,109,109,109,109,109,570,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 146 */
+571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,
+571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,
+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,
+572,572,572,572,572,572,572,572,109,109,109,109,109,109,572,572,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 147 */
+573,574,574,574,109,574,574,109,109,109,109,109,574,574,574,574,
+573,573,573,573,109,573,573,573,109,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,109,109,109,109,574,574,574,109,109,109,109,574,
+575,575,575,575,575,575,575,575,109,109,109,109,109,109,109,109,
+576,576,576,576,576,576,576,576,576,109,109,109,109,109,109,109,
+577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
+577,577,577,577,577,577,577,577,577,577,577,577,577,578,578,579,
+
+/* block 148 */
+580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,
+580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,
+580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,
+580,580,580,580,580,580,109,109,109,581,581,581,581,581,581,581,
+582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,
+582,582,582,582,582,582,109,109,583,583,583,583,583,583,583,583,
+584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
+584,584,584,109,109,109,109,109,585,585,585,585,585,585,585,585,
+
+/* block 149 */
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 150 */
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,109,
+
+/* block 151 */
+588,589,588,590,590,590,590,590,590,590,590,590,590,590,590,590,
+590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,
+590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,
+590,590,590,590,590,590,590,590,589,589,589,589,589,589,589,589,
+589,589,589,589,589,589,589,591,591,591,591,591,591,591,109,109,
+109,109,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
+592,592,592,592,592,592,593,593,593,593,593,593,593,593,593,593,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 152 */
+594,594,595,596,596,596,596,596,596,596,596,596,596,596,596,596,
+596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
+596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
+595,595,595,594,594,594,594,595,595,594,594,597,597,598,597,597,
+597,597,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,
+599,599,599,599,599,599,599,599,599,109,109,109,109,109,109,109,
+600,600,600,600,600,600,600,600,600,600,109,109,109,109,109,109,
+
+/* block 153 */
+601,601,601,602,602,602,602,602,602,602,602,602,602,602,602,602,
+602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,
+602,602,602,602,602,602,602,601,601,601,601,601,603,601,601,601,
+601,601,601,601,601,109,604,604,604,604,604,604,604,604,604,604,
+605,605,605,605,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 154 */
+606,606,607,608,608,608,608,608,608,608,608,608,608,608,608,608,
+608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,
+608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,
+608,608,608,607,607,607,606,606,606,606,606,606,606,606,606,607,
+607,608,608,608,608,609,609,609,609,109,109,109,109,109,109,109,
+610,610,610,610,610,610,610,610,610,610,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 155 */
+611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,
+611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,
+611,611,611,611,611,611,611,611,611,611,611,612,613,612,613,613,
+612,612,612,612,612,612,613,612,109,109,109,109,109,109,109,109,
+614,614,614,614,614,614,614,614,614,614,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 156 */
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+
+/* block 157 */
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 158 */
+616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,
+616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,
+616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,
+616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,
+616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,
+616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,
+616,616,616,109,109,109,109,109,109,109,109,109,109,109,109,109,
+617,617,617,617,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 159 */
+618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,
+618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,
+618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,
+618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,
+618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,
+618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,
+618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,
+618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,
+
+/* block 160 */
+618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,
+618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,
+618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 161 */
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+
+/* block 162 */
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 163 */
+619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,
+619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,
+619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,
+619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,
+619,619,619,619,619,109,109,109,109,109,109,109,109,109,109,109,
+619,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
+620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
+620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,109,
+
+/* block 164 */
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,621,
+621,621,621,622,622,622,622,622,622,622,622,622,622,622,622,622,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 165 */
+469,467,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 166 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109,
+
+/* block 167 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19,109,109, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19,623,395,104,104,104, 19, 19, 19,395,623,623,
+623,623,623, 22, 22, 22, 22, 22, 22, 22, 22,104,104,104,104,104,
+
+/* block 168 */
+104,104,104, 19, 19,104,104,104,104,104,104,104, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,104,104,104,104, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 169 */
+545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
+545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
+545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
+545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
+545,545,624,624,624,545,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 170 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 171 */
+428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,
+428,428,428,428,428,428,428,428,428,428,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,428,428,428,428,428,428,428,428,428,428,428,428,
+428,428,428,428,428,428,428,428,428,428,428,428,428,428,429,429,
+429,429,429,429,429,109,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,428,428,428,428,428,428,428,428,
+428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,
+
+/* block 172 */
+428,428,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,428,109,428,428,
+109,109,428,109,109,428,428,109,109,428,428,428,428,109,428,428,
+428,428,428,428,428,428,429,429,429,429,109,429,109,429,429,429,
+429,429,429,429,109,429,429,429,429,429,429,429,429,429,429,429,
+428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,
+428,428,428,428,428,428,428,428,428,428,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+
+/* block 173 */
+429,429,429,429,428,428,109,428,428,428,428,109,109,428,428,428,
+428,428,428,428,428,109,428,428,428,428,428,428,428,109,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,428,428,109,428,428,428,428,109,
+428,428,428,428,428,109,428,109,109,109,428,428,428,428,428,428,
+428,109,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,428,428,428,428,
+428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,
+
+/* block 174 */
+428,428,428,428,428,428,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,
+428,428,428,428,428,428,428,428,428,428,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,428,428,428,428,428,428,428,428,428,428,428,428,
+428,428,428,428,428,428,428,428,428,428,428,428,428,428,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+
+/* block 175 */
+429,429,429,429,429,429,429,429,428,428,428,428,428,428,428,428,
+428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,
+428,428,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,428,428,428,428,
+428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,
+428,428,428,428,428,428,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,
+
+/* block 176 */
+428,428,428,428,428,428,428,428,428,428,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,429,429,109,109,428,428,428,428,428,428,428,428,
+428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,
+428, 8,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,429,429,429, 8,429,429,429,429,
+429,429,428,428,428,428,428,428,428,428,428,428,428,428,428,428,
+428,428,428,428,428,428,428,428,428,428,428, 8,429,429,429,429,
+
+/* block 177 */
+429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,429, 8,429,429,429,429,429,429,428,428,428,428,
+428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,
+428,428,428,428,428, 8,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, 8,
+429,429,429,429,429,429,428,428,428,428,428,428,428,428,428,428,
+428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, 8,
+429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+
+/* block 178 */
+429,429,429,429,429,429,429,429,429, 8,429,429,429,429,429,429,
+428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,
+428,428,428,428,428,428,428,428,428, 8,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+429,429,429, 8,429,429,429,429,429,429,428,429,109,109, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+
+/* block 179 */
+191,191,191,191,109,191,191,191,191,191,191,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+109,191,191,109,191,109,109,191,109,191,191,191,191,191,191,191,
+191,191,191,109,191,191,191,191,109,191,109,191,109,109,109,109,
+109,109,191,109,109,109,109,191,109,191,109,191,109,191,191,191,
+109,191,191,109,191,109,109,191,109,191,109,191,109,191,109,191,
+109,191,191,109,191,109,109,191,191,191,191,109,191,191,191,191,
+191,191,191,109,191,191,191,191,109,191,191,191,191,109,191,109,
+
+/* block 180 */
+191,191,191,191,191,191,191,191,191,191,109,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,109,109,109,109,
+109,191,191,191,109,191,191,191,191,191,109,191,191,191,191,191,
+191,191,191,191,191,191,191,191,191,191,191,191,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+186,186,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 181 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+
+/* block 182 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,
+109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,
+109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 183 */
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,109,109,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+
+/* block 184 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,625,625,625,625,625,625,625,625,625,625,
+625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,
+
+/* block 185 */
+626, 19, 19,109,109,109,109,109,109,109,109,109,109,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109,109,109,
+ 19, 19,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 186 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+ 19, 19, 19, 19, 19, 19,109, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,
+
+/* block 187 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19,109, 19, 19, 19, 19, 19,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 188 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,
+ 19,109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+
+/* block 189 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19,109, 19, 19, 19, 19,109,109,109,
+
+/* block 190 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,
+ 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109,109,109,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 191 */
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109, 19, 19, 19, 19, 19,
+
+/* block 192 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19,109,109,109,109, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 193 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 194 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 195 */
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 196 */
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,109,109,109,109,109,109,109,109,109,109,109,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+
+/* block 197 */
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+
+/* block 198 */
+426, 22,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
+426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+
+/* block 199 */
+426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
+426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
+426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
+426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
+426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
+426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
+426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
+426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
+
+/* block 200 */
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+
+/* block 201 */
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
+
+/* block 202 */
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,109,109,
+
+};
+
+#if UCD_BLOCK_SIZE != 128
+#error Please correct UCD_BLOCK_SIZE in pcre_internal.h
+#endif
+#endif /* SUPPORT_UCP */
+
+#endif /* PCRE_INCLUDED */
diff --git a/plugins/Pcre16/src/pcre_version.c b/plugins/Pcre16/src/pcre_version.c
new file mode 100644
index 0000000000..ae86ff28bc
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_version.c
@@ -0,0 +1,98 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2012 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 external function pcre_version(), which returns a
+string that identifies the PCRE version that is in use. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+
+/*************************************************
+* Return version string *
+*************************************************/
+
+/* These macros are the standard way of turning unquoted text into C strings.
+They allow macros like PCRE_MAJOR to be defined without quotes, which is
+convenient for user programs that want to test its value. */
+
+#define STRING(a) # a
+#define XSTRING(s) STRING(s)
+
+/* A problem turned up with PCRE_PRERELEASE, which is defined empty for
+production releases. Originally, it was used naively in this code:
+
+ return XSTRING(PCRE_MAJOR)
+ "." XSTRING(PCRE_MINOR)
+ XSTRING(PCRE_PRERELEASE)
+ " " XSTRING(PCRE_DATE);
+
+However, when PCRE_PRERELEASE is empty, this leads to an attempted expansion of
+STRING(). The C standard states: "If (before argument substitution) any
+argument consists of no preprocessing tokens, the behavior is undefined." It
+turns out the gcc treats this case as a single empty string - which is what we
+really want - but Visual C grumbles about the lack of an argument for the
+macro. Unfortunately, both are within their rights. To cope with both ways of
+handling this, I had resort to some messy hackery that does a test at run time.
+I could find no way of detecting that a macro is defined as an empty string at
+pre-processor time. This hack uses a standard trick for avoiding calling
+the STRING macro with an empty argument when doing the test. */
+
+#if defined COMPILE_PCRE8
+PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
+pcre_version(void)
+#elif defined COMPILE_PCRE16
+PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
+pcre16_version(void)
+#elif defined COMPILE_PCRE32
+PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
+pcre32_version(void)
+#endif
+{
+return (XSTRING(Z PCRE_PRERELEASE)[1] == 0)?
+ XSTRING(PCRE_MAJOR.PCRE_MINOR PCRE_DATE) :
+ XSTRING(PCRE_MAJOR.PCRE_MINOR) XSTRING(PCRE_PRERELEASE PCRE_DATE);
+}
+
+/* End of pcre_version.c */
diff --git a/plugins/Pcre16/src/pcre_xclass.c b/plugins/Pcre16/src/pcre_xclass.c
new file mode 100644
index 0000000000..c2b61f0f92
--- /dev/null
+++ b/plugins/Pcre16/src/pcre_xclass.c
@@ -0,0 +1,268 @@
+/*************************************************
+* 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
+ Copyright (c) 1997-2013 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 an internal function that is used to match an extended
+class. It is used by both pcre_exec() and pcre_def_exec(). */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+
+/*************************************************
+* Match character against an XCLASS *
+*************************************************/
+
+/* This function is called to match a character against an extended class that
+might contain values > 255 and/or Unicode properties.
+
+Arguments:
+ c the character
+ data points to the flag byte of the XCLASS data
+
+Returns: TRUE if character matches, else FALSE
+*/
+
+BOOL
+PRIV(xclass)(pcre_uint32 c, const pcre_uchar *data, BOOL utf)
+{
+pcre_uchar t;
+BOOL negated = (*data & XCL_NOT) != 0;
+
+(void)utf;
+#ifdef COMPILE_PCRE8
+/* In 8 bit mode, this must always be TRUE. Help the compiler to know that. */
+utf = TRUE;
+#endif
+
+/* Character values < 256 are matched against a bitmap, if one is present. If
+not, we still carry on, because there may be ranges that start below 256 in the
+additional data. */
+
+if (c < 256)
+ {
+ if ((*data & XCL_HASPROP) == 0)
+ {
+ if ((*data & XCL_MAP) == 0) return negated;
+ return (((pcre_uint8 *)(data + 1))[c/8] & (1 << (c&7))) != 0;
+ }
+ if ((*data & XCL_MAP) != 0 &&
+ (((pcre_uint8 *)(data + 1))[c/8] & (1 << (c&7))) != 0)
+ return !negated; /* char found */
+ }
+
+/* First skip the bit map if present. Then match against the list of Unicode
+properties or large chars or ranges that end with a large char. We won't ever
+encounter XCL_PROP or XCL_NOTPROP when UCP support is not compiled. */
+
+if ((*data++ & XCL_MAP) != 0) data += 32 / sizeof(pcre_uchar);
+
+while ((t = *data++) != XCL_END)
+ {
+ pcre_uint32 x, y;
+ if (t == XCL_SINGLE)
+ {
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ GETCHARINC(x, data); /* macro generates multiple statements */
+ }
+ else
+#endif
+ x = *data++;
+ if (c == x) return !negated;
+ }
+ else if (t == XCL_RANGE)
+ {
+#ifdef SUPPORT_UTF
+ if (utf)
+ {
+ GETCHARINC(x, data); /* macro generates multiple statements */
+ GETCHARINC(y, data); /* macro generates multiple statements */
+ }
+ else
+#endif
+ {
+ x = *data++;
+ y = *data++;
+ }
+ if (c >= x && c <= y) return !negated;
+ }
+
+#ifdef SUPPORT_UCP
+ else /* XCL_PROP & XCL_NOTPROP */
+ {
+ const ucd_record *prop = GET_UCD(c);
+ BOOL isprop = t == XCL_PROP;
+
+ switch(*data)
+ {
+ case PT_ANY:
+ if (isprop) return !negated;
+ break;
+
+ case PT_LAMP:
+ if ((prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
+ prop->chartype == ucp_Lt) == isprop) return !negated;
+ break;
+
+ case PT_GC:
+ if ((data[1] == PRIV(ucp_gentype)[prop->chartype]) == isprop)
+ return !negated;
+ break;
+
+ case PT_PC:
+ if ((data[1] == prop->chartype) == isprop) return !negated;
+ break;
+
+ case PT_SC:
+ if ((data[1] == prop->script) == isprop) return !negated;
+ break;
+
+ case PT_ALNUM:
+ if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N) == isprop)
+ return !negated;
+ break;
+
+ /* Perl space used to exclude VT, but from Perl 5.18 it is included,
+ which means that Perl space and POSIX space are now identical. PCRE
+ was changed at release 8.34. */
+
+ case PT_SPACE: /* Perl space */
+ case PT_PXSPACE: /* POSIX space */
+ switch(c)
+ {
+ HSPACE_CASES:
+ VSPACE_CASES:
+ if (isprop) return !negated;
+ break;
+
+ default:
+ if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == isprop)
+ return !negated;
+ break;
+ }
+ break;
+
+ case PT_WORD:
+ if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE)
+ == isprop)
+ return !negated;
+ break;
+
+ case PT_UCNC:
+ if (c < 0xa0)
+ {
+ if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
+ c == CHAR_GRAVE_ACCENT) == isprop)
+ return !negated;
+ }
+ else
+ {
+ if ((c < 0xd800 || c > 0xdfff) == isprop)
+ return !negated;
+ }
+ break;
+
+ /* The following three properties can occur only in an XCLASS, as there
+ is no \p or \P coding for them. */
+
+ /* Graphic character. Implement this as not Z (space or separator) and
+ not C (other), except for Cf (format) with a few exceptions. This seems
+ to be what Perl does. The exceptional characters are:
+
+ U+061C Arabic Letter Mark
+ U+180E Mongolian Vowel Separator
+ U+2066 - U+2069 Various "isolate"s
+ */
+
+ case PT_PXGRAPH:
+ if ((PRIV(ucp_gentype)[prop->chartype] != ucp_Z &&
+ (PRIV(ucp_gentype)[prop->chartype] != ucp_C ||
+ (prop->chartype == ucp_Cf &&
+ c != 0x061c && c != 0x180e && (c < 0x2066 || c > 0x2069))
+ )) == isprop)
+ return !negated;
+ break;
+
+ /* Printable character: same as graphic, with the addition of Zs, i.e.
+ not Zl and not Zp, and U+180E. */
+
+ case PT_PXPRINT:
+ if ((prop->chartype != ucp_Zl &&
+ prop->chartype != ucp_Zp &&
+ (PRIV(ucp_gentype)[prop->chartype] != ucp_C ||
+ (prop->chartype == ucp_Cf &&
+ c != 0x061c && (c < 0x2066 || c > 0x2069))
+ )) == isprop)
+ return !negated;
+ break;
+
+ /* Punctuation: all Unicode punctuation, plus ASCII characters that
+ Unicode treats as symbols rather than punctuation, for Perl
+ compatibility (these are $+<=>^`|~). */
+
+ case PT_PXPUNCT:
+ if ((PRIV(ucp_gentype)[prop->chartype] == ucp_P ||
+ (c < 256 && PRIV(ucp_gentype)[prop->chartype] == ucp_S)) == isprop)
+ return !negated;
+ break;
+
+ /* This should never occur, but compilers may mutter if there is no
+ default. */
+
+ default:
+ return FALSE;
+ }
+
+ data += 2;
+ }
+#endif /* SUPPORT_UCP */
+ }
+
+return negated; /* char did not match */
+}
+
+/* End of pcre_xclass.c */
diff --git a/plugins/Pcre16/src/ucp.h b/plugins/Pcre16/src/ucp.h
new file mode 100644
index 0000000000..d8b34bfcc5
--- /dev/null
+++ b/plugins/Pcre16/src/ucp.h
@@ -0,0 +1,200 @@
+/*************************************************
+* Unicode Property Table handler *
+*************************************************/
+
+#ifndef _UCP_H
+#define _UCP_H
+
+/* This file contains definitions of the property values that are returned by
+the UCD access macros. New values that are added for new releases of Unicode
+should always be at the end of each enum, for backwards compatibility.
+
+IMPORTANT: Note also that the specific numeric values of the enums have to be
+the same as the values that are generated by the maint/MultiStage2.py script,
+where the equivalent property descriptive names are listed in vectors.
+
+ALSO: The specific values of the first two enums are assumed for the table
+called catposstab in pcre_compile.c. */
+
+/* These are the general character categories. */
+
+enum {
+ ucp_C, /* Other */
+ ucp_L, /* Letter */
+ ucp_M, /* Mark */
+ ucp_N, /* Number */
+ ucp_P, /* Punctuation */
+ ucp_S, /* Symbol */
+ ucp_Z /* Separator */
+};
+
+/* These are the particular character categories. */
+
+enum {
+ ucp_Cc, /* Control */
+ ucp_Cf, /* Format */
+ ucp_Cn, /* Unassigned */
+ ucp_Co, /* Private use */
+ ucp_Cs, /* Surrogate */
+ ucp_Ll, /* Lower case letter */
+ ucp_Lm, /* Modifier letter */
+ ucp_Lo, /* Other letter */
+ ucp_Lt, /* Title case letter */
+ ucp_Lu, /* Upper case letter */
+ ucp_Mc, /* Spacing mark */
+ ucp_Me, /* Enclosing mark */
+ ucp_Mn, /* Non-spacing mark */
+ ucp_Nd, /* Decimal number */
+ ucp_Nl, /* Letter number */
+ ucp_No, /* Other number */
+ ucp_Pc, /* Connector punctuation */
+ ucp_Pd, /* Dash punctuation */
+ ucp_Pe, /* Close punctuation */
+ ucp_Pf, /* Final punctuation */
+ ucp_Pi, /* Initial punctuation */
+ ucp_Po, /* Other punctuation */
+ ucp_Ps, /* Open punctuation */
+ ucp_Sc, /* Currency symbol */
+ ucp_Sk, /* Modifier symbol */
+ ucp_Sm, /* Mathematical symbol */
+ ucp_So, /* Other symbol */
+ ucp_Zl, /* Line separator */
+ ucp_Zp, /* Paragraph separator */
+ ucp_Zs /* Space separator */
+};
+
+/* These are grapheme break properties. Note that the code for processing them
+assumes that the values are less than 16. If more values are added that take
+the number to 16 or more, the code will have to be rewritten. */
+
+enum {
+ ucp_gbCR, /* 0 */
+ ucp_gbLF, /* 1 */
+ ucp_gbControl, /* 2 */
+ ucp_gbExtend, /* 3 */
+ ucp_gbPrepend, /* 4 */
+ ucp_gbSpacingMark, /* 5 */
+ ucp_gbL, /* 6 Hangul syllable type L */
+ ucp_gbV, /* 7 Hangul syllable type V */
+ ucp_gbT, /* 8 Hangul syllable type T */
+ ucp_gbLV, /* 9 Hangul syllable type LV */
+ ucp_gbLVT, /* 10 Hangul syllable type LVT */
+ ucp_gbRegionalIndicator, /* 11 */
+ ucp_gbOther /* 12 */
+};
+
+/* These are the script identifications. */
+
+enum {
+ ucp_Arabic,
+ ucp_Armenian,
+ ucp_Bengali,
+ ucp_Bopomofo,
+ ucp_Braille,
+ ucp_Buginese,
+ ucp_Buhid,
+ ucp_Canadian_Aboriginal,
+ ucp_Cherokee,
+ ucp_Common,
+ ucp_Coptic,
+ ucp_Cypriot,
+ ucp_Cyrillic,
+ ucp_Deseret,
+ ucp_Devanagari,
+ ucp_Ethiopic,
+ ucp_Georgian,
+ ucp_Glagolitic,
+ ucp_Gothic,
+ ucp_Greek,
+ ucp_Gujarati,
+ ucp_Gurmukhi,
+ ucp_Han,
+ ucp_Hangul,
+ ucp_Hanunoo,
+ ucp_Hebrew,
+ ucp_Hiragana,
+ ucp_Inherited,
+ ucp_Kannada,
+ ucp_Katakana,
+ ucp_Kharoshthi,
+ ucp_Khmer,
+ ucp_Lao,
+ ucp_Latin,
+ ucp_Limbu,
+ ucp_Linear_B,
+ ucp_Malayalam,
+ ucp_Mongolian,
+ ucp_Myanmar,
+ ucp_New_Tai_Lue,
+ ucp_Ogham,
+ ucp_Old_Italic,
+ ucp_Old_Persian,
+ ucp_Oriya,
+ ucp_Osmanya,
+ ucp_Runic,
+ ucp_Shavian,
+ ucp_Sinhala,
+ ucp_Syloti_Nagri,
+ ucp_Syriac,
+ ucp_Tagalog,
+ ucp_Tagbanwa,
+ ucp_Tai_Le,
+ ucp_Tamil,
+ ucp_Telugu,
+ ucp_Thaana,
+ ucp_Thai,
+ ucp_Tibetan,
+ ucp_Tifinagh,
+ ucp_Ugaritic,
+ ucp_Yi,
+ /* New for Unicode 5.0: */
+ ucp_Balinese,
+ ucp_Cuneiform,
+ ucp_Nko,
+ ucp_Phags_Pa,
+ ucp_Phoenician,
+ /* New for Unicode 5.1: */
+ ucp_Carian,
+ ucp_Cham,
+ ucp_Kayah_Li,
+ ucp_Lepcha,
+ ucp_Lycian,
+ ucp_Lydian,
+ ucp_Ol_Chiki,
+ ucp_Rejang,
+ ucp_Saurashtra,
+ ucp_Sundanese,
+ ucp_Vai,
+ /* New for Unicode 5.2: */
+ ucp_Avestan,
+ ucp_Bamum,
+ ucp_Egyptian_Hieroglyphs,
+ ucp_Imperial_Aramaic,
+ ucp_Inscriptional_Pahlavi,
+ ucp_Inscriptional_Parthian,
+ ucp_Javanese,
+ ucp_Kaithi,
+ ucp_Lisu,
+ ucp_Meetei_Mayek,
+ ucp_Old_South_Arabian,
+ ucp_Old_Turkic,
+ ucp_Samaritan,
+ ucp_Tai_Tham,
+ ucp_Tai_Viet,
+ /* New for Unicode 6.0.0: */
+ ucp_Batak,
+ ucp_Brahmi,
+ ucp_Mandaic,
+ /* New for Unicode 6.1.0: */
+ ucp_Chakma,
+ ucp_Meroitic_Cursive,
+ ucp_Meroitic_Hieroglyphs,
+ ucp_Miao,
+ ucp_Sharada,
+ ucp_Sora_Sompeng,
+ ucp_Takri
+};
+
+#endif
+
+/* End of ucp.h */