QRegularExpression: import PCRE under 3rdparty/
authorGiuseppe D'Angelo <dangelog@gmail.com>
Mon, 23 Jan 2012 23:06:27 +0000 (23:06 +0000)
committerQt by Nokia <qt-info@nokia.com>
Sat, 3 Mar 2012 00:00:12 +0000 (01:00 +0100)
Imported only the minimum subset of PCRE version 8.30,
without documentation, tests, examples, etc. by using
the import_from_pcre_tarball.sh script.

Change-Id: Ib1112a6179789814cc3c90cbde59408d2ccd0f57
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
65 files changed:
src/3rdparty/pcre/AUTHORS [new file with mode: 0644]
src/3rdparty/pcre/COPYING [new file with mode: 0644]
src/3rdparty/pcre/LICENCE [new file with mode: 0644]
src/3rdparty/pcre/pcre.h [new file with mode: 0644]
src/3rdparty/pcre/pcre16_byte_order.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_chartables.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_compile.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_config.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_dfa_exec.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_exec.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_fullinfo.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_get.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_globals.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_jit_compile.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_maketables.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_newline.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_ord2utf16.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_refcount.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_string_utils.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_study.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_tables.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_ucd.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_utf16_utils.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_valid_utf16.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_version.c [new file with mode: 0644]
src/3rdparty/pcre/pcre16_xclass.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_byte_order.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_chartables.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_compile.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_config.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_dfa_exec.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_exec.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_fullinfo.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_get.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_globals.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_internal.h [new file with mode: 0644]
src/3rdparty/pcre/pcre_jit_compile.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_maketables.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_newline.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_ord2utf8.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_refcount.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_string_utils.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_study.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_tables.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_ucd.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_valid_utf8.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_version.c [new file with mode: 0644]
src/3rdparty/pcre/pcre_xclass.c [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitConfig.h [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitConfigInternal.h [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitExecAllocator.c [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitLir.c [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitLir.h [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitNativeARM_v5.c [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitNativePPC_32.c [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitNativePPC_64.c [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitNativePPC_common.c [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitNativeX86_32.c [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitNativeX86_64.c [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitNativeX86_common.c [new file with mode: 0644]
src/3rdparty/pcre/sljit/sljitUtils.c [new file with mode: 0644]
src/3rdparty/pcre/ucp.h [new file with mode: 0644]

diff --git a/src/3rdparty/pcre/AUTHORS b/src/3rdparty/pcre/AUTHORS
new file mode 100644 (file)
index 0000000..ba4753d
--- /dev/null
@@ -0,0 +1,45 @@
+THE MAIN PCRE LIBRARY
+---------------------
+
+Written by:       Philip Hazel
+Email local part: ph10
+Email domain:     cam.ac.uk
+
+University of Cambridge Computing Service,
+Cambridge, England.
+
+Copyright (c) 1997-2012 University of Cambridge
+All rights reserved
+
+
+PCRE JUST-IN-TIME COMPILATION SUPPORT
+-------------------------------------
+
+Written by:       Zoltan Herczeg
+Email local part: hzmester
+Emain domain:     freemail.hu
+
+Copyright(c) 2010-2012 Zoltan Herczeg
+All rights reserved.
+
+
+STACK-LESS JUST-IN-TIME COMPILER
+--------------------------------
+
+Written by:       Zoltan Herczeg
+Email local part: hzmester
+Emain domain:     freemail.hu
+
+Copyright(c) 2009-2012 Zoltan Herczeg
+All rights reserved.
+
+
+THE C++ WRAPPER LIBRARY
+-----------------------
+
+Written by:       Google Inc.
+
+Copyright (c) 2007-2012 Google Inc
+All rights reserved
+
+####
diff --git a/src/3rdparty/pcre/COPYING b/src/3rdparty/pcre/COPYING
new file mode 100644 (file)
index 0000000..58eed01
--- /dev/null
@@ -0,0 +1,5 @@
+PCRE LICENCE
+
+Please see the file LICENCE in the PCRE distribution for licensing details.
+
+End
diff --git a/src/3rdparty/pcre/LICENCE b/src/3rdparty/pcre/LICENCE
new file mode 100644 (file)
index 0000000..5ce31a8
--- /dev/null
@@ -0,0 +1,92 @@
+PCRE LICENCE
+------------
+
+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.
+
+Release 8 of PCRE is distributed under the terms of the "BSD" licence, as
+specified below. The documentation for PCRE, supplied in the "doc"
+directory, is distributed under the same terms as the software itself.
+
+The basic library functions are written in C and are freestanding. Also
+included in the distribution is a set of C++ wrapper functions, and a
+just-in-time compiler that can be used to optimize pattern matching. These
+are both optional features that can be omitted when the library is built.
+
+
+THE BASIC LIBRARY FUNCTIONS
+---------------------------
+
+Written by:       Philip Hazel
+Email local part: ph10
+Email domain:     cam.ac.uk
+
+University of Cambridge Computing Service,
+Cambridge, England.
+
+Copyright (c) 1997-2012 University of Cambridge
+All rights reserved.
+
+
+PCRE JUST-IN-TIME COMPILATION SUPPORT
+-------------------------------------
+
+Written by:       Zoltan Herczeg
+Email local part: hzmester
+Emain domain:     freemail.hu
+
+Copyright(c) 2010-2012 Zoltan Herczeg
+All rights reserved.
+
+
+STACK-LESS JUST-IN-TIME COMPILER
+--------------------------------
+
+Written by:       Zoltan Herczeg
+Email local part: hzmester
+Emain domain:     freemail.hu
+
+Copyright(c) 2009-2012 Zoltan Herczeg
+All rights reserved.
+
+
+THE C++ WRAPPER FUNCTIONS
+-------------------------
+
+Contributed by:   Google Inc.
+
+Copyright (c) 2007-2012, Google Inc.
+All rights reserved.
+
+
+THE "BSD" LICENCE
+-----------------
+
+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 name of Google
+      Inc. nor the names of their 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.
+
+End
diff --git a/src/3rdparty/pcre/pcre.h b/src/3rdparty/pcre/pcre.h
new file mode 100644 (file)
index 0000000..712bd3d
--- /dev/null
@@ -0,0 +1,503 @@
+/*************************************************
+*       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-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_H
+#define _PCRE_H
+
+/* The current PCRE version information. */
+
+#define PCRE_MAJOR          8
+#define PCRE_MINOR          30
+#define PCRE_PRERELEASE     
+#define PCRE_DATE           2012-02-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
+
+/* Options. Some are compile-time only, some are run-time only, and some are
+both, so we keep them all distinct. However, almost all the bits in the options
+word are now used. In the long run, we may have to re-use some of the
+compile-time only bits for runtime options, or vice versa. In the comments
+below, "compile", "exec", and "DFA exec" mean that the option is permitted to
+be set for those functions; "used in" means that an option may be set only for
+compile, but is subsequently referenced in exec and/or DFA exec. Any of the
+compile-time options may be inspected during studying (and therefore JIT
+compiling). */
+
+#define PCRE_CASELESS           0x00000001  /* Compile */
+#define PCRE_MULTILINE          0x00000002  /* Compile */
+#define PCRE_DOTALL             0x00000004  /* Compile */
+#define PCRE_EXTENDED           0x00000008  /* Compile */
+#define PCRE_ANCHORED           0x00000010  /* Compile, exec, DFA exec */
+#define PCRE_DOLLAR_ENDONLY     0x00000020  /* Compile, used in exec, DFA exec */
+#define PCRE_EXTRA              0x00000040  /* Compile */
+#define PCRE_NOTBOL             0x00000080  /* Exec, DFA exec */
+#define PCRE_NOTEOL             0x00000100  /* Exec, DFA exec */
+#define PCRE_UNGREEDY           0x00000200  /* Compile */
+#define PCRE_NOTEMPTY           0x00000400  /* Exec, DFA exec */
+/* The next two are also used in exec and DFA exec */
+#define PCRE_UTF8               0x00000800  /* Compile (same as PCRE_UTF16) */
+#define PCRE_UTF16              0x00000800  /* Compile (same as PCRE_UTF8) */
+#define PCRE_NO_AUTO_CAPTURE    0x00001000  /* Compile */
+/* The next two are also used in exec and DFA exec */
+#define PCRE_NO_UTF8_CHECK      0x00002000  /* Compile (same as PCRE_NO_UTF16_CHECK) */
+#define PCRE_NO_UTF16_CHECK     0x00002000  /* Compile (same as PCRE_NO_UTF8_CHECK) */
+#define PCRE_AUTO_CALLOUT       0x00004000  /* Compile */
+#define PCRE_PARTIAL_SOFT       0x00008000  /* Exec, DFA exec */
+#define PCRE_PARTIAL            0x00008000  /* Backwards compatible synonym */
+#define PCRE_DFA_SHORTEST       0x00010000  /* DFA exec */
+#define PCRE_DFA_RESTART        0x00020000  /* DFA exec */
+#define PCRE_FIRSTLINE          0x00040000  /* Compile, used in exec, DFA exec */
+#define PCRE_DUPNAMES           0x00080000  /* Compile */
+#define PCRE_NEWLINE_CR         0x00100000  /* Compile, exec, DFA exec */
+#define PCRE_NEWLINE_LF         0x00200000  /* Compile, exec, DFA exec */
+#define PCRE_NEWLINE_CRLF       0x00300000  /* Compile, exec, DFA exec */
+#define PCRE_NEWLINE_ANY        0x00400000  /* Compile, exec, DFA exec */
+#define PCRE_NEWLINE_ANYCRLF    0x00500000  /* Compile, exec, DFA exec */
+#define PCRE_BSR_ANYCRLF        0x00800000  /* Compile, exec, DFA exec */
+#define PCRE_BSR_UNICODE        0x01000000  /* Compile, exec, DFA exec */
+#define PCRE_JAVASCRIPT_COMPAT  0x02000000  /* Compile, used in exec */
+#define PCRE_NO_START_OPTIMIZE  0x04000000  /* Compile, exec, DFA exec */
+#define PCRE_NO_START_OPTIMISE  0x04000000  /* Synonym */
+#define PCRE_PARTIAL_HARD       0x08000000  /* Exec, DFA exec */
+#define PCRE_NOTEMPTY_ATSTART   0x10000000  /* Exec, DFA exec */
+#define PCRE_UCP                0x20000000  /* Compile, used in exec, DFA exec */
+
+/* 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 */
+#define PCRE_ERROR_BADUTF16        (-10)  /* Same for 8/16 */
+#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)
+
+/* 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
+
+/* 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
+
+/* 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
+
+/* 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
+
+/* Request types for pcre_study(). Do not re-arrange, in order to remain
+compatible. */
+
+#define PCRE_STUDY_JIT_COMPILE            0x0001
+
+/* Bit flags for the pcre[16]_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_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;
+
+/* 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
+
+/* 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;
+
+/* 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;
+
+/* 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 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 *);
+#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 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 *);
+#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 *);
+
+/* 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 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 int  pcre_config(int, void *);
+PCRE_EXP_DECL int  pcre16_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  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  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  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 void pcre_free_substring(const char *);
+PCRE_EXP_DECL void pcre16_free_substring(PCRE_SPTR16);
+PCRE_EXP_DECL void pcre_free_substring_list(const char **);
+PCRE_EXP_DECL void pcre16_free_substring_list(PCRE_SPTR16 *);
+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  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  pcre_get_stringnumber(const pcre *, const char *);
+PCRE_EXP_DECL int  pcre16_get_stringnumber(const pcre16 *, PCRE_SPTR16);
+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  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  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 const unsigned char *pcre_maketables(void);
+PCRE_EXP_DECL const unsigned char *pcre16_maketables(void);
+PCRE_EXP_DECL int  pcre_refcount(pcre *, int);
+PCRE_EXP_DECL int  pcre16_refcount(pcre16 *, 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 void pcre_free_study(pcre_extra *);
+PCRE_EXP_DECL void pcre16_free_study(pcre16_extra *);
+PCRE_EXP_DECL const char *pcre_version(void);
+PCRE_EXP_DECL const char *pcre16_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  pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *,
+                  PCRE_SPTR16, 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 void pcre_jit_stack_free(pcre_jit_stack *);
+PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_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 *);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif /* End of pcre.h */
diff --git a/src/3rdparty/pcre/pcre16_byte_order.c b/src/3rdparty/pcre/pcre16_byte_order.c
new file mode 100644 (file)
index 0000000..11d2973
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_chartables.c b/src/3rdparty/pcre/pcre16_chartables.c
new file mode 100644 (file)
index 0000000..7c0ff35
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_compile.c b/src/3rdparty/pcre/pcre16_compile.c
new file mode 100644 (file)
index 0000000..e499b67
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_config.c b/src/3rdparty/pcre/pcre16_config.c
new file mode 100644 (file)
index 0000000..b521387
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_dfa_exec.c b/src/3rdparty/pcre/pcre16_dfa_exec.c
new file mode 100644 (file)
index 0000000..2ba740e
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_exec.c b/src/3rdparty/pcre/pcre16_exec.c
new file mode 100644 (file)
index 0000000..7417b17
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_fullinfo.c b/src/3rdparty/pcre/pcre16_fullinfo.c
new file mode 100644 (file)
index 0000000..544dca6
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_get.c b/src/3rdparty/pcre/pcre16_get.c
new file mode 100644 (file)
index 0000000..3ded08c
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_globals.c b/src/3rdparty/pcre/pcre16_globals.c
new file mode 100644 (file)
index 0000000..a136b3d
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_jit_compile.c b/src/3rdparty/pcre/pcre16_jit_compile.c
new file mode 100644 (file)
index 0000000..ab0cacd
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_maketables.c b/src/3rdparty/pcre/pcre16_maketables.c
new file mode 100644 (file)
index 0000000..b1cd1c5
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_newline.c b/src/3rdparty/pcre/pcre16_newline.c
new file mode 100644 (file)
index 0000000..7fe2014
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_ord2utf16.c b/src/3rdparty/pcre/pcre16_ord2utf16.c
new file mode 100644 (file)
index 0000000..9f7db86
--- /dev/null
@@ -0,0 +1,95 @@
+/*************************************************
+*      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 PCRE_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
+*/
+
+int
+PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer)
+{
+#ifdef SUPPORT_UTF
+
+/* Checking invalid cvalue character, encoded as invalid UTF-16 character.
+Should never happen in practice. */
+if ((cvalue & 0xf800) == 0xd800 || cvalue >= 0x110000)
+  cvalue = 0xfffe;
+
+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/src/3rdparty/pcre/pcre16_refcount.c b/src/3rdparty/pcre/pcre16_refcount.c
new file mode 100644 (file)
index 0000000..d3d1543
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_string_utils.c b/src/3rdparty/pcre/pcre16_string_utils.c
new file mode 100644 (file)
index 0000000..382c407
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_study.c b/src/3rdparty/pcre/pcre16_study.c
new file mode 100644 (file)
index 0000000..f87de08
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_tables.c b/src/3rdparty/pcre/pcre16_tables.c
new file mode 100644 (file)
index 0000000..d842970
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_ucd.c b/src/3rdparty/pcre/pcre16_ucd.c
new file mode 100644 (file)
index 0000000..ee23439
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_utf16_utils.c b/src/3rdparty/pcre/pcre16_utf16_utils.c
new file mode 100644 (file)
index 0000000..7cfdbdd
--- /dev/null
@@ -0,0 +1,129 @@
+/*************************************************
+*      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 PCRE_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 /* SUPPORT_UTF */
+(void)(output);  /* Keep picky compilers happy */
+(void)(input);
+(void)(keep_boms);
+#endif /* SUPPORT_UTF */
+return length;
+}
+
+/* End of pcre16_utf16_utils.c */
diff --git a/src/3rdparty/pcre/pcre16_valid_utf16.c b/src/3rdparty/pcre/pcre16_valid_utf16.c
new file mode 100644 (file)
index 0000000..90b9f86
--- /dev/null
@@ -0,0 +1,146 @@
+/*************************************************
+*      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 an internal function for validating UTF-16 character
+strings. */
+
+
+#ifdef PCRE_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  Not allowed 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_uchar 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. */
+
+    /* This is probably a BOM from a different byte-order.
+    Regardless, the string is rejected. */
+    if (c == 0xfffe)
+      {
+      *erroroffset = p - string;
+      return PCRE_UTF16_ERR4;
+      }
+    }
+  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);
+#endif /* SUPPORT_UTF */
+
+return PCRE_UTF16_ERR0;   /* This indicates success */
+}
+
+/* End of pcre16_valid_utf16.c */
diff --git a/src/3rdparty/pcre/pcre16_version.c b/src/3rdparty/pcre/pcre16_version.c
new file mode 100644 (file)
index 0000000..e991b1a
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre16_xclass.c b/src/3rdparty/pcre/pcre16_xclass.c
new file mode 100644 (file)
index 0000000..5aac2a3
--- /dev/null
@@ -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/src/3rdparty/pcre/pcre_byte_order.c b/src/3rdparty/pcre/pcre_byte_order.c
new file mode 100644 (file)
index 0000000..6f5fa74
--- /dev/null
@@ -0,0 +1,288 @@
+/*************************************************
+*      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 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 PCRE_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
+*/
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *argument_re,
+  pcre_extra *extra_data, const unsigned char *tables)
+#else
+PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *argument_re,
+  pcre16_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;
+#ifdef SUPPORT_UTF
+BOOL utf;
+BOOL utf16_char;
+#endif /* SUPPORT_UTF */
+#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_uint16(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_uint16(re->flags);
+re->top_bracket = swap_uint16(re->top_bracket);
+re->top_backref = swap_uint16(re->top_backref);
+re->first_char = swap_uint16(re->first_char);
+re->req_char = swap_uint16(re->req_char);
+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;
+#ifdef SUPPORT_UTF
+utf = (re->options & PCRE_UTF16) != 0;
+utf16_char = FALSE;
+#endif
+
+while(TRUE)
+  {
+  /* Swap previous characters. */
+  while (length-- > 0)
+    {
+    *ptr = swap_uint16(*ptr);
+    ptr++;
+    }
+#ifdef SUPPORT_UTF
+  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;
+  *ptr = swap_uint16(*ptr);
+  switch (*ptr)
+    {
+    case OP_END:
+    return 0;
+
+#ifdef SUPPORT_UTF
+    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++;
+    *ptr = swap_uint16(*ptr);
+    if (LINK_SIZE > 1)
+      {
+      /* LINK_SIZE can be 1 or 2 in 16 bit mode. */
+      ptr++;
+      *ptr = swap_uint16(*ptr);
+      }
+    ptr++;
+    length = (GET(ptr, -LINK_SIZE)) - (1 + LINK_SIZE + 1);
+    *ptr = swap_uint16(*ptr);
+    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 bit mode. */
+#endif /* !COMPILE_PCRE8 */
+
+return 0;
+}
+
+/* End of pcre_byte_order.c */
diff --git a/src/3rdparty/pcre/pcre_chartables.c b/src/3rdparty/pcre/pcre_chartables.c
new file mode 100644 (file)
index 0000000..55df497
--- /dev/null
@@ -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 PCRE_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,0x00,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/src/3rdparty/pcre/pcre_compile.c b/src/3rdparty/pcre/pcre_compile.c
new file mode 100644 (file)
index 0000000..b0c57ca
--- /dev/null
@@ -0,0 +1,8162 @@
+/*************************************************
+*      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_compile(), along with
+supporting internal functions that are not used by other modules. */
+
+
+#ifdef PCRE_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)_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%8))
+
+/* 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)
+
+
+/*************************************************
+*      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)
+
+/* 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   0x10000000l      /* Indicates caselessness */
+#define REQ_VARY       0x20000000l      /* Reqchar followed non-literal item */
+
+/* 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);
+
+
+/* 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. */
+
+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 };
+
+/* 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. The POSIX class
+substitutes must be in the order of the names, defined above, and there are
+both positive and negative cases. NULL means no substitute. */
+
+#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 */       /* NOTE: Xsp is Perl space */
+  string_pXsp,          /* \s */
+  string_PXwd,          /* \W */
+  string_pXwd           /* \w */
+};
+
+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 */    /* NOTE: Xps is POSIX space */
+  string_pXwd,          /* word */
+  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 */   /* NOTE: Xps is POSIX space */
+  string_PXwd,          /* ^word */
+  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{...} sequence 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\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"
+  ;
+
+/* 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
+
+
+/* Definition to allow mutual recursion */
+
+static BOOL
+  compile_regex(int, pcre_uchar **, const pcre_uchar **, int *, BOOL, BOOL, int, int,
+    int *, int *, branch_chain *, compile_data *, int *);
+
+
+
+/*************************************************
+*            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++ != 0) {};
+  if (*s == 0) 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 a negative value which
+encodes one of the more complicated things such as \d. A backreference to group
+n is returned as -(ESC_REF + n); ESC_REF is the highest ESC_xxx macro. When
+UTF-8 is enabled, a positive value greater than 255 may be returned. 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
+  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 or positive => a data character
+                 negative => a special escape sequence
+                 on error, errorcodeptr is set
+*/
+
+static int
+check_escape(const pcre_uchar **ptrptr, 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_int32 c;
+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 == 0) *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) c = i;
+
+#else           /* EBCDIC coding */
+/* Not alphanumeric */
+else if (c < 'a' || (!MAX_255(c) || (ebcdic_chartab[c] & 0x0E) == 0)) {}
+else if ((i = escapes[c - 0x48]) != 0)  c = i;
+#endif
+
+/* Escapes that need further processing, or are illegal. */
+
+else
+  {
+  const pcre_uchar *oldptr;
+  BOOL braced, negated;
+
+  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 int 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
+          }
+        }
+      }
+    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)
+      {
+      c = -ESC_g;
+      break;
+      }
+
+    /* Handle the Perl-compatible cases */
+
+    if (ptr[1] == CHAR_LEFT_CURLY_BRACKET)
+      {
+      const pcre_uchar *p;
+      for (p = ptr+2; *p != 0 && *p != CHAR_RIGHT_CURLY_BRACKET; p++)
+        if (*p != CHAR_MINUS && !IS_DIGIT(*p)) break;
+      if (*p != 0 && *p != CHAR_RIGHT_CURLY_BRACKET)
+        {
+        c = -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. */
+    c = 0;
+    while (IS_DIGIT(ptr[1]))
+      {
+      if (((unsigned int)c) > INT_MAX / 10) /* Integer overflow */
+        {
+        c = -1;
+        break;
+        }
+      c = c * 10 + *(++ptr) - CHAR_0;
+      }
+    if (((unsigned int)c) > INT_MAX) /* Integer overflow */
+      {
+      while (IS_DIGIT(ptr[1]))
+        ptr++;
+      *errorcodeptr = ERR61;
+      break;
+      }
+
+    if (braced && *(++ptr) != CHAR_RIGHT_CURLY_BRACKET)
+      {
+      *errorcodeptr = ERR57;
+      break;
+      }
+
+    if (c == 0)
+      {
+      *errorcodeptr = ERR58;
+      break;
+      }
+
+    if (negated)
+      {
+      if (c > bracount)
+        {
+        *errorcodeptr = ERR15;
+        break;
+        }
+      c = bracount - (c - 1);
+      }
+
+    c = -(ESC_REF + c);
+    break;
+
+    /* The handling of escape sequences consisting of a string of digits
+    starting with one that is not zero is not straightforward. By experiment,
+    the way Perl works seems to be as follows:
+
+    Outside a character class, the digits are read as a decimal number. If the
+    number is less than 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. Inside a
+    character class, \ followed by a digit is always 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. */
+      c -= CHAR_0;
+      while (IS_DIGIT(ptr[1]))
+        {
+        if (((unsigned int)c) > INT_MAX / 10) /* Integer overflow */
+          {
+          c = -1;
+          break;
+          }
+        c = c * 10 + *(++ptr) - CHAR_0;
+        }
+      if (((unsigned int)c) > INT_MAX) /* Integer overflow */
+        {
+        while (IS_DIGIT(ptr[1]))
+          ptr++;
+        *errorcodeptr = ERR61;
+        break;
+        }
+      if (c < 10 || c <= bracount)
+        {
+        c = -(ESC_REF + c);
+        break;
+        }
+      ptr = oldptr;      /* Put the pointer back and fall through */
+      }
+
+    /* Handle an octal number following \. If the first digit is 8 or 9, Perl
+    generates a binary zero byte and treats the digit as a following literal.
+    Thus we have to pull back the pointer by one. */
+
+    if ((c = *ptr) >= CHAR_8)
+      {
+      ptr--;
+      c = 0;
+      break;
+      }
+
+    /* \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;
+
+    /* \x is complicated. \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, { is treated as a data character. */
+
+    case CHAR_x:
+    if ((options & PCRE_JAVASCRIPT_COMPAT) != 0)
+      {
+      /* In JavaScript, \x must be followed by two hexadecimal numbers.
+      Otherwise it is a lowercase x letter. */
+      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 int 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
+          }
+        }
+      break;
+      }
+
+    if (ptr[1] == CHAR_LEFT_CURLY_BRACKET)
+      {
+      const pcre_uchar *pt = ptr + 2;
+
+      c = 0;
+      while (MAX_255(*pt) && (digitab[*pt] & ctype_xdigit) != 0)
+        {
+        register int cc = *pt++;
+        if (c == 0 && cc == CHAR_0) continue;     /* Leading zeroes */
+
+#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
+
+#ifdef COMPILE_PCRE8
+        if (c > (utf ? 0x10ffff : 0xff)) { c = -1; break; }
+#else
+#ifdef COMPILE_PCRE16
+        if (c > (utf ? 0x10ffff : 0xffff)) { c = -1; break; }
+#endif
+#endif
+        }
+
+      if (c < 0)
+        {
+        while (MAX_255(*pt) && (digitab[*pt] & ctype_xdigit) != 0) pt++;
+        *errorcodeptr = ERR34;
+        }
+
+      if (*pt == CHAR_RIGHT_CURLY_BRACKET)
+        {
+        if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73;
+        ptr = pt;
+        break;
+        }
+
+      /* If the sequence of hex digits does not end with '}', then we don't
+      recognize this construct; fall through to the normal \x handling. */
+      }
+
+    /* Read just a single-byte hex-defined char */
+
+    c = 0;
+    while (i++ < 2 && MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0)
+      {
+      int 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
+      }
+    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 == 0)
+      {
+      *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 (c == -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 && c <= -ESC_D && c >= -ESC_w)
+  c -= (ESC_DU - ESC_D);
+
+/* Set the pointer to the final character before returning. */
+
+*ptrptr = ptr;
+return c;
+}
+
+
+
+#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
+  dptr           points to an int that is set to the detailed property value
+  errorcodeptr   points to the error code variable
+
+Returns:         type value from ucp_type_table, or -1 for an invalid type
+*/
+
+static int
+get_ucp(const pcre_uchar **ptrptr, BOOL *negptr, int *dptr, int *errorcodeptr)
+{
+int c, i, bot, top;
+const pcre_uchar *ptr = *ptrptr;
+pcre_uchar name[32];
+
+c = *(++ptr);
+if (c == 0) 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 == 0) 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)
+  {
+  i = (bot + top) >> 1;
+  c = STRCMP_UC_C8(name, PRIV(utt_names) + PRIV(utt)[i].name_offset);
+  if (c == 0)
+    {
+    *dptr = PRIV(utt)[i].value;
+    return PRIV(utt)[i].type;
+    }
+  if (c > 0) bot = i + 1; else top = i;
+  }
+
+*errorcodeptr = ERR47;
+*ptrptr = ptr;
+return -1;
+
+ERROR_RETURN:
+*errorcodeptr = ERR46;
+*ptrptr = ptr;
+return -1;
+}
+#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 + *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 + *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;
+}
+
+
+
+/*************************************************
+*  Subroutine for finding forward reference      *
+*************************************************/
+
+/* This recursive function is called only from find_parens() below. The
+top-level call starts at the beginning of the pattern. All other calls must
+start at a parenthesis. It scans along a pattern's text looking for capturing
+subpatterns, and counting them. If it finds a named pattern that matches the
+name it is given, it returns its number. Alternatively, if the name is NULL, it
+returns when it reaches a given numbered subpattern. Recursion is used to keep
+track of subpatterns that reset the capturing group numbers - the (?| feature.
+
+This function was originally called only from the second pass, in which we know
+that if (?< or (?' or (?P< is encountered, the name will be correctly
+terminated because that is checked in the first pass. There is now one call to
+this function in the first pass, to check for a recursive back reference by
+name (so that we can make the whole group atomic). In this case, we need check
+only up to the current position in the pattern, and that is still OK because
+and previous occurrences will have been checked. To make this work, the test
+for "end of pattern" is a check against cd->end_pattern in the main loop,
+instead of looking for a binary zero. This means that the special first-pass
+call can adjust cd->end_pattern temporarily. (Checks for binary zero while
+processing items within the loop are OK, because afterwards the main loop will
+terminate.)
+
+Arguments:
+  ptrptr       address of the current character pointer (updated)
+  cd           compile background data
+  name         name to seek, or NULL if seeking a numbered subpattern
+  lorn         name length, or subpattern number if name is NULL
+  xmode        TRUE if we are in /x mode
+  utf          TRUE if we are in UTF-8 / UTF-16 mode
+  count        pointer to the current capturing subpattern number (updated)
+
+Returns:       the number of the named subpattern, or -1 if not found
+*/
+
+static int
+find_parens_sub(pcre_uchar **ptrptr, compile_data *cd, const pcre_uchar *name, int lorn,
+  BOOL xmode, BOOL utf, int *count)
+{
+pcre_uchar *ptr = *ptrptr;
+int start_count = *count;
+int hwm_count = start_count;
+BOOL dup_parens = FALSE;
+
+/* If the first character is a parenthesis, check on the type of group we are
+dealing with. The very first call may not start with a parenthesis. */
+
+if (ptr[0] == CHAR_LEFT_PARENTHESIS)
+  {
+  /* Handle specials such as (*SKIP) or (*UTF8) etc. */
+
+  if (ptr[1] == CHAR_ASTERISK) ptr += 2;
+
+  /* Handle a normal, unnamed capturing parenthesis. */
+
+  else if (ptr[1] != CHAR_QUESTION_MARK)
+    {
+    *count += 1;
+    if (name == NULL && *count == lorn) return *count;
+    ptr++;
+    }
+
+  /* All cases now have (? at the start. Remember when we are in a group
+  where the parenthesis numbers are duplicated. */
+
+  else if (ptr[2] == CHAR_VERTICAL_LINE)
+    {
+    ptr += 3;
+    dup_parens = TRUE;
+    }
+
+  /* Handle comments; all characters are allowed until a ket is reached. */
+
+  else if (ptr[2] == CHAR_NUMBER_SIGN)
+    {
+    for (ptr += 3; *ptr != 0; ptr++) if (*ptr == CHAR_RIGHT_PARENTHESIS) break;
+    goto FAIL_EXIT;
+    }
+
+  /* Handle a condition. If it is an assertion, just carry on so that it
+  is processed as normal. If not, skip to the closing parenthesis of the
+  condition (there can't be any nested parens). */
+
+  else if (ptr[2] == CHAR_LEFT_PARENTHESIS)
+    {
+    ptr += 2;
+    if (ptr[1] != CHAR_QUESTION_MARK)
+      {
+      while (*ptr != 0 && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
+      if (*ptr != 0) ptr++;
+      }
+    }
+
+  /* Start with (? but not a condition. */
+
+  else
+    {
+    ptr += 2;
+    if (*ptr == CHAR_P) ptr++;                      /* Allow optional P */
+
+    /* We have to disambiguate (?<! and (?<= from (?<name> for named groups */
+
+    if ((*ptr == CHAR_LESS_THAN_SIGN && ptr[1] != CHAR_EXCLAMATION_MARK &&
+        ptr[1] != CHAR_EQUALS_SIGN) || *ptr == CHAR_APOSTROPHE)
+      {
+      int term;
+      const pcre_uchar *thisname;
+      *count += 1;
+      if (name == NULL && *count == lorn) return *count;
+      term = *ptr++;
+      if (term == CHAR_LESS_THAN_SIGN) term = CHAR_GREATER_THAN_SIGN;
+      thisname = ptr;
+      while (*ptr != term) ptr++;
+      if (name != NULL && lorn == ptr - thisname &&
+          STRNCMP_UC_UC(name, thisname, lorn) == 0)
+        return *count;
+      term++;
+      }
+    }
+  }
+
+/* Past any initial parenthesis handling, scan for parentheses or vertical
+bars. Stop if we get to cd->end_pattern. Note that this is important for the
+first-pass call when this value is temporarily adjusted to stop at the current
+position. So DO NOT change this to a test for binary zero. */
+
+for (; ptr < cd->end_pattern; ptr++)
+  {
+  /* Skip over backslashed characters and also entire \Q...\E */
+
+  if (*ptr == CHAR_BACKSLASH)
+    {
+    if (*(++ptr) == 0) goto FAIL_EXIT;
+    if (*ptr == CHAR_Q) for (;;)
+      {
+      while (*(++ptr) != 0 && *ptr != CHAR_BACKSLASH) {};
+      if (*ptr == 0) goto FAIL_EXIT;
+      if (*(++ptr) == CHAR_E) break;
+      }
+    continue;
+    }
+
+  /* Skip over character classes; this logic must be similar to the way they
+  are handled for real. If the first character is '^', 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. Note the use of STR macros to
+  encode "Q\\E" so that it works in UTF-8 on EBCDIC platforms. */
+
+  if (*ptr == CHAR_LEFT_SQUARE_BRACKET)
+    {
+    BOOL negate_class = FALSE;
+    for (;;)
+      {
+      if (ptr[1] == CHAR_BACKSLASH)
+        {
+        if (ptr[2] == CHAR_E)
+          ptr+= 2;
+        else if (STRNCMP_UC_C8(ptr + 2,
+                 STR_Q STR_BACKSLASH STR_E, 3) == 0)
+          ptr += 4;
+        else
+          break;
+        }
+      else if (!negate_class && ptr[1] == CHAR_CIRCUMFLEX_ACCENT)
+        {
+        negate_class = TRUE;
+        ptr++;
+        }
+      else break;
+      }
+
+    /* If the next character is ']', it is a data character that must be
+    skipped, except in JavaScript compatibility mode. */
+
+    if (ptr[1] == CHAR_RIGHT_SQUARE_BRACKET &&
+        (cd->external_options & PCRE_JAVASCRIPT_COMPAT) == 0)
+      ptr++;
+
+    while (*(++ptr) != CHAR_RIGHT_SQUARE_BRACKET)
+      {
+      if (*ptr == 0) return -1;
+      if (*ptr == CHAR_BACKSLASH)
+        {
+        if (*(++ptr) == 0) goto FAIL_EXIT;
+        if (*ptr == CHAR_Q) for (;;)
+          {
+          while (*(++ptr) != 0 && *ptr != CHAR_BACKSLASH) {};
+          if (*ptr == 0) goto FAIL_EXIT;
+          if (*(++ptr) == CHAR_E) break;
+          }
+        continue;
+        }
+      }
+    continue;
+    }
+
+  /* Skip comments in /x mode */
+
+  if (xmode && *ptr == CHAR_NUMBER_SIGN)
+    {
+    ptr++;
+    while (*ptr != 0)
+      {
+      if (IS_NEWLINE(ptr)) { ptr += cd->nllen - 1; break; }
+      ptr++;
+#ifdef SUPPORT_UTF
+      if (utf) FORWARDCHAR(ptr);
+#endif
+      }
+    if (*ptr == 0) goto FAIL_EXIT;
+    continue;
+    }
+
+  /* Check for the special metacharacters */
+
+  if (*ptr == CHAR_LEFT_PARENTHESIS)
+    {
+    int rc = find_parens_sub(&ptr, cd, name, lorn, xmode, utf, count);
+    if (rc > 0) return rc;
+    if (*ptr == 0) goto FAIL_EXIT;
+    }
+
+  else if (*ptr == CHAR_RIGHT_PARENTHESIS)
+    {
+    if (dup_parens && *count < hwm_count) *count = hwm_count;
+    goto FAIL_EXIT;
+    }
+
+  else if (*ptr == CHAR_VERTICAL_LINE && dup_parens)
+    {
+    if (*count > hwm_count) hwm_count = *count;
+    *count = start_count;
+    }
+  }
+
+FAIL_EXIT:
+*ptrptr = ptr;
+return -1;
+}
+
+
+
+
+/*************************************************
+*       Find forward referenced subpattern       *
+*************************************************/
+
+/* This function scans along a pattern's text looking for capturing
+subpatterns, and counting them. If it finds a named pattern that matches the
+name it is given, it returns its number. Alternatively, if the name is NULL, it
+returns when it reaches a given numbered subpattern. This is used for forward
+references to subpatterns. We used to be able to start this scan from the
+current compiling point, using the current count value from cd->bracount, and
+do it all in a single loop, but the addition of the possibility of duplicate
+subpattern numbers means that we have to scan from the very start, in order to
+take account of such duplicates, and to use a recursive function to keep track
+of the different types of group.
+
+Arguments:
+  cd           compile background data
+  name         name to seek, or NULL if seeking a numbered subpattern
+  lorn         name length, or subpattern number if name is NULL
+  xmode        TRUE if we are in /x mode
+  utf          TRUE if we are in UTF-8 / UTF-16 mode
+
+Returns:       the number of the found subpattern, or -1 if not found
+*/
+
+static int
+find_parens(compile_data *cd, const pcre_uchar *name, int lorn, BOOL xmode,
+  BOOL utf)
+{
+pcre_uchar *ptr = (pcre_uchar *)cd->start_pattern;
+int count = 0;
+int rc;
+
+/* If the pattern does not start with an opening parenthesis, the first call
+to find_parens_sub() will scan right to the end (if necessary). However, if it
+does start with a parenthesis, find_parens_sub() will return when it hits the
+matching closing parens. That is why we have to have a loop. */
+
+for (;;)
+  {
+  rc = find_parens_sub(&ptr, cd, name, lorn, xmode, utf, &count);
+  if (rc > 0 || *ptr++ == 0) break;
+  }
+
+return rc;
+}
+
+
+
+
+/*************************************************
+*      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_NCREF:
+    case OP_RREF:
+    case OP_NRREF:
+    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 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 int 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_DOLL:
+    case OP_DOLLM:
+    case OP_EOD:
+    case OP_EODN:
+    case OP_FAIL:
+    case OP_NCREF:
+    case OP_NRREF:
+    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 += 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 */
+
+#if defined SUPPORT_UTF || defined COMPILE_PCRE16
+    case OP_XCLASS:
+    cc += GET(cc, 1) - PRIV(OP_lengths)[OP_CLASS];
+    /* Fall through */
+#endif
+
+    case OP_CLASS:
+    case OP_NCLASS:
+    cc += PRIV(OP_lengths)[OP_CLASS];
+
+    switch (*cc)
+      {
+      case OP_CRPLUS:
+      case OP_CRMINPLUS:
+      case OP_CRSTAR:
+      case OP_CRMINSTAR:
+      case OP_CRQUERY:
+      case OP_CRMINQUERY:
+      return -1;
+
+      case OP_CRRANGE:
+      case OP_CRMINRANGE:
+      if (GET2(cc,1) != GET2(cc,1+IMM2_SIZE)) return -1;
+      branchlength += 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_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 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 int 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 = 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:
+      code += code[1];
+      break;
+
+      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. */
+
+#ifdef SUPPORT_UTF
+    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 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 int 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:
+      code += code[1];
+      break;
+
+      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. */
+
+#ifdef SUPPORT_UTF
+    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 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 mode
+  cd          contains pointers to tables etc.
+
+Returns:      TRUE if what is matched could be empty
+*/
+
+static BOOL
+could_be_empty_branch(const pcre_uchar *code, const pcre_uchar *endcode,
+  BOOL utf, compile_data *cd)
+{
+register int c;
+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;
+    BOOL empty_branch;
+
+    /* Test for forward reference */
+
+    for (scode = cd->start_workspace; scode < cd->hwm; scode += LINK_SIZE)
+      if (GET(scode, 0) == code + 1 - cd->start_code) return TRUE;
+
+    /* Not a forward reference, test for completed backward reference */
+
+    empty_branch = FALSE;
+    scode = cd->start_code + GET(code, 1);
+    if (GET(scode, 1) == 0) return TRUE;    /* Unclosed */
+
+    /* Completed backwards reference */
+
+    do
+      {
+      if (could_be_empty_branch(scode, endcode, utf, cd))
+        {
+        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))
+          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:
+      break;
+
+      default:                   /* Non-repeat => class must match */
+      case OP_CRPLUS:            /* These repeats aren't empty */
+      case OP_CRMINPLUS:
+      return FALSE;
+
+      case OP_CRRANGE:
+      case OP_CRMINRANGE:
+      if (GET2(ccode, 1) > 0) return FALSE;  /* Minimum > 0 */
+      break;
+      }
+    break;
+
+    /* Opcodes that must match a character */
+
+    case OP_PROP:
+    case OP_NOTPROP:
+    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_ANY:
+    case OP_ALLANY:
+    case OP_ANYBYTE:
+    case OP_CHAR:
+    case OP_CHARI:
+    case OP_NOT:
+    case OP_NOTI:
+    case OP_PLUS:
+    case OP_MINPLUS:
+    case OP_POSPLUS:
+    case OP_EXACT:
+    case OP_NOTPLUS:
+    case OP_NOTMINPLUS:
+    case OP_NOTPOSPLUS:
+    case OP_NOTEXACT:
+    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 may be followed by a multibyte character */
+
+#ifdef SUPPORT_UTF
+    case OP_STAR:
+    case OP_STARI:
+    case OP_MINSTAR:
+    case OP_MINSTARI:
+    case OP_POSSTAR:
+    case OP_POSSTARI:
+    case OP_QUERY:
+    case OP_QUERYI:
+    case OP_MINQUERY:
+    case OP_MINQUERYI:
+    case OP_POSQUERY:
+    case OP_POSQUERYI:
+    if (utf && HAS_EXTRALEN(code[1])) code += GET_EXTRALEN(code[1]);
+    break;
+
+    case OP_UPTO:
+    case OP_UPTOI:
+    case OP_MINUPTO:
+    case OP_MINUPTOI:
+    case OP_POSUPTO:
+    case OP_POSUPTOI:
+    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:
+    code += code[1];
+    break;
+
+    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 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))
+    return FALSE;
+  bcptr = bcptr->outer;
+  }
+return TRUE;
+}
+
+
+
+/*************************************************
+*           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 that 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)
+{
+int terminator;          /* Don't combine these lines; the Solaris cc */
+terminator = *(++ptr);   /* compiler warns about "non-constant" initializer. */
+for (++ptr; *ptr != 0; 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, 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 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 = 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 = 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 internal ranges of
+characters in the "other" case. Each call returns the next one, updating the
+start address.
+
+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:        TRUE when range returned; FALSE when no more
+*/
+
+static BOOL
+get_othercase_range(unsigned int *cptr, unsigned int d, unsigned int *ocptr,
+  unsigned int *odptr)
+{
+unsigned int c, othercase, next;
+
+for (c = *cptr; c <= d; c++)
+  { if ((othercase = UCD_OTHERCASE(c)) != c) break; }
+
+if (c > d) return FALSE;
+
+*ocptr = othercase;
+next = othercase + 1;
+
+for (++c; c <= d; c++)
+  {
+  if (UCD_OTHERCASE(c) != next) break;
+  next++;
+  }
+
+*odptr = next - 1;
+*cptr = c;
+
+return TRUE;
+}
+
+
+
+/*************************************************
+*        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(int c, int ptype, int pdata, BOOL negated)
+{
+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;
+
+  case PT_SPACE:    /* Perl space */
+  return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
+          c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR)
+          == negated;
+
+  case PT_PXSPACE:  /* POSIX space */
+  return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
+          c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
+          c == CHAR_FF || c == CHAR_CR)
+          == negated;
+
+  case PT_WORD:
+  return (PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+          PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
+          c == CHAR_UNDERSCORE) == negated;
+  }
+return FALSE;
+}
+#endif  /* SUPPORT_UCP */
+
+
+
+/*************************************************
+*     Check if auto-possessifying is possible    *
+*************************************************/
+
+/* This function is called for unlimited repeats of certain items, to see
+whether the next thing could possibly match the repeated item. If not, it makes
+sense to automatically possessify the repeated item.
+
+Arguments:
+  previous      pointer to the repeated opcode
+  utf           TRUE in UTF-8 / UTF-16 mode
+  ptr           next character in pattern
+  options       options bits
+  cd            contains pointers to tables etc.
+
+Returns:        TRUE if possessifying is wanted
+*/
+
+static BOOL
+check_auto_possessive(const pcre_uchar *previous, BOOL utf,
+  const pcre_uchar *ptr, int options, compile_data *cd)
+{
+pcre_int32 c, next;
+int op_code = *previous++;
+
+/* Skip whitespace and comments in extended mode */
+
+if ((options & PCRE_EXTENDED) != 0)
+  {
+  for (;;)
+    {
+    while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_space) != 0) ptr++;
+    if (*ptr == CHAR_NUMBER_SIGN)
+      {
+      ptr++;
+      while (*ptr != 0)
+        {
+        if (IS_NEWLINE(ptr)) { ptr += cd->nllen; break; }
+        ptr++;
+#ifdef SUPPORT_UTF
+        if (utf) FORWARDCHAR(ptr);
+#endif
+        }
+      }
+    else break;
+    }
+  }
+
+/* If the next item is one that we can handle, get its value. A non-negative
+value is a character, a negative value is an escape value. */
+
+if (*ptr == CHAR_BACKSLASH)
+  {
+  int temperrorcode = 0;
+  next = check_escape(&ptr, &temperrorcode, cd->bracount, options, FALSE);
+  if (temperrorcode != 0) return FALSE;
+  ptr++;    /* Point after the escape sequence */
+  }
+else if (!MAX_255(*ptr) || (cd->ctypes[*ptr] & ctype_meta) == 0)
+  {
+#ifdef SUPPORT_UTF
+  if (utf) { GETCHARINC(next, ptr); } else
+#endif
+  next = *ptr++;
+  }
+else return FALSE;
+
+/* Skip whitespace and comments in extended mode */
+
+if ((options & PCRE_EXTENDED) != 0)
+  {
+  for (;;)
+    {
+    while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_space) != 0) ptr++;
+    if (*ptr == CHAR_NUMBER_SIGN)
+      {
+      ptr++;
+      while (*ptr != 0)
+        {
+        if (IS_NEWLINE(ptr)) { ptr += cd->nllen; break; }
+        ptr++;
+#ifdef SUPPORT_UTF
+        if (utf) FORWARDCHAR(ptr);
+#endif
+        }
+      }
+    else break;
+    }
+  }
+
+/* If the next thing is itself optional, we have to give up. */
+
+if (*ptr == CHAR_ASTERISK || *ptr == CHAR_QUESTION_MARK ||
+  STRNCMP_UC_C8(ptr, STR_LEFT_CURLY_BRACKET STR_0 STR_COMMA, 3) == 0)
+    return FALSE;
+
+/* Now compare the next item with the previous opcode. First, handle cases when
+the next item is a character. */
+
+if (next >= 0) switch(op_code)
+  {
+  case OP_CHAR:
+#ifdef SUPPORT_UTF
+  GETCHARTEST(c, previous);
+#else
+  c = *previous;
+#endif
+  return c != next;
+
+  /* For CHARI (caseless character) we must check the other case. If we have
+  Unicode property support, we can use it to test the other case of
+  high-valued characters. */
+
+  case OP_CHARI:
+#ifdef SUPPORT_UTF
+  GETCHARTEST(c, previous);
+#else
+  c = *previous;
+#endif
+  if (c == next) return FALSE;
+#ifdef SUPPORT_UTF
+  if (utf)
+    {
+    unsigned int othercase;
+    if (next < 128) othercase = cd->fcc[next]; else
+#ifdef SUPPORT_UCP
+    othercase = UCD_OTHERCASE((unsigned int)next);
+#else
+    othercase = NOTACHAR;
+#endif
+    return (unsigned int)c != othercase;
+    }
+  else
+#endif  /* SUPPORT_UTF */
+  return (c != TABLE_GET((unsigned int)next, cd->fcc, next));  /* Non-UTF-8 mode */
+
+  /* For OP_NOT and OP_NOTI, the data is always a single-byte character. These
+  opcodes are not used for multi-byte characters, because they are coded using
+  an XCLASS instead. */
+
+  case OP_NOT:
+  return (c = *previous) == next;
+
+  case OP_NOTI:
+  if ((c = *previous) == next) return TRUE;
+#ifdef SUPPORT_UTF
+  if (utf)
+    {
+    unsigned int othercase;
+    if (next < 128) othercase = cd->fcc[next]; else
+#ifdef SUPPORT_UCP
+    othercase = UCD_OTHERCASE(next);
+#else
+    othercase = NOTACHAR;
+#endif
+    return (unsigned int)c == othercase;
+    }
+  else
+#endif  /* SUPPORT_UTF */
+  return (c == (int)(TABLE_GET((unsigned int)next, cd->fcc, next)));  /* Non-UTF-8 mode */
+
+  /* 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:
+  return next > 127 || (cd->ctypes[next] & ctype_digit) == 0;
+
+  case OP_NOT_DIGIT:
+  return next <= 127 && (cd->ctypes[next] & ctype_digit) != 0;
+
+  case OP_WHITESPACE:
+  return next > 127 || (cd->ctypes[next] & ctype_space) == 0;
+
+  case OP_NOT_WHITESPACE:
+  return next <= 127 && (cd->ctypes[next] & ctype_space) != 0;
+
+  case OP_WORDCHAR:
+  return next > 127 || (cd->ctypes[next] & ctype_word) == 0;
+
+  case OP_NOT_WORDCHAR:
+  return next <= 127 && (cd->ctypes[next] & ctype_word) != 0;
+
+  case OP_HSPACE:
+  case OP_NOT_HSPACE:
+  switch(next)
+    {
+    case 0x09:
+    case 0x20:
+    case 0xa0:
+    case 0x1680:
+    case 0x180e:
+    case 0x2000:
+    case 0x2001:
+    case 0x2002:
+    case 0x2003:
+    case 0x2004:
+    case 0x2005:
+    case 0x2006:
+    case 0x2007:
+    case 0x2008:
+    case 0x2009:
+    case 0x200A:
+    case 0x202f:
+    case 0x205f:
+    case 0x3000:
+    return op_code == OP_NOT_HSPACE;
+    default:
+    return op_code != OP_NOT_HSPACE;
+    }
+
+  case OP_ANYNL:
+  case OP_VSPACE:
+  case OP_NOT_VSPACE:
+  switch(next)
+    {
+    case 0x0a:
+    case 0x0b:
+    case 0x0c:
+    case 0x0d:
+    case 0x85:
+    case 0x2028:
+    case 0x2029:
+    return op_code == OP_NOT_VSPACE;
+    default:
+    return op_code != OP_NOT_VSPACE;
+    }
+
+#ifdef SUPPORT_UCP
+  case OP_PROP:
+  return check_char_prop(next, previous[0], previous[1], FALSE);
+
+  case OP_NOTPROP:
+  return check_char_prop(next, previous[0], previous[1], TRUE);
+#endif
+
+  default:
+  return FALSE;
+  }
+
+
+/* Handle the case when the next item is \d, \s, etc. Note that when PCRE_UCP
+is set, \d turns into ESC_du rather than ESC_d, etc., so ESC_d etc. are
+generated only when PCRE_UCP is *not* set, that is, when only ASCII
+characteristics are recognized. Similarly, the opcodes OP_DIGIT etc. are
+replaced by OP_PROP codes when PCRE_UCP is set. */
+
+switch(op_code)
+  {
+  case OP_CHAR:
+  case OP_CHARI:
+#ifdef SUPPORT_UTF
+  GETCHARTEST(c, previous);
+#else
+  c = *previous;
+#endif
+  switch(-next)
+    {
+    case ESC_d:
+    return c > 127 || (cd->ctypes[c] & ctype_digit) == 0;
+
+    case ESC_D:
+    return c <= 127 && (cd->ctypes[c] & ctype_digit) != 0;
+
+    case ESC_s:
+    return c > 127 || (cd->ctypes[c] & ctype_space) == 0;
+
+    case ESC_S:
+    return c <= 127 && (cd->ctypes[c] & ctype_space) != 0;
+
+    case ESC_w:
+    return c > 127 || (cd->ctypes[c] & ctype_word) == 0;
+
+    case ESC_W:
+    return c <= 127 && (cd->ctypes[c] & ctype_word) != 0;
+
+    case ESC_h:
+    case ESC_H:
+    switch(c)
+      {
+      case 0x09:
+      case 0x20:
+      case 0xa0:
+      case 0x1680:
+      case 0x180e:
+      case 0x2000:
+      case 0x2001:
+      case 0x2002:
+      case 0x2003:
+      case 0x2004:
+      case 0x2005:
+      case 0x2006:
+      case 0x2007:
+      case 0x2008:
+      case 0x2009:
+      case 0x200A:
+      case 0x202f:
+      case 0x205f:
+      case 0x3000:
+      return -next != ESC_h;
+      default:
+      return -next == ESC_h;
+      }
+
+    case ESC_v:
+    case ESC_V:
+    switch(c)
+      {
+      case 0x0a:
+      case 0x0b:
+      case 0x0c:
+      case 0x0d:
+      case 0x85:
+      case 0x2028:
+      case 0x2029:
+      return -next != ESC_v;
+      default:
+      return -next == ESC_v;
+      }
+
+    /* When PCRE_UCP is set, these values get generated for \d etc. Find
+    their substitutions and process them. The result will always be either
+    -ESC_p or -ESC_P. Then fall through to process those values. */
+
+#ifdef SUPPORT_UCP
+    case ESC_du:
+    case ESC_DU:
+    case ESC_wu:
+    case ESC_WU:
+    case ESC_su:
+    case ESC_SU:
+      {
+      int temperrorcode = 0;
+      ptr = substitutes[-next - ESC_DU];
+      next = check_escape(&ptr, &temperrorcode, 0, options, FALSE);
+      if (temperrorcode != 0) return FALSE;
+      ptr++;    /* For compatibility */
+      }
+    /* Fall through */
+
+    case ESC_p:
+    case ESC_P:
+      {
+      int ptype, pdata, errorcodeptr;
+      BOOL negated;
+
+      ptr--;      /* Make ptr point at the p or P */
+      ptype = get_ucp(&ptr, &negated, &pdata, &errorcodeptr);
+      if (ptype < 0) return FALSE;
+      ptr++;      /* Point past the final curly ket */
+
+      /* If the property item is optional, we have to give up. (When generated
+      from \d etc by PCRE_UCP, this test will have been applied much earlier,
+      to the original \d etc. At this point, ptr will point to a zero byte. */
+
+      if (*ptr == CHAR_ASTERISK || *ptr == CHAR_QUESTION_MARK ||
+        STRNCMP_UC_C8(ptr, STR_LEFT_CURLY_BRACKET STR_0 STR_COMMA, 3) == 0)
+          return FALSE;
+
+      /* Do the property check. */
+
+      return check_char_prop(c, ptype, pdata, (next == -ESC_P) != negated);
+      }
+#endif
+
+    default:
+    return FALSE;
+    }
+
+  /* In principle, support for Unicode properties should be integrated here as
+  well. It means re-organizing the above code so as to get hold of the property
+  values before switching on the op-code. However, I wonder how many patterns
+  combine ASCII \d etc with Unicode properties? (Note that if PCRE_UCP is set,
+  these op-codes are never generated.) */
+
+  case OP_DIGIT:
+  return next == -ESC_D || next == -ESC_s || next == -ESC_W ||
+         next == -ESC_h || next == -ESC_v || next == -ESC_R;
+
+  case OP_NOT_DIGIT:
+  return next == -ESC_d;
+
+  case OP_WHITESPACE:
+  return next == -ESC_S || next == -ESC_d || next == -ESC_w || next == -ESC_R;
+
+  case OP_NOT_WHITESPACE:
+  return next == -ESC_s || next == -ESC_h || next == -ESC_v;
+
+  case OP_HSPACE:
+  return next == -ESC_S || next == -ESC_H || next == -ESC_d ||
+         next == -ESC_w || next == -ESC_v || next == -ESC_R;
+
+  case OP_NOT_HSPACE:
+  return next == -ESC_h;
+
+  /* Can't have \S in here because VT matches \S (Perl anomaly) */
+  case OP_ANYNL:
+  case OP_VSPACE:
+  return next == -ESC_V || next == -ESC_d || next == -ESC_w;
+
+  case OP_NOT_VSPACE:
+  return next == -ESC_v || next == -ESC_R;
+
+  case OP_WORDCHAR:
+  return next == -ESC_W || next == -ESC_s || next == -ESC_h ||
+         next == -ESC_v || next == -ESC_R;
+
+  case OP_NOT_WORDCHAR:
+  return next == -ESC_w || next == -ESC_d;
+
+  default:
+  return FALSE;
+  }
+
+/* Control does not reach here */
+}
+
+
+
+/*************************************************
+*           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   set to initial literal character, or < 0 (REQ_UNSET, REQ_NONE)
+  reqcharptr     set to the last literal character required, else < 0
+  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_int32 *firstcharptr,
+  pcre_int32 *reqcharptr, 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_int32 firstchar, reqchar;
+pcre_int32 zeroreqchar, zerofirstchar;
+pcre_int32 req_caseopt, reqvary, tempreqvary;
+int options = *optionsptr;               /* May change dynamically */
+int after_manual_callout = 0;
+int length_prevgroup = 0;
+register int c;
+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_UTF16 has the same value as PCRE_UTF8. */
+BOOL utf = (options & PCRE_UTF8) != 0;
+pcre_uchar utf_chars[6];
+#else
+BOOL utf = FALSE;
+#endif
+
+/* Helper variables for OP_XCLASS opcode (for characters > 255). */
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+BOOL xclass;
+pcre_uchar *class_uchardata;
+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 = 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_single_char;
+  int newoptions;
+  int recno;
+  int refsign;
+  int skipbytes;
+  int subreqchar;
+  int subfirstchar;
+  int terminator;
+  int mclength;
+  int tempbracount;
+  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 == 0 && 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 != 0)
+    {
+    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;
+      }
+    }
+
+  /* Fill in length of a previous callout, except when 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));
+
+  if (!is_quantifier && previous_callout != NULL &&
+       after_manual_callout-- <= 0)
+    {
+    if (lengthptr == NULL)      /* Don't attempt in pre-compile phase */
+      complete_callout(previous_callout, ptr, cd);
+    previous_callout = NULL;
+    }
+
+  /* In extended mode, skip white space and comments. */
+
+  if ((options & PCRE_EXTENDED) != 0)
+    {
+    if (MAX_255(*ptr) && (cd->ctypes[c] & ctype_space) != 0) continue;
+    if (c == CHAR_NUMBER_SIGN)
+      {
+      ptr++;
+      while (*ptr != 0)
+        {
+        if (IS_NEWLINE(ptr)) { ptr += cd->nllen - 1; break; }
+        ptr++;
+#ifdef SUPPORT_UTF
+        if (utf) FORWARDCHAR(ptr);
+#endif
+        }
+      if (*ptr != 0) continue;
+
+      /* Else fall through to handle end of string */
+      c = 0;
+      }
+    }
+
+  /* No auto callout for quantifiers. */
+
+  if ((options & PCRE_AUTO_CALLOUT) != 0 && !is_quantifier)
+    {
+    previous_callout = code;
+    code = auto_callout(code, ptr, cd);
+    }
+
+  switch(c)
+    {
+    /* ===================================================================*/
+    case 0:                        /* The branch terminates at string end */
+    case CHAR_VERTICAL_LINE:       /* or | or ) */
+    case CHAR_RIGHT_PARENTHESIS:
+    *firstcharptr = firstchar;
+    *reqcharptr = reqchar;
+    *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 (firstchar == REQ_UNSET) firstchar = 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 (firstchar == REQ_UNSET) firstchar = REQ_NONE;
+    zerofirstchar = firstchar;
+    zeroreqchar = reqchar;
+    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;
+
+    case CHAR_LEFT_SQUARE_BRACKET:
+    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 (firstchar == REQ_UNSET) firstchar = REQ_NONE;
+      zerofirstchar = firstchar;
+      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;
+
+    /* 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_single_char will be 1 if the class contains only
+    a single character. */
+
+    class_has_8bitchar = 0;
+    class_single_char = 0;
+
+    /* Initialize the 32-char bit map to all zeros. We build the map in a
+    temporary bit of memory, in case the class contains only 1 character (less
+    than 256), because in that case the compiled code doesn't use the bit map.
+    */
+
+    memset(classbits, 0, 32 * sizeof(pcre_uint8));
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+    xclass = FALSE;                           /* No chars >= 256 */
+    class_uchardata = code + LINK_SIZE + 2;   /* For UTF-8 items */
+    class_uchardata_base = class_uchardata;   /* For resetting in pass 1 */
+#endif
+
+    /* 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 != 0) 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). */
+
+      if (lengthptr != NULL)
+        {
+        *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. */
+
+#ifdef SUPPORT_UCP
+        if ((options & PCRE_UCP) != 0)
+          {
+          int pc = posix_class + ((local_negate)? POSIX_SUBSIZE/2 : 0);
+          if (posix_substitutes[pc] != NULL)
+            {
+            nestptr = tempptr + 1;
+            ptr = posix_substitutes[pc] - 1;
+            continue;
+            }
+          }
+#endif
+        /* In the non-UCP case, 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];
+          }
+
+        /* Not 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 characters. */
+        class_has_8bitchar = 1;
+        /* Every class contains at least two characters. */
+        class_single_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_single_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)
+        {
+        c = check_escape(&ptr, errorcodeptr, cd->bracount, options, TRUE);
+        if (*errorcodeptr != 0) goto FAILED;
+
+        if (-c == ESC_b) c = CHAR_BS;    /* \b is backspace in a class */
+        else if (-c == ESC_N)            /* \N is not supported in a class */
+          {
+          *errorcodeptr = ERR71;
+          goto FAILED;
+          }
+        else if (-c == 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 (-c == ESC_E) continue;  /* Ignore orphan \E */
+
+        if (c < 0)
+          {
+          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_single_char += 2;
+
+          switch (-c)
+            {
+#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[-c - 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 omits VT from \s, but we must preserve it
+            if it was previously set by something earlier in the character
+            class. */
+
+            case ESC_s:
+            classbits[0] |= cbits[cbit_space];
+            classbits[1] |= cbits[cbit_space+1] & ~0x08;
+            for (c = 2; 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];
+            classbits[1] |= 0x08;    /* Perl 5.004 onwards omits VT from \s */
+            continue;
+
+            case ESC_h:
+            SETBIT(classbits, 0x09); /* VT */
+            SETBIT(classbits, 0x20); /* SPACE */
+            SETBIT(classbits, 0xa0); /* NSBP */
+#ifndef COMPILE_PCRE8
+            xclass = TRUE;
+            *class_uchardata++ = XCL_SINGLE;
+            *class_uchardata++ = 0x1680;
+            *class_uchardata++ = XCL_SINGLE;
+            *class_uchardata++ = 0x180e;
+            *class_uchardata++ = XCL_RANGE;
+            *class_uchardata++ = 0x2000;
+            *class_uchardata++ = 0x200a;
+            *class_uchardata++ = XCL_SINGLE;
+            *class_uchardata++ = 0x202f;
+            *class_uchardata++ = XCL_SINGLE;
+            *class_uchardata++ = 0x205f;
+            *class_uchardata++ = XCL_SINGLE;
+            *class_uchardata++ = 0x3000;
+#elif defined SUPPORT_UTF
+            if (utf)
+              {
+              xclass = TRUE;
+              *class_uchardata++ = XCL_SINGLE;
+              class_uchardata += PRIV(ord2utf)(0x1680, class_uchardata);
+              *class_uchardata++ = XCL_SINGLE;
+              class_uchardata += PRIV(ord2utf)(0x180e, class_uchardata);
+              *class_uchardata++ = XCL_RANGE;
+              class_uchardata += PRIV(ord2utf)(0x2000, class_uchardata);
+              class_uchardata += PRIV(ord2utf)(0x200a, class_uchardata);
+              *class_uchardata++ = XCL_SINGLE;
+              class_uchardata += PRIV(ord2utf)(0x202f, class_uchardata);
+              *class_uchardata++ = XCL_SINGLE;
+              class_uchardata += PRIV(ord2utf)(0x205f, class_uchardata);
+              *class_uchardata++ = XCL_SINGLE;
+              class_uchardata += PRIV(ord2utf)(0x3000, class_uchardata);
+              }
+#endif
+            continue;
+
+            case ESC_H:
+            for (c = 0; c < 32; c++)
+              {
+              int x = 0xff;
+              switch (c)
+                {
+                case 0x09/8: x ^= 1 << (0x09%8); break;
+                case 0x20/8: x ^= 1 << (0x20%8); break;
+                case 0xa0/8: x ^= 1 << (0xa0%8); break;
+                default: break;
+                }
+              classbits[c] |= x;
+              }
+#ifndef COMPILE_PCRE8
+            xclass = TRUE;
+            *class_uchardata++ = XCL_RANGE;
+            *class_uchardata++ = 0x0100;
+            *class_uchardata++ = 0x167f;
+            *class_uchardata++ = XCL_RANGE;
+            *class_uchardata++ = 0x1681;
+            *class_uchardata++ = 0x180d;
+            *class_uchardata++ = XCL_RANGE;
+            *class_uchardata++ = 0x180f;
+            *class_uchardata++ = 0x1fff;
+            *class_uchardata++ = XCL_RANGE;
+            *class_uchardata++ = 0x200b;
+            *class_uchardata++ = 0x202e;
+            *class_uchardata++ = XCL_RANGE;
+            *class_uchardata++ = 0x2030;
+            *class_uchardata++ = 0x205e;
+            *class_uchardata++ = XCL_RANGE;
+            *class_uchardata++ = 0x2060;
+            *class_uchardata++ = 0x2fff;
+            *class_uchardata++ = XCL_RANGE;
+            *class_uchardata++ = 0x3001;
+#ifdef SUPPORT_UTF
+            if (utf)
+              class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata);
+            else
+#endif
+              *class_uchardata++ = 0xffff;
+#elif defined SUPPORT_UTF
+            if (utf)
+              {
+              xclass = TRUE;
+              *class_uchardata++ = XCL_RANGE;
+              class_uchardata += PRIV(ord2utf)(0x0100, class_uchardata);
+              class_uchardata += PRIV(ord2utf)(0x167f, class_uchardata);
+              *class_uchardata++ = XCL_RANGE;
+              class_uchardata += PRIV(ord2utf)(0x1681, class_uchardata);
+              class_uchardata += PRIV(ord2utf)(0x180d, class_uchardata);
+              *class_uchardata++ = XCL_RANGE;
+              class_uchardata += PRIV(ord2utf)(0x180f, class_uchardata);
+              class_uchardata += PRIV(ord2utf)(0x1fff, class_uchardata);
+              *class_uchardata++ = XCL_RANGE;
+              class_uchardata += PRIV(ord2utf)(0x200b, class_uchardata);
+              class_uchardata += PRIV(ord2utf)(0x202e, class_uchardata);
+              *class_uchardata++ = XCL_RANGE;
+              class_uchardata += PRIV(ord2utf)(0x2030, class_uchardata);
+              class_uchardata += PRIV(ord2utf)(0x205e, class_uchardata);
+              *class_uchardata++ = XCL_RANGE;
+              class_uchardata += PRIV(ord2utf)(0x2060, class_uchardata);
+              class_uchardata += PRIV(ord2utf)(0x2fff, class_uchardata);
+              *class_uchardata++ = XCL_RANGE;
+              class_uchardata += PRIV(ord2utf)(0x3001, class_uchardata);
+              class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata);
+              }
+#endif
+            continue;
+
+            case ESC_v:
+            SETBIT(classbits, 0x0a); /* LF */
+            SETBIT(classbits, 0x0b); /* VT */
+            SETBIT(classbits, 0x0c); /* FF */
+            SETBIT(classbits, 0x0d); /* CR */
+            SETBIT(classbits, 0x85); /* NEL */
+#ifndef COMPILE_PCRE8
+            xclass = TRUE;
+            *class_uchardata++ = XCL_RANGE;
+            *class_uchardata++ = 0x2028;
+            *class_uchardata++ = 0x2029;
+#elif defined SUPPORT_UTF
+            if (utf)
+              {
+              xclass = TRUE;
+              *class_uchardata++ = XCL_RANGE;
+              class_uchardata += PRIV(ord2utf)(0x2028, class_uchardata);
+              class_uchardata += PRIV(ord2utf)(0x2029, class_uchardata);
+              }
+#endif
+            continue;
+
+            case ESC_V:
+            for (c = 0; c < 32; c++)
+              {
+              int x = 0xff;
+              switch (c)
+                {
+                case 0x0a/8: x ^= 1 << (0x0a%8);
+                             x ^= 1 << (0x0b%8);
+                             x ^= 1 << (0x0c%8);
+                             x ^= 1 << (0x0d%8);
+                             break;
+                case 0x85/8: x ^= 1 << (0x85%8); break;
+                default: break;
+                }
+              classbits[c] |= x;
+              }
+
+#ifndef COMPILE_PCRE8
+            xclass = TRUE;
+            *class_uchardata++ = XCL_RANGE;
+            *class_uchardata++ = 0x0100;
+            *class_uchardata++ = 0x2027;
+            *class_uchardata++ = XCL_RANGE;
+            *class_uchardata++ = 0x202a;
+#ifdef SUPPORT_UTF
+            if (utf)
+              class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata);
+            else
+#endif
+              *class_uchardata++ = 0xffff;
+#elif defined SUPPORT_UTF
+            if (utf)
+              {
+              xclass = TRUE;
+              *class_uchardata++ = XCL_RANGE;
+              class_uchardata += PRIV(ord2utf)(0x0100, class_uchardata);
+              class_uchardata += PRIV(ord2utf)(0x2027, class_uchardata);
+              *class_uchardata++ = XCL_RANGE;
+              class_uchardata += PRIV(ord2utf)(0x202a, class_uchardata);
+              class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata);
+              }
+#endif
+            continue;
+
+#ifdef SUPPORT_UCP
+            case ESC_p:
+            case ESC_P:
+              {
+              BOOL negated;
+              int pdata;
+              int ptype = get_ucp(&ptr, &negated, &pdata, errorcodeptr);
+              if (ptype < 0) goto FAILED;
+              xclass = TRUE;
+              *class_uchardata++ = ((-c == ESC_p) != negated)?
+                XCL_PROP : XCL_NOTPROP;
+              *class_uchardata++ = ptype;
+              *class_uchardata++ = pdata;
+              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_single_char -= 2;  /* Undo the speculative increase. */
+            c = *ptr;                /* Get the final character and fall through */
+            break;
+            }
+          }
+
+        /* Fall through if we have a single character (c >= 0). This may be
+        greater than 256. */
+
+        }   /* End of backslash handling */
+
+      /* A single 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 \r or \n */
+
+      if (c == CHAR_CR || c == CHAR_NL) cd->external_flags |= PCRE_HASCRORLF;
+
+      /* Check for range */
+
+      if (!inescq && ptr[1] == CHAR_MINUS)
+        {
+        int 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;
+          }
+
+        if (*ptr == 0 || (!inescq && *ptr == CHAR_RIGHT_SQUARE_BRACKET))
+          {
+          ptr = oldptr;
+          goto LONE_SINGLE_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, but
+        not any of the other escapes. Perl 5.6 treats a hyphen as a literal
+        in such circumstances. */
+
+        if (!inescq && d == CHAR_BACKSLASH)
+          {
+          d = check_escape(&ptr, errorcodeptr, cd->bracount, options, TRUE);
+          if (*errorcodeptr != 0) goto FAILED;
+
+          /* \b is backspace; any other special means the '-' was literal */
+
+          if (d < 0)
+            {
+            if (d == -ESC_b) d = CHAR_BS; else
+              {
+              ptr = oldptr;
+              goto LONE_SINGLE_CHARACTER;  /* A few lines below */
+              }
+            }
+          }
+
+        /* 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 LONE_SINGLE_CHARACTER;  /* A few lines below */
+
+        /* Remember \r or \n */
+
+        if (d == CHAR_CR || d == CHAR_NL) cd->external_flags |= PCRE_HASCRORLF;
+
+        /* Since we found a character range, single character optimizations
+        cannot be done anymore. */
+        class_single_char = 2;
+
+        /* In UTF-8 mode, if the upper limit is > 255, or > 127 for caseless
+        matching, we have to use an XCLASS with extra data items. Caseless
+        matching for characters > 127 is available only if UCP support is
+        available. */
+
+#if defined SUPPORT_UTF && !(defined COMPILE_PCRE8)
+        if ((d > 255) || (utf && ((options & PCRE_CASELESS) != 0 && d > 127)))
+#elif defined  SUPPORT_UTF
+        if (utf && (d > 255 || ((options & PCRE_CASELESS) != 0 && d > 127)))
+#elif !(defined COMPILE_PCRE8)
+        if (d > 255)
+#endif
+#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
+          {
+          xclass = TRUE;
+
+          /* With UCP support, we can find the other case equivalents of
+          the relevant characters. There may be several ranges. Optimize how
+          they fit with the basic range. */
+
+#ifdef SUPPORT_UCP
+#ifndef COMPILE_PCRE8
+          if (utf && (options & PCRE_CASELESS) != 0)
+#else
+          if ((options & PCRE_CASELESS) != 0)
+#endif
+            {
+            unsigned int occ, ocd;
+            unsigned int cc = c;
+            unsigned int origd = d;
+            while (get_othercase_range(&cc, origd, &occ, &ocd))
+              {
+              if (occ >= (unsigned int)c &&
+                  ocd <= (unsigned int)d)
+                continue;                          /* Skip embedded ranges */
+
+              if (occ < (unsigned int)c  &&
+                  ocd >= (unsigned int)c - 1)      /* Extend the basic range */
+                {                                  /* if there is overlap,   */
+                c = occ;                           /* noting that if occ < c */
+                continue;                          /* we can't have ocd > d  */
+                }                                  /* because a subrange is  */
+              if (ocd > (unsigned int)d &&
+                  occ <= (unsigned int)d + 1)      /* always shorter than    */
+                {                                  /* the basic range.       */
+                d = ocd;
+                continue;
+                }
+
+              if (occ == ocd)
+                {
+                *class_uchardata++ = XCL_SINGLE;
+                }
+              else
+                {
+                *class_uchardata++ = XCL_RANGE;
+                class_uchardata += PRIV(ord2utf)(occ, class_uchardata);
+                }
+              class_uchardata += PRIV(ord2utf)(ocd, class_uchardata);
+              }
+            }
+#endif  /* SUPPORT_UCP */
+
+          /* Now record the original range, possibly modified for UCP caseless
+          overlapping ranges. */
+
+          *class_uchardata++ = XCL_RANGE;
+#ifdef SUPPORT_UTF
+#ifndef COMPILE_PCRE8
+          if (utf)
+            {
+            class_uchardata += PRIV(ord2utf)(c, class_uchardata);
+            class_uchardata += PRIV(ord2utf)(d, class_uchardata);
+            }
+          else
+            {
+            *class_uchardata++ = c;
+            *class_uchardata++ = d;
+            }
+#else
+          class_uchardata += PRIV(ord2utf)(c, class_uchardata);
+          class_uchardata += PRIV(ord2utf)(d, class_uchardata);
+#endif
+#else /* SUPPORT_UTF */
+          *class_uchardata++ = c;
+          *class_uchardata++ = d;
+#endif /* SUPPORT_UTF */
+
+          /* With UCP support, we are done. Without UCP support, there is no
+          caseless matching for UTF characters > 127; we can use the bit map
+          for the smaller ones. As for 16 bit characters without UTF, we
+          can still use  */
+
+#ifdef SUPPORT_UCP
+#ifndef COMPILE_PCRE8
+          if (utf)
+#endif
+            continue;    /* With next character in the class */
+#endif  /* SUPPORT_UCP */
+
+#if defined SUPPORT_UTF && !defined(SUPPORT_UCP) && !(defined COMPILE_PCRE8)
+          if (utf)
+            {
+            if ((options & PCRE_CASELESS) == 0 || c > 127) continue;
+            /* Adjust upper limit and fall through to set up the map */
+            d = 127;
+            }
+          else
+            {
+            if (c > 255) continue;
+            /* Adjust upper limit and fall through to set up the map */
+            d = 255;
+            }
+#elif defined SUPPORT_UTF && !defined(SUPPORT_UCP)
+          if ((options & PCRE_CASELESS) == 0 || c > 127) continue;
+          /* Adjust upper limit and fall through to set up the map */
+          d = 127;
+#else
+          if (c > 255) continue;
+          /* Adjust upper limit and fall through to set up the map */
+          d = 255;
+#endif  /* SUPPORT_UTF && !SUPPORT_UCP && !COMPILE_PCRE8 */
+          }
+#endif  /* SUPPORT_UTF || !COMPILE_PCRE8 */
+
+        /* We use the bit map for 8 bit mode, or when the characters fall
+        partially or entirely to [0-255] ([0-127] for UCP) ranges. */
+
+        class_has_8bitchar = 1;
+
+        /* We can save a bit of time by skipping this in the pre-compile. */
+
+        if (lengthptr == NULL) for (; c <= d; c++)
+          {
+          classbits[c/8] |= (1 << (c&7));
+          if ((options & PCRE_CASELESS) != 0)
+            {
+            int uc = cd->fcc[c]; /* flip case */
+            classbits[uc/8] |= (1 << (uc&7));
+            }
+          }
+
+        continue;   /* Go get the next char in the class */
+        }
+
+      /* Handle a lone 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. */
+
+      LONE_SINGLE_CHARACTER:
+
+      /* Only the value of 1 matters for class_single_char. */
+      if (class_single_char < 2) class_single_char++;
+
+      /* If class_charcount is 1, we saw precisely one character. As long as
+      there were no negated characters >= 128 and there was no use of \p or \P,
+      in other words, no use of any XCLASS features, we can optimize.
+
+      In UTF-8 mode, we can optimize the negative case only if there were no
+      characters >= 128 because OP_NOT and the related opcodes like OP_NOTSTAR
+      operate on single-bytes characters only. This is an historical hangover.
+      Maybe one day we can tidy these opcodes to handle multi-byte characters.
+
+      The optimization throws away the bit map. We turn the item into a
+      1-character OP_CHAR[I] if it's positive, or OP_NOT[I] if it's negative.
+      Note that OP_NOT[I] does not support multibyte characters. 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. */
+
+#ifdef SUPPORT_UTF
+      if (class_single_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET
+        && (!utf || !negate_class || c < (MAX_VALUE_FOR_SINGLE_CHAR + 1)))
+#else
+      if (class_single_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
+#endif
+        {
+        ptr++;
+        zeroreqchar = reqchar;
+
+        /* The OP_NOT[I] opcodes work on single characters only. */
+
+        if (negate_class)
+          {
+          if (firstchar == REQ_UNSET) firstchar = REQ_NONE;
+          zerofirstchar = firstchar;
+          *code++ = ((options & PCRE_CASELESS) != 0)? OP_NOTI: OP_NOT;
+          *code++ = c;
+          goto NOT_CHAR;
+          }
+
+        /* For a single, positive character, get the value into mcbuffer, and
+        then we can handle this with the normal one-character code. */
+
+#ifdef SUPPORT_UTF
+        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 */
+
+      /* Handle a character that cannot go in the bit map. */
+
+#if defined SUPPORT_UTF && !(defined COMPILE_PCRE8)
+      if ((c > 255) || (utf && ((options & PCRE_CASELESS) != 0 && c > 127)))
+#elif defined SUPPORT_UTF
+      if (utf && (c > 255 || ((options & PCRE_CASELESS) != 0 && c > 127)))
+#elif !(defined COMPILE_PCRE8)
+      if (c > 255)
+#endif
+
+#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
+        {
+        xclass = TRUE;
+        *class_uchardata++ = XCL_SINGLE;
+#ifdef SUPPORT_UTF
+#ifndef COMPILE_PCRE8
+        /* In non 8 bit mode, we can get here even if we are not in UTF mode. */
+        if (!utf)
+          *class_uchardata++ = c;
+        else
+#endif
+          class_uchardata += PRIV(ord2utf)(c, class_uchardata);
+#else /* SUPPORT_UTF */
+        *class_uchardata++ = c;
+#endif /* SUPPORT_UTF */
+
+#ifdef SUPPORT_UCP
+#ifdef COMPILE_PCRE8
+        if ((options & PCRE_CASELESS) != 0)
+#else
+        /* In non 8 bit mode, we can get here even if we are not in UTF mode. */
+        if (utf && (options & PCRE_CASELESS) != 0)
+#endif
+          {
+          unsigned int othercase;
+          if ((int)(othercase = UCD_OTHERCASE(c)) != c)
+            {
+            *class_uchardata++ = XCL_SINGLE;
+            class_uchardata += PRIV(ord2utf)(othercase, class_uchardata);
+            }
+          }
+#endif  /* SUPPORT_UCP */
+
+        }
+      else
+#endif  /* SUPPORT_UTF || COMPILE_PCRE16 */
+
+      /* Handle a single-byte character */
+        {
+        class_has_8bitchar = 1;
+        classbits[c/8] |= (1 << (c&7));
+        if ((options & PCRE_CASELESS) != 0)
+          {
+          c = cd->fcc[c]; /* flip case */
+          classbits[c/8] |= (1 << (c&7));
+          }
+        }
+      }
+
+    /* 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)) != 0 ||
+           (nestptr != NULL &&
+             (ptr = nestptr, nestptr = NULL, c = *(++ptr)) != 0)) &&
+           (c != CHAR_RIGHT_SQUARE_BRACKET || inescq));
+
+    /* Check for missing terminating ']' */
+
+    if (c == 0)
+      {
+      *errorcodeptr = ERR6;
+      goto FAILED;
+      }
+
+    /* 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 (firstchar == REQ_UNSET) firstchar = REQ_NONE;
+    zerofirstchar = firstchar;
+    zeroreqchar = reqchar;
+
+    /* 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 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));
+        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);
+    NOT_CHAR:
+    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 */
+      reqchar = zeroreqchar;        /* Ditto */
+      }
+
+    /* 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;
+
+    /* 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 match, abolish the item and generate a
+    repeat item instead. If a char item has a minumum 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)
+      {
+      op_type = (*previous == OP_CHAR)? 0 : OP_STARI - OP_STAR;
+
+      /* 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. */
+
+#ifdef SUPPORT_UTF
+      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 (repeat_min > 1) reqchar = c | req_caseopt | cd->req_varyopt;
+        }
+
+      /* If the repetition is unlimited, it pays to see if the next thing on
+      the line is something that cannot possibly match this character. If so,
+      automatically possessifying this item gains some performance in the case
+      where the match fails. */
+
+      if (!possessive_quantifier &&
+          repeat_max < 0 &&
+          check_auto_possessive(previous, utf, ptr + 1, options, cd))
+        {
+        repeat_type = 0;    /* Force greedy */
+        possessive_quantifier = TRUE;
+        }
+
+      goto OUTPUT_SINGLE_REPEAT;   /* Code shared with single character types */
+      }
+
+    /* If previous was a single negated character ([^a] or similar), we use
+    one of the special opcodes, replacing it. The code is shared with single-
+    character repeats by setting opt_type to add a suitable offset into
+    repeat_type. We can also test for auto-possessification. OP_NOT and OP_NOTI
+    are currently used only for single-byte chars. */
+
+    else if (*previous == OP_NOT || *previous == OP_NOTI)
+      {
+      op_type = ((*previous == OP_NOT)? OP_NOTSTAR : OP_NOTSTARI) - OP_STAR;
+      c = previous[1];
+      if (!possessive_quantifier &&
+          repeat_max < 0 &&
+          check_auto_possessive(previous, utf, ptr + 1, options, cd))
+        {
+        repeat_type = 0;    /* Force greedy */
+        possessive_quantifier = TRUE;
+        }
+      goto OUTPUT_SINGLE_REPEAT;
+      }
+
+    /* 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;
+
+      if (!possessive_quantifier &&
+          repeat_max < 0 &&
+          check_auto_possessive(previous, utf, ptr + 1, options, cd))
+        {
+        repeat_type = 0;    /* Force greedy */
+        possessive_quantifier = TRUE;
+        }
+
+      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;
+
+      /*--------------------------------------------------------------------*/
+      /* This code is obsolete from release 8.00; the restriction was finally
+      removed: */
+
+      /* All real repeats make it impossible to handle partial matching (maybe
+      one day we will be able to remove this restriction). */
+
+      /* if (repeat_max != 1) cd->external_flags |= PCRE_NOPARTIAL; */
+      /*--------------------------------------------------------------------*/
+
+      /* 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)
+          {
+#ifdef SUPPORT_UTF
+          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)
+          {
+#ifdef SUPPORT_UTF
+          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. */
+
+#ifdef SUPPORT_UTF
+      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)
+      {
+      if (repeat_max == 0)
+        {
+        code = previous;
+        goto END_REPEAT;
+        }
+
+      /*--------------------------------------------------------------------*/
+      /* This code is obsolete from release 8.00; the restriction was finally
+      removed: */
+
+      /* All real repeats make it impossible to handle partial matching (maybe
+      one day we will be able to remove this restriction). */
+
+      /* if (repeat_max != 1) cd->external_flags |= PCRE_NOPARTIAL; */
+      /*--------------------------------------------------------------------*/
+
+      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, BRA, CBRA, 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 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 && reqchar < 0) reqchar = firstchar;
+
+            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))
+                {
+                *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 '+', or if certain optimization
+    tests above succeeded, 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.
+
+    Possessifying an 'exact' quantifier has no effect, so we can ignore it. But
+    an 'upto' may follow. We skip over an 'exact' item, and then test the
+    length of what remains before proceeding. */
+
+    if (possessive_quantifier)
+      {
+      int len;
+
+      if (*tempcode == OP_TYPEEXACT)
+        tempcode += PRIV(OP_lengths)[*tempcode] +
+          ((tempcode[1 + IMM2_SIZE] == OP_PROP
+          || tempcode[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0);
+
+      else if (*tempcode == OP_EXACT || *tempcode == OP_NOTEXACT)
+        {
+        tempcode += PRIV(OP_lengths)[*tempcode];
+#ifdef SUPPORT_UTF
+        if (utf && HAS_EXTRALEN(tempcode[-1]))
+          tempcode += GET_EXTRALEN(tempcode[-1]);
+#endif
+        }
+
+      len = (int)(code - tempcode);
+      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;
+
+        /* 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;
+        }
+      }
+
+    /* 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 != 0 && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
+        arglen = (int)(ptr - arg);
+        }
+
+      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)
+          {
+          /* 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);
+              }
+            *code++ = (cd->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT;
+
+            /* Do not set firstchar after *ACCEPT */
+            if (firstchar == REQ_UNSET) firstchar = 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;
+              }
+            *code = verbs[i].op;
+            if (*code++ == OP_THEN) cd->external_flags |= PCRE_HASTHEN;
+            }
+
+          else
+            {
+            if (verbs[i].op_arg < 0)   /* Argument is forbidden */
+              {
+              *errorcodeptr = ERR59;
+              goto FAILED;
+              }
+            *code = verbs[i].op_arg;
+            if (*code++ == OP_THEN_ARG) cd->external_flags |= PCRE_HASTHEN;
+            *code++ = arglen;
+            memcpy(code, arg, IN_UCHARS(arglen));
+            code += arglen;
+            *code++ = 0;
+            }
+
+          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 != 0 && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
+        if (*ptr == 0)
+          {
+          *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 */
+
+        /* A condition can be an assertion, a number (referring to a numbered
+        group), 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 several syntaxes for testing a named group: (?(name)) is used
+        by Python; Perl 5.10 onwards uses (?(<name>) or (?('name')).
+
+        There are two unfortunate ambiguities, caused by history. (a) 'R' can
+        be the recursive thing or the name 'R' (and similarly for 'R' followed
+        by digits), and (b) a number could be a name that consists of digits.
+        In both cases, we look for a name first; if not found, we try the other
+        cases. */
+
+        /* 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 (ptr[1] == CHAR_QUESTION_MARK && (ptr[2] == CHAR_EQUALS_SIGN ||
+            ptr[2] == CHAR_EXCLAMATION_MARK || ptr[2] == CHAR_LESS_THAN_SIGN))
+          break;
+
+        /* Most other conditions use OP_CREF (a couple change to OP_RREF
+        below), and all need to skip 1+IMM2_SIZE bytes at the start of the group. */
+
+        code[1+LINK_SIZE] = OP_CREF;
+        skipbytes = 1+IMM2_SIZE;
+        refsign = -1;
+
+        /* Check for a test for recursion in a named group. */
+
+        if (ptr[1] == CHAR_R && ptr[2] == 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') */
+
+        else if (ptr[1] == CHAR_LESS_THAN_SIGN)
+          {
+          terminator = CHAR_GREATER_THAN_SIGN;
+          ptr++;
+          }
+        else if (ptr[1] == CHAR_APOSTROPHE)
+          {
+          terminator = CHAR_APOSTROPHE;
+          ptr++;
+          }
+        else
+          {
+          terminator = 0;
+          if (ptr[1] == CHAR_MINUS || ptr[1] == CHAR_PLUS) refsign = *(++ptr);
+          }
+
+        /* We now expect to read a name; any thing else is an error */
+
+        if (!MAX_255(ptr[1]) || (cd->ctypes[ptr[1]] & ctype_word) == 0)
+          {
+          ptr += 1;  /* To get the right offset */
+          *errorcodeptr = ERR28;
+          goto FAILED;
+          }
+
+        /* Read the name, but also get it as a number if it's all digits */
+
+        recno = 0;
+        name = ++ptr;
+        while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0)
+          {
+          if (recno >= 0)
+            recno = (IS_DIGIT(*ptr))? recno * 10 + *ptr - CHAR_0 : -1;
+          ptr++;
+          }
+        namelen = (int)(ptr - name);
+
+        if ((terminator > 0 && *ptr++ != terminator) ||
+            *ptr++ != CHAR_RIGHT_PARENTHESIS)
+          {
+          ptr--;      /* Error offset */
+          *errorcodeptr = ERR26;
+          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 the string started with "+" or "-" we require the rest to
+        be digits, in which case recno will be set. */
+
+        if (refsign > 0)
+          {
+          if (recno <= 0)
+            {
+            *errorcodeptr = ERR58;
+            goto FAILED;
+            }
+          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 (did not start with "+" or "-"), start by looking for the
+        name. If we find a name, add one to the opcode to change OP_CREF or
+        OP_RREF into OP_NCREF or OP_NRREF. These behave exactly the same,
+        except they record that the reference was originally to a name. The
+        information is used to check duplicate names. */
+
+        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 a previous named subpattern */
+
+        if (i < cd->names_found)
+          {
+          recno = GET2(slot, 0);
+          PUT2(code, 2+LINK_SIZE, recno);
+          code[1+LINK_SIZE]++;
+          }
+
+        /* Search the pattern for a forward reference */
+
+        else if ((i = find_parens(cd, name, namelen,
+                        (options & PCRE_EXTENDED) != 0, utf)) > 0)
+          {
+          PUT2(code, 2+LINK_SIZE, i);
+          code[1+LINK_SIZE]++;
+          }
+
+        /* If terminator == 0 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 != 0
+        [things like (?(<name>... or (?('name')... or (?(R&name)... ] we have
+        now checked all the possibilities, so give an error. */
+
+        else if (terminator != 0)
+          {
+          *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;
+          }
+
+        /* Check for the "name" actually being a subpattern number. We are
+        in the second pass here, so final_bracount is set. */
+
+        else if (recno > 0 && recno <= cd->final_bracount)
+          {
+          PUT2(code, 2+LINK_SIZE, recno);
+          }
+
+        /* Either an unidentified subpattern, or a reference to (?(0) */
+
+        else
+          {
+          *errorcodeptr = (recno == 0)? ERR35: ERR15;
+          goto FAILED;
+          }
+        break;
+
+
+        /* ------------------------------------------------------------ */
+        case CHAR_EQUALS_SIGN:                 /* Positive lookahead */
+        bravalue = OP_ASSERT;
+        cd->assert_depth += 1;
+        ptr++;
+        break;
+
+
+        /* ------------------------------------------------------------ */
+        case CHAR_EXCLAMATION_MARK:            /* Negative lookahead */
+        ptr++;
+        if (*ptr == CHAR_RIGHT_PARENTHESIS)    /* Optimize (?!) */
+          {
+          *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;
+
+          while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) ptr++;
+          namelen = (int)(ptr - name);
+
+          /* In the pre-compile phase, just do a syntax check. */
+
+          if (lengthptr != NULL)
+            {
+            if (*ptr != 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;
+                }
+              }
+            }
+
+          /* In the real compile, create the entry in the table, maintaining
+          alphabetical order. Duplicate names for different numbers are
+          permitted only if PCRE_DUPNAMES is set. Duplicate names for the same
+          number are always OK. (An existing number can be re-used if (?|
+          appears in the pattern.) In either event, a duplicate name results in
+          a duplicate entry in the table, even if the number is the same. This
+          is because the number of names, and hence the table size, is computed
+          in the pre-compile, and it affects various numbers and pointers which
+          would all have to be modified, and the compiled code moved down, if
+          duplicates with the same number were omitted from the table. This
+          doesn't seem worth the hassle. However, *different* names for the
+          same number are not permitted. */
+
+          else
+            {
+            BOOL dupname = FALSE;
+            slot = cd->name_table;
+
+            for (i = 0; i < cd->names_found; i++)
+              {
+              int crc = memcmp(name, slot+IMM2_SIZE, IN_UCHARS(namelen));
+              if (crc == 0)
+                {
+                if (slot[IMM2_SIZE+namelen] == 0)
+                  {
+                  if (GET2(slot, 0) != cd->bracount + 1 &&
+                      (options & PCRE_DUPNAMES) == 0)
+                    {
+                    *errorcodeptr = ERR43;
+                    goto FAILED;
+                    }
+                  else dupname = TRUE;
+                  }
+                else 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. */
+
+              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;
+              }
+
+            /* For non-duplicate names, check for a duplicate number before
+            adding the new name. */
+
+            if (!dupname)
+              {
+              pcre_uchar *cslot = cd->name_table;
+              for (i = 0; i < cd->names_found; i++)
+                {
+                if (cslot != slot)
+                  {
+                  if (GET2(cslot, 0) == cd->bracount + 1)
+                    {
+                    *errorcodeptr = ERR65;
+                    goto FAILED;
+                    }
+                  }
+                else i--;
+                cslot += cd->name_entry_size;
+                }
+              }
+
+            PUT2(slot, 0, cd->bracount + 1);
+            memcpy(slot + IMM2_SIZE, name, IN_UCHARS(namelen));
+            slot[IMM2_SIZE + namelen] = 0;
+            }
+          }
+
+        /* In both pre-compile and compile, count the number of names we've
+        encountered. */
+
+        cd->names_found++;
+        ptr++;                    /* Move past > or ' */
+        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;
+        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)
+          {
+          const pcre_uchar *temp;
+
+          if (namelen == 0)
+            {
+            *errorcodeptr = ERR62;
+            goto FAILED;
+            }
+          if (*ptr != terminator)
+            {
+            *errorcodeptr = ERR42;
+            goto FAILED;
+            }
+          if (namelen > MAX_NAME_SIZE)
+            {
+            *errorcodeptr = ERR48;
+            goto FAILED;
+            }
+
+          /* The name table does not exist in the first pass, so we cannot
+          do a simple search as in the code below. Instead, we have to scan the
+          pattern to find the number. It is important that we scan it only as
+          far as we have got because the syntax of named subpatterns has not
+          been checked for the rest of the pattern, and find_parens() assumes
+          correct syntax. In any case, it's a waste of resources to scan
+          further. We stop the scan at the current point by temporarily
+          adjusting the value of cd->endpattern. */
+
+          temp = cd->end_pattern;
+          cd->end_pattern = ptr;
+          recno = find_parens(cd, name, namelen,
+            (options & PCRE_EXTENDED) != 0, utf);
+          cd->end_pattern = temp;
+          if (recno < 0) recno = 0;    /* Forward ref; set dummy number */
+          }
+
+        /* In the real compile, seek the name in the 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 that 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)         /* Back reference */
+            {
+            recno = GET2(slot, 0);
+            }
+          else if ((recno =                /* Forward back reference */
+                    find_parens(cd, name, namelen,
+                      (options & PCRE_EXTENDED) != 0, utf)) <= 0)
+            {
+            *errorcodeptr = ERR15;
+            goto FAILED;
+            }
+          }
+
+        /* In both phases, we can now go to the code than handles numerical
+        recursion or backreferences. */
+
+        if (is_recurse) goto HANDLE_RECURSION;
+          else 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 != 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 (find_parens(cd, NULL, recno,
+                    (options & PCRE_EXTENDED) != 0, utf) < 0)
+                {
+                *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 (firstchar == REQ_UNSET) firstchar = 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. 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 */
+         &subreqchar,                     /* For possible last char */
+         bcptr,                           /* Current branch chain */
+         cd,                              /* Tables block */
+         (lengthptr == NULL)? NULL :      /* Actual compile phase */
+           &length_prevgroup              /* Pre-compile phase */
+         ))
+      goto FAILED;
+
+    /* 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) subfirstchar = subreqchar = 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;
+    zerofirstchar = firstchar;
+    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 (firstchar == REQ_UNSET)
+        {
+        if (subfirstchar >= 0)
+          {
+          firstchar = subfirstchar;
+          groupsetfirstchar = TRUE;
+          }
+        else firstchar = REQ_NONE;
+        zerofirstchar = 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 (subfirstchar >= 0 && subreqchar < 0)
+        subreqchar = subfirstchar | 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 (subreqchar >= 0) reqchar = subreqchar;
+      }
+
+    /* 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 && subreqchar >= 0) reqchar = subreqchar;
+    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 ESC_REF plus 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;
+    c = check_escape(&ptr, errorcodeptr, cd->bracount, options, FALSE);
+    if (*errorcodeptr != 0) goto FAILED;
+
+    if (c < 0)
+      {
+      if (-c == 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 (-c == 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 (firstchar == REQ_UNSET && -c > ESC_b && -c < ESC_Z)
+        firstchar = REQ_NONE;
+
+      /* Set values to reset to if this is followed by a zero repeat. */
+
+      zerofirstchar = firstchar;
+      zeroreqchar = reqchar;
+
+      /* \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
+      -ESC_REF+n, and for the Perl syntax \g{name} the result is -ESC_k (as
+      that is a synonym for a named back reference). */
+
+      if (-c == ESC_g)
+        {
+        const pcre_uchar *p;
+        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 actually check for a number below, the paths that
+        would actually be in error are never taken. */
+
+        skipbytes = 0;
+        reset_bracount = FALSE;
+
+        /* Test for a name */
+
+        if (ptr[1] != CHAR_PLUS && ptr[1] != CHAR_MINUS)
+          {
+          BOOL is_a_number = TRUE;
+          for (p = ptr + 1; *p != 0 && *p != terminator; p++)
+            {
+            if (!MAX_255(*p)) { is_a_number = FALSE; break; }
+            if ((cd->ctypes[*p] & ctype_digit) == 0) is_a_number = FALSE;
+            if ((cd->ctypes[*p] & ctype_word) == 0) break;
+            }
+          if (*p != terminator)
+            {
+            *errorcodeptr = ERR57;
+            break;
+            }
+          if (is_a_number)
+            {
+            ptr++;
+            goto HANDLE_NUMERICAL_RECURSION;
+            }
+          is_recurse = TRUE;
+          goto NAMED_REF_OR_RECURSE;
+          }
+
+        /* Test a signed number in angle brackets or quotes. */
+
+        p = ptr + 2;
+        while (IS_DIGIT(*p)) p++;
+        if (*p != 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 (-c == 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 (-c >= ESC_REF)
+        {
+        open_capitem *oc;
+        recno = -c - ESC_REF;
+
+        HANDLE_REFERENCE:    /* Come here from named backref handling */
+        if (firstchar == REQ_UNSET) firstchar = 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 (-c == ESC_P || -c == ESC_p)
+        {
+        BOOL negated;
+        int pdata;
+        int ptype = get_ucp(&ptr, &negated, &pdata, errorcodeptr);
+        if (ptype < 0) goto FAILED;
+        previous = code;
+        *code++ = ((-c == 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 (-c == ESC_X || -c == ESC_P || -c == 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. */
+
+      else
+        {
+#ifdef SUPPORT_UCP
+        if (-c >= ESC_DU && -c <= ESC_wu)
+          {
+          nestptr = ptr + 1;                   /* Where to resume */
+          ptr = substitutes[-c - 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 = (-c > ESC_b && -c < ESC_Z)? code : NULL;
+          *code++ = (!utf && c == -ESC_C)? OP_ALLANY : -c;
+          }
+        }
+      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. */
+
+#ifdef SUPPORT_UTF
+    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 UTF-8 mode, it may be a
+    multi-byte 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;
+    *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 (firstchar == REQ_UNSET)
+      {
+      zerofirstchar = REQ_NONE;
+      zeroreqchar = reqchar;
+
+      /* 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;
+        if (mclength != 1) reqchar = code[-1] | cd->req_varyopt;
+        }
+      else firstchar = reqchar = REQ_NONE;
+      }
+
+    /* firstchar was previously set; we can set reqchar only if the length is
+    1 or the matching is caseful. */
+
+    else
+      {
+      zerofirstchar = firstchar;
+      zeroreqchar = reqchar;
+      if (mclength == 1 || req_caseopt == 0)
+        reqchar = code[-1] | 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, or a negative number
+  reqcharptr     place to put the last required character, 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_int32 *firstcharptr, pcre_int32 *reqcharptr,
+  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_int32 firstchar, reqchar;
+pcre_int32 branchfirstchar, branchreqchar;
+int length;
+int orig_bracount;
+int max_bracount;
+branch_chain bc;
+
+bc.outer = bcptr;
+bc.current_branch = code;
+
+firstchar = reqchar = 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,
+        &branchreqchar, &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;
+      reqchar = branchreqchar;
+      }
+
+    /* 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 (firstchar >= 0 && firstchar != branchfirstchar)
+        {
+        if (reqchar < 0) reqchar = firstchar;
+        firstchar = 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 (firstchar < 0 && branchfirstchar >= 0 && branchreqchar < 0)
+          branchreqchar = branchfirstchar;
+
+      /* Now ensure that the reqchars match */
+
+      if ((reqchar & ~REQ_VARY) != (branchreqchar & ~REQ_VARY))
+        reqchar = REQ_NONE;
+      else reqchar |= branchreqchar;   /* 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 { 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;
+    *reqcharptr = reqchar;
+    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.
+
+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
+  backref_map    the back reference bitmap
+
+Returns:     TRUE or FALSE
+*/
+
+static BOOL
+is_anchored(register const pcre_uchar *code, unsigned int bracket_map,
+  unsigned int backref_map)
+{
+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, backref_map)) 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, backref_map)) return FALSE;
+     }
+
+   /* Other brackets */
+
+   else if (op == OP_ASSERT || op == OP_ONCE || op == OP_ONCE_NC ||
+            op == OP_COND)
+     {
+     if (!is_anchored(scode, bracket_map, backref_map)) 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. */
+
+   else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR ||
+             op == OP_TYPEPOSSTAR))
+     {
+     if (scode[1] != OP_ALLANY || (bracket_map & backref_map) != 0)
+       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.
+
+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
+  backref_map    the back reference bitmap
+
+Returns:         TRUE or FALSE
+*/
+
+static BOOL
+is_startline(const pcre_uchar *code, unsigned int bracket_map,
+  unsigned int backref_map)
+{
+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_NCREF:
+       case OP_RREF:
+       case OP_NRREF:
+       case OP_DEF:
+       return FALSE;
+
+       default:     /* Assertion */
+       if (!is_startline(scode, bracket_map, backref_map)) 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, backref_map)) 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, backref_map)) return FALSE;
+     }
+
+   /* Other brackets */
+
+   else if (op == OP_ASSERT || op == OP_ONCE || op == OP_ONCE_NC)
+     {
+     if (!is_startline(scode, bracket_map, backref_map)) return FALSE;
+     }
+
+   /* .* means "start at start or after \n" if it isn't in brackets that
+   may be referenced. */
+
+   else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR)
+     {
+     if (scode[1] != OP_ANY || (bracket_map & backref_map) != 0) return FALSE;
+     }
+
+   /* Check for explicit circumflex */
+
+   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 bracket all
+of whose alternatives start with the same asserted char (recurse ad lib), then
+we return that char, otherwise -1.
+
+Arguments:
+  code       points to start of expression (the bracket)
+  inassert   TRUE if in an assertion
+
+Returns:     -1 or the fixed first char
+*/
+
+static int
+find_firstassertedchar(const pcre_uchar *code, BOOL inassert)
+{
+register int c = -1;
+do {
+   int d;
+   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 int op = *scode;
+
+   switch(op)
+     {
+     default:
+     return -1;
+
+     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:
+     case OP_COND:
+     if ((d = find_firstassertedchar(scode, op == OP_ASSERT)) < 0)
+       return -1;
+     if (c < 0) c = d; else if (c != d) return -1;
+     break;
+
+     case OP_EXACT:
+     scode += IMM2_SIZE;
+     /* Fall through */
+
+     case OP_CHAR:
+     case OP_PLUS:
+     case OP_MINPLUS:
+     case OP_POSPLUS:
+     if (!inassert) return -1;
+     if (c < 0) c = scode[1];
+       else if (c != scode[1]) return -1;
+     break;
+
+     case OP_EXACTI:
+     scode += IMM2_SIZE;
+     /* Fall through */
+
+     case OP_CHARI:
+     case OP_PLUSI:
+     case OP_MINPLUSI:
+     case OP_POSPLUSI:
+     if (!inassert) return -1;
+     if (c < 0) c = scode[1] | REQ_CASELESS;
+       else if (c != scode[1]) return -1;
+     break;
+     }
+
+   code += GET(code, 1);
+   }
+while (*code == OP_ALT);
+return c;
+}
+
+
+
+/*************************************************
+*        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
+*/
+
+#ifdef 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)
+#else
+PCRE_EXP_DEFN pcre16 * PCRE_CALL_CONVENTION
+pcre16_compile(PCRE_SPTR16 pattern, int options, const char **errorptr,
+  int *erroroffset, const unsigned char *tables)
+#endif
+{
+#ifdef COMPILE_PCRE8
+return pcre_compile2(pattern, options, NULL, errorptr, erroroffset, tables);
+#else
+return pcre16_compile2(pattern, options, NULL, errorptr, erroroffset, tables);
+#endif
+}
+
+
+#ifdef 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)
+#else
+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)
+#endif
+{
+REAL_PCRE *re;
+int length = 1;  /* For final END opcode */
+pcre_int32 firstchar, reqchar;
+int newline;
+int errorcode = 0;
+int skipatstart = 0;
+BOOL utf;
+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];
+
+/* 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;
+  }
+
+/* Check for global one-time settings at the start of the pattern, and remember
+the offset for later. */
+
+while (ptr[skipatstart] == CHAR_LEFT_PARENTHESIS &&
+       ptr[skipatstart+1] == CHAR_ASTERISK)
+  {
+  int newnl = 0;
+  int newbsr = 0;
+
+#ifdef COMPILE_PCRE8
+  if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF_RIGHTPAR, 5) == 0)
+    { skipatstart += 7; options |= PCRE_UTF8; continue; }
+#endif
+#ifdef COMPILE_PCRE16
+  if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF_RIGHTPAR, 6) == 0)
+    { skipatstart += 8; options |= PCRE_UTF16; continue; }
+#endif
+  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_START_OPT_RIGHTPAR, 13) == 0)
+    { skipatstart += 15; options |= PCRE_NO_START_OPTIMIZE; 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_UTF16 has the same value as PCRE_UTF8. */
+utf = (options & PCRE_UTF8) != 0;
+
+/* 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)
+  {
+#ifdef COMPILE_PCRE8
+  errorcode = ERR44;
+#else
+  errorcode = ERR74;
+#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->start_code = cworkspace;
+cd->hwm = cworkspace;
+cd->start_workspace = cworkspace;
+cd->workspace_size = COMPILE_WORK_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->assert_depth = 0;
+cd->external_options = options;
+cd->external_flags = 0;
+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, &reqchar, 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;
+  }
+
+/* Compute the size of data block needed and get it, either from malloc or
+externally provided function. 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);
+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->dummy1 = 0;
+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;
+
+/* 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->assert_depth = 0;
+cd->bracount = 0;
+cd->names_found = 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->check_lookbehind = FALSE;
+cd->open_caps = NULL;
+
+/* 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, &reqchar, NULL, cd, NULL);
+re->top_bracket = cd->bracount;
+re->top_backref = cd->top_backref;
+re->flags = cd->external_flags | PCRE_MODE;
+
+if (cd->had_accept) reqchar = REQ_NONE;   /* Must disable after (*ACCEPT) */
+
+/* If not reached end of pattern on success, there's an excess bracket. */
+
+if (errorcode == 0 && *ptr != 0) 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
+
+/* 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. */
+
+if (cd->workspace_size > COMPILE_WORK_SIZE)
+  (PUBL(free))((void *)cd->start_workspace);
+
+/* 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;
+
+/* 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 can't 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;
+        }
+      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 .* when DOTALL is set).
+
+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 .* for non-DOTALL matches.
+*/
+
+if ((re->options & PCRE_ANCHORED) == 0)
+  {
+  if (is_anchored(codestart, 0, cd->backref_map))
+    re->options |= PCRE_ANCHORED;
+  else
+    {
+    if (firstchar < 0)
+      firstchar = find_firstassertedchar(codestart, FALSE);
+    if (firstchar >= 0)   /* Remove caseless flag for non-caseable chars */
+      {
+#ifdef COMPILE_PCRE8
+      re->first_char = firstchar & 0xff;
+#else
+#ifdef COMPILE_PCRE16
+      re->first_char = firstchar & 0xffff;
+#endif
+#endif
+      if ((firstchar & 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->backref_map))
+      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 (reqchar >= 0 &&
+     ((re->options & PCRE_ANCHORED) == 0 || (reqchar & REQ_VARY) != 0))
+  {
+#ifdef COMPILE_PCRE8
+  re->req_char = reqchar & 0xff;
+#else
+#ifdef COMPILE_PCRE16
+  re->req_char = reqchar & 0xffff;
+#endif
+#endif
+  if ((reqchar & 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);
+  }
+
+#ifdef COMPILE_PCRE8
+pcre_printint((pcre *)re, stdout, TRUE);
+#else
+pcre16_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 */
+
+#ifdef COMPILE_PCRE8
+return (pcre *)re;
+#else
+return (pcre16 *)re;
+#endif
+}
+
+/* End of pcre_compile.c */
diff --git a/src/3rdparty/pcre/pcre_config.c b/src/3rdparty/pcre/pcre_config.c
new file mode 100644 (file)
index 0000000..6ebafaf
--- /dev/null
@@ -0,0 +1,170 @@
+/*************************************************
+*      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 PCRE_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
+*/
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_config(int what, void *where)
+#else
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_config(int what, void *where)
+#endif
+{
+switch (what)
+  {
+  case PCRE_CONFIG_UTF8:
+#if 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_UTF16:
+#if defined COMPILE_PCRE8
+  *((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_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/src/3rdparty/pcre/pcre_dfa_exec.c b/src/3rdparty/pcre/pcre_dfa_exec.c
new file mode 100644 (file)
index 0000000..bc89c0d
--- /dev/null
@@ -0,0 +1,3490 @@
+/*************************************************
+*      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-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_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 PCRE_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,                             /* CLASS                                  */
+  0,                             /* NCLASS                                 */
+  0,                             /* XCLASS - variable length               */
+  0,                             /* REF                                    */
+  0,                             /* REFI                                   */
+  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, NCREF                            */
+  0, 0,                          /* RREF, NRREF                            */
+  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,                             /* CLASS                                  */
+  1,                             /* NCLASS                                 */
+  1,                             /* XCLASS - variable length               */
+  0,                             /* REF                                    */
+  0,                             /* REFI                                   */
+  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, NCREF                            */
+  0, 0,                          /* RREF, NRREF                            */
+  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  (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)
+{
+int 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)\n", rlevel*2-2, SP, (x), (y), (z))); \
+    } \
+  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
+
+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;
+  unsigned int c, d;
+  int forced_fail = 0;
+  BOOL 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 bytes in the character */
+#ifdef SUPPORT_UTF
+    if (utf) { GETCHARLEN(c, ptr, clen); } else
+#endif  /* SUPPORT_UTF */
+    c = *ptr;
+    }
+  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 count, codevalue, rrc;
+
+#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 (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);
+        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. 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], 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))
+        { 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); }
+        }
+      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 (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;
+#ifdef SUPPORT_UTF
+          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 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;
+
+          case PT_SPACE:    /* Perl space */
+          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
+               c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
+          break;
+
+          case PT_PXSPACE:  /* POSIX space */
+          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
+               c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
+               c == CHAR_FF || c == CHAR_CR;
+          break;
+
+          case PT_WORD:
+          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+               PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
+               c == CHAR_UNDERSCORE;
+          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 ((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 ((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 ((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 ((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 >= 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 ((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 >= 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 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;
+
+          case PT_SPACE:    /* Perl space */
+          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
+               c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
+          break;
+
+          case PT_PXSPACE:  /* POSIX space */
+          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
+               c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
+               c == CHAR_FF || c == CHAR_CR;
+          break;
+
+          case PT_WORD:
+          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+               PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
+               c == CHAR_UNDERSCORE;
+          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 && UCD_CATEGORY(c) != ucp_M)
+        {
+        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--;
+          }
+        while (nptr < end_subject)
+          {
+          int nd;
+          int ndlen = 1;
+          GETCHARLEN(nd, nptr, ndlen);
+          if (UCD_CATEGORY(nd) != ucp_M) break;
+          ncount++;
+          nptr += ndlen;
+          }
+        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 0x000b:
+          case 0x000c:
+          case 0x0085:
+          case 0x2028:
+          case 0x2029:
+          if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
+          goto ANYNL01;
+
+          case 0x000d:
+          if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
+          /* Fall through */
+
+          ANYNL01:
+          case 0x000a:
+          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)
+          {
+          case 0x000a:
+          case 0x000b:
+          case 0x000c:
+          case 0x000d:
+          case 0x0085:
+          case 0x2028:
+          case 0x2029:
+          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)
+          {
+          case 0x09:      /* HT */
+          case 0x20:      /* SPACE */
+          case 0xa0:      /* NBSP */
+          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 */
+          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 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;
+
+          case PT_SPACE:    /* Perl space */
+          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
+               c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
+          break;
+
+          case PT_PXSPACE:  /* POSIX space */
+          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
+               c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
+               c == CHAR_FF || c == CHAR_CR;
+          break;
+
+          case PT_WORD:
+          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+               PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
+               c == CHAR_UNDERSCORE;
+          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 && UCD_CATEGORY(c) != ucp_M)
+        {
+        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--;
+          }
+        while (nptr < end_subject)
+          {
+          int nd;
+          int ndlen = 1;
+          GETCHARLEN(nd, nptr, ndlen);
+          if (UCD_CATEGORY(nd) != ucp_M) break;
+          ncount++;
+          nptr += ndlen;
+          }
+        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 0x000b:
+          case 0x000c:
+          case 0x0085:
+          case 0x2028:
+          case 0x2029:
+          if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
+          goto ANYNL02;
+
+          case 0x000d:
+          if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
+          /* Fall through */
+
+          ANYNL02:
+          case 0x000a:
+          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 + 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)
+          {
+          case 0x000a:
+          case 0x000b:
+          case 0x000c:
+          case 0x000d:
+          case 0x0085:
+          case 0x2028:
+          case 0x2029:
+          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 + 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)
+          {
+          case 0x09:      /* HT */
+          case 0x20:      /* SPACE */
+          case 0xa0:      /* NBSP */
+          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 */
+          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 + 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 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;
+
+          case PT_SPACE:    /* Perl space */
+          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
+               c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR;
+          break;
+
+          case PT_PXSPACE:  /* POSIX space */
+          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
+               c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
+               c == CHAR_FF || c == CHAR_CR;
+          break;
+
+          case PT_WORD:
+          OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+               PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
+               c == CHAR_UNDERSCORE;
+          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 >= 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 && UCD_CATEGORY(c) != ucp_M)
+        {
+        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--;
+          }
+        while (nptr < end_subject)
+          {
+          int nd;
+          int ndlen = 1;
+          GETCHARLEN(nd, nptr, ndlen);
+          if (UCD_CATEGORY(nd) != ucp_M) break;
+          ncount++;
+          nptr += ndlen;
+          }
+        if (++count >= 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 0x000b:
+          case 0x000c:
+          case 0x0085:
+          case 0x2028:
+          case 0x2029:
+          if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
+          goto ANYNL03;
+
+          case 0x000d:
+          if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
+          /* Fall through */
+
+          ANYNL03:
+          case 0x000a:
+          if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO)
+            {
+            active_count--;           /* Remove non-match possibility */
+            next_active_state--;
+            }
+          if (++count >= 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)
+          {
+          case 0x000a:
+          case 0x000b:
+          case 0x000c:
+          case 0x000d:
+          case 0x0085:
+          case 0x2028:
+          case 0x2029:
+          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 >= 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)
+          {
+          case 0x09:      /* HT */
+          case 0x20:      /* SPACE */
+          case 0xa0:      /* NBSP */
+          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 */
+          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 >= 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 && UCD_CATEGORY(c) != ucp_M)
+        {
+        const pcre_uchar *nptr = ptr + clen;
+        int ncount = 0;
+        while (nptr < end_subject)
+          {
+          int nclen = 1;
+          GETCHARLEN(c, nptr, nclen);
+          if (UCD_CATEGORY(c) != ucp_M) break;
+          ncount++;
+          nptr += nclen;
+          }
+        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 0x000b:
+        case 0x000c:
+        case 0x0085:
+        case 0x2028:
+        case 0x2029:
+        if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
+
+        case 0x000a:
+        ADD_NEW(state_offset + 1, 0);
+        break;
+
+        case 0x000d:
+        if (ptr + 1 < end_subject && ptr[1] == 0x0a)
+          {
+          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)
+        {
+        case 0x000a:
+        case 0x000b:
+        case 0x000c:
+        case 0x000d:
+        case 0x0085:
+        case 0x2028:
+        case 0x2029:
+        break;
+
+        default:
+        ADD_NEW(state_offset + 1, 0);
+        break;
+        }
+      break;
+
+      /*-----------------------------------------------------------------*/
+      case OP_VSPACE:
+      if (clen > 0) switch(c)
+        {
+        case 0x000a:
+        case 0x000b:
+        case 0x000c:
+        case 0x000d:
+        case 0x0085:
+        case 0x2028:
+        case 0x2029:
+        ADD_NEW(state_offset + 1, 0);
+        break;
+
+        default: break;
+        }
+      break;
+
+      /*-----------------------------------------------------------------*/
+      case OP_NOT_HSPACE:
+      if (clen > 0) switch(c)
+        {
+        case 0x09:      /* HT */
+        case 0x20:      /* SPACE */
+        case 0xa0:      /* NBSP */
+        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 */
+        break;
+
+        default:
+        ADD_NEW(state_offset + 1, 0);
+        break;
+        }
+      break;
+
+      /*-----------------------------------------------------------------*/
+      case OP_HSPACE:
+      if (clen > 0) switch(c)
+        {
+        case 0x09:      /* HT */
+        case 0x20:      /* SPACE */
+        case 0xa0:      /* NBSP */
+        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 */
+        ADD_NEW(state_offset + 1, 0);
+        break;
+        }
+      break;
+
+      /*-----------------------------------------------------------------*/
+      /* Match a negated single character casefully. This is only used for
+      one-byte characters, that is, we know that d < 256. The character we are
+      checking (c) can be multibyte. */
+
+      case OP_NOT:
+      if (clen > 0 && c != d) { ADD_NEW(state_offset + dlen + 1, 0); }
+      break;
+
+      /*-----------------------------------------------------------------*/
+      /* Match a negated single character caselessly. This is only used for
+      one-byte characters, that is, we know that d < 256. The character we are
+      checking (c) can be multibyte. */
+
+      case OP_NOTI:
+      if (clen > 0 && c != d && c != fcc[d])
+        { 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)
+        {
+        unsigned int 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)
+        {
+        unsigned int 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)
+        {
+        unsigned int 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)
+        {
+        unsigned int 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 >= 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)
+        {
+        unsigned int 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 >= 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:
+          ADD_ACTIVE(next_state_offset + 1, 0);
+          if (isinclass) { ADD_NEW(state_offset, 0); }
+          break;
+
+          case OP_CRPLUS:
+          case OP_CRMINPLUS:
+          count = current_state->count;  /* Already matched */
+          if (count > 0) { ADD_ACTIVE(next_state_offset + 1, 0); }
+          if (isinclass) { count++; ADD_NEW(state_offset, count); }
+          break;
+
+          case OP_CRQUERY:
+          case OP_CRMINQUERY:
+          ADD_ACTIVE(next_state_offset + 1, 0);
+          if (isinclass) { ADD_NEW(next_state_offset + 1, 0); }
+          break;
+
+          case OP_CRRANGE:
+          case OP_CRMINRANGE:
+          count = current_state->count;  /* Already matched */
+          if (count >= GET2(ecode, 1))
+            { ADD_ACTIVE(next_state_offset + 1 + 2 * IMM2_SIZE, 0); }
+          if (isinclass)
+            {
+            int max = GET2(ecode, 1 + IMM2_SIZE);
+            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;
+#ifdef COMPILE_PCRE8
+            cb.subject          = (PCRE_SPTR)start_subject;
+#else
+            cb.subject          = (PCRE_SPTR16)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 are not supported */
+
+        if (condcode == OP_CREF || condcode == OP_NCREF)
+          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 || condcode == OP_NRREF)
+          {
+          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];
+#ifdef SUPPORT_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);
+#ifdef SUPPORT_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
+            {
+#ifdef SUPPORT_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;
+#ifdef COMPILE_PCRE8
+        cb.subject          = (PCRE_SPTR)start_subject;
+#else
+        cb.subject          = (PCRE_SPTR16)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 */
+        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... */
+        ptr >= end_subject &&                  /* Reached end of subject */
+        ptr > md->start_used_ptr)              /* Inspected non-empty string */
+      {
+      if (offsetcount >= 2)
+        {
+        offsets[0] = (int)(md->start_used_ptr - start_subject);
+        offsets[1] = (int)(end_subject - start_subject);
+        }
+      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
+*/
+
+#ifdef 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)
+#else
+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)
+#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 (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET;
+
+/* We need to find the pointer to any study data before we test for byte
+flipping, so we scan the extra_data block first. This may set two fields in the
+match block, so we must initialize them beforehand. However, the other fields
+in the match block must not be set until after the byte flipping. */
+
+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;
+  }
+
+/* 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;
+
+/* 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_UTF16 has 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;
+      }
+    return (errorcode <= PCRE_UTF8_ERR5 && (options & PCRE_PARTIAL_HARD) != 0)?
+      PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8;
+    }
+  if (start_offset > 0 && start_offset < length &&
+        NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset]))
+    return PCRE_ERROR_BADUTF8_OFFSET;
+  }
+#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 char. */
+
+      if (has_first_char)
+        {
+        if (first_char != first_char2)
+          while (current_subject < end_subject &&
+              *current_subject != first_char && *current_subject != first_char2)
+            current_subject++;
+        else
+          while (current_subject < end_subject &&
+                 *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 (current_subject[-1] == CHAR_CR &&
+               (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
+               current_subject < end_subject &&
+               *current_subject == CHAR_NL)
+            current_subject++;
+          }
+        }
+
+      /* Or to a non-unique first char after study */
+
+      else if (start_bits != NULL)
+        {
+        while (current_subject < end_subject)
+          {
+          register unsigned int c = *current_subject;
+#ifndef COMPILE_PCRE8
+          if (c > 255) c = 255;
+#endif
+          if ((start_bits[c/8] & (1 << (c&7))) == 0)
+            {
+            current_subject++;
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+            /* In non 8-bit mode, the iteration will stop for
+            characters > 255 at the beginning or not stop at all. */
+            if (utf)
+              ACROSSCHAR(current_subject < end_subject, *current_subject,
+                current_subject++);
+#endif
+            }
+          else break;
+          }
+        }
+      }
+
+    /* 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
+      bytes 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 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 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 int pp = *p++;
+              if (pp == req_char || pp == req_char2) { p--; break; }
+              }
+            }
+          else
+            {
+            while (p < end_subject)
+              {
+              if (*p++ == req_char) { p--; break; }
+              }
+            }
+
+          /* If we can't find the required character, break the matching loop,
+          which will cause a return or PCRE_ERROR_NOMATCH. */
+
+          if (p >= end_subject) 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;
+          }
+        }
+      }
+    }   /* 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) 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 (current_subject[-1] == CHAR_CR &&
+      current_subject < end_subject &&
+      *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/src/3rdparty/pcre/pcre_exec.c b/src/3rdparty/pcre/pcre_exec.c
new file mode 100644 (file)
index 0000000..2905808
--- /dev/null
@@ -0,0 +1,6960 @@
+/*************************************************
+*      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 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 PCRE_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
+
+/* 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_COMMIT       (-998)
+#define MATCH_KETRPOS      (-997)
+#define MATCH_ONCE         (-996)
+#define MATCH_PRUNE        (-995)
+#define MATCH_SKIP         (-994)
+#define MATCH_SKIP_ARG     (-993)
+#define MATCH_THEN         (-992)
+
+/* 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 };
+static const char rep_max[] = { 0, 0, 0, 0, 1, 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)
+{
+unsigned int c;
+if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
+while (length-- > 0)
+  if (isprint(c = *(p++))) printf("%c", 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 if not matched, otherwise the number of subject bytes matched
+*/
+
+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];
+
+#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). */
+
+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)
+  {
+#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UCP
+  if (md->utf)
+    {
+    /* Match characters up to the end of the reference. NOTE: the number of
+    bytes matched may differ, because there are some characters whose upper and
+    lower case versions code as 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)
+      {
+      int c, d;
+      if (eptr >= md->end_subject) return -1;
+      GETCHARINC(c, eptr);
+      GETCHARINC(d, p);
+      if (c != d && c != UCD_OTHERCASE(d)) return -1;
+      }
+    }
+  else
+#endif
+#endif
+
+  /* The same code works when not in UTF-8 mode and in UTF-8 mode when there
+  is no UCP support. */
+    {
+    if (eptr + length > md->end_subject) return -1;
+    while (length-- > 0)
+      {
+      if (TABLE_GET(*p, md->lcc, *p) != TABLE_GET(*eptr, md->lcc, *eptr)) return -1;
+      p++;
+      eptr++;
+      }
+    }
+  }
+
+/* In the caseful case, we can just compare the bytes, whether or not we
+are in UTF-8 mode. */
+
+else
+  {
+  if (eptr + length > md->end_subject) return -1;
+  while (length-- > 0) if (*p++ != *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 };
+
+/* 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 ", 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 = (heapframe *)(PUBL(stack_malloc))(sizeof(heapframe));\
+  if (newframe == NULL) RRETURN(PCRE_ERROR_NOMEMORY);\
+  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 (oldframe != &frame_zero) (PUBL(stack_free))(oldframe);\
+  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;
+
+  /* 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;
+  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;
+  int Xnumber;
+  int Xoffset;
+  int Xop;
+  int 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 unsigned int 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_zero;
+heapframe *frame = &frame_zero;
+frame->Xprevframe = NULL;            /* Marks the top level */
+
+/* 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;
+int prop_value;
+int prop_fail_result;
+int oclength;
+pcre_uchar occhars[6];
+#endif
+
+int codelink;
+int ctype;
+int length;
+int max;
+int min;
+int number;
+int offset;
+int op;
+int 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(ecode + 2, md->start_match_ptr) == 0)
+      {
+      md->start_match_ptr = eptr;
+      RRETURN(MATCH_SKIP);
+      }
+    RRETURN(rrc);
+
+    case OP_FAIL:
+    RRETURN(MATCH_NOMATCH);
+
+    /* COMMIT overrides PRUNE, SKIP, and THEN */
+
+    case OP_COMMIT:
+    RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+      eptrb, RM52);
+    if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE &&
+        rrc != MATCH_SKIP && rrc != MATCH_SKIP_ARG &&
+        rrc != MATCH_THEN)
+      RRETURN(rrc);
+    RRETURN(MATCH_COMMIT);
+
+    /* PRUNE overrides THEN */
+
+    case OP_PRUNE:
+    RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+      eptrb, RM51);
+    if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) 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 && rrc != MATCH_THEN) RRETURN(rrc);
+    RRETURN(MATCH_PRUNE);
+
+    /* SKIP overrides PRUNE and THEN */
+
+    case OP_SKIP:
+    RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+      eptrb, RM53);
+    if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN)
+      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. There is a flag that disables this opcode when re-matching a
+    pattern that ended with a SKIP for which there was not a matching MARK. */
+
+    case OP_SKIP_ARG:
+    if (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 && rrc != MATCH_PRUNE && rrc != MATCH_THEN)
+      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 the md->ignore_skip_arg flag set. */
+
+    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 */
+      {
+      md->match_function_type = MATCH_CBEGROUP;
+      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;
+      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;
+      }
+
+    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;
+          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);
+
+    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;
+        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;
+      }
+
+    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 if there is only one branch, but that's OK because that is
+    exactly what going to the ket would do. */
+
+    case OP_COND:
+    case OP_SCOND:
+    codelink = GET(ecode, 1);
+
+    /* Because of the way auto-callout works during compile, a callout item is
+    inserted between OP_COND and an assertion condition. */
+
+    if (ecode[LINK_SIZE+1] == OP_CALLOUT)
+      {
+      if (PUBL(callout) != NULL)
+        {
+        PUBL(callout_block) cb;
+        cb.version          = 2;   /* Version 1 of the callout block */
+        cb.callout_number   = ecode[LINK_SIZE+2];
+        cb.offset_vector    = md->offset_vector;
+#ifdef COMPILE_PCRE8
+        cb.subject          = (PCRE_SPTR)md->start_subject;
+#else
+        cb.subject          = (PCRE_SPTR16)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, LINK_SIZE + 3);
+        cb.next_item_length = GET(ecode, 3 + 2*LINK_SIZE);
+        cb.capture_top      = offset_top/2;
+        cb.capture_last     = md->capture_last;
+        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 += PRIV(OP_lengths)[OP_CALLOUT];
+      }
+
+    condcode = ecode[LINK_SIZE+1];
+
+    /* Now see what the actual condition is */
+
+    if (condcode == OP_RREF || condcode == OP_NRREF)    /* Recursion test */
+      {
+      if (md->recursive == NULL)                /* Not recursing => FALSE */
+        {
+        condition = FALSE;
+        ecode += GET(ecode, 1);
+        }
+      else
+        {
+        int recno = GET2(ecode, LINK_SIZE + 2);   /* Recursion group number*/
+        condition = (recno == RREF_ANY || recno == md->recursive->group_num);
+
+        /* If the test is for recursion into a specific subpattern, and it is
+        false, but the test was set up by name, scan the table to see if the
+        name refers to any other numbers, and test them. The condition is true
+        if any one is set. */
+
+        if (!condition && condcode == OP_NRREF)
+          {
+          pcre_uchar *slotA = md->name_table;
+          for (i = 0; i < md->name_count; i++)
+            {
+            if (GET2(slotA, 0) == recno) break;
+            slotA += md->name_entry_size;
+            }
+
+          /* Found a name for the number - there can be only one; duplicate
+          names for different numbers are allowed, but not vice versa. First
+          scan down for duplicates. */
+
+          if (i < md->name_count)
+            {
+            pcre_uchar *slotB = slotA;
+            while (slotB > md->name_table)
+              {
+              slotB -= md->name_entry_size;
+              if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
+                {
+                condition = GET2(slotB, 0) == md->recursive->group_num;
+                if (condition) break;
+                }
+              else break;
+              }
+
+            /* Scan up for duplicates */
+
+            if (!condition)
+              {
+              slotB = slotA;
+              for (i++; i < md->name_count; i++)
+                {
+                slotB += md->name_entry_size;
+                if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
+                  {
+                  condition = GET2(slotB, 0) == md->recursive->group_num;
+                  if (condition) break;
+                  }
+                else break;
+                }
+              }
+            }
+          }
+
+        /* Chose branch according to the condition */
+
+        ecode += condition? 1 + IMM2_SIZE : GET(ecode, 1);
+        }
+      }
+
+    else if (condcode == OP_CREF || condcode == OP_NCREF)  /* Group used test */
+      {
+      offset = GET2(ecode, LINK_SIZE+2) << 1;  /* Doubled ref number */
+      condition = offset < offset_top && md->offset_vector[offset] >= 0;
+
+      /* If the numbered capture is unset, but the reference was by name,
+      scan the table to see if the name refers to any other numbers, and test
+      them. The condition is true if any one is set. This is tediously similar
+      to the code above, but not close enough to try to amalgamate. */
+
+      if (!condition && condcode == OP_NCREF)
+        {
+        int refno = offset >> 1;
+        pcre_uchar *slotA = md->name_table;
+
+        for (i = 0; i < md->name_count; i++)
+          {
+          if (GET2(slotA, 0) == refno) break;
+          slotA += md->name_entry_size;
+          }
+
+        /* Found a name for the number - there can be only one; duplicate names
+        for different numbers are allowed, but not vice versa. First scan down
+        for duplicates. */
+
+        if (i < md->name_count)
+          {
+          pcre_uchar *slotB = slotA;
+          while (slotB > md->name_table)
+            {
+            slotB -= md->name_entry_size;
+            if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
+              {
+              offset = GET2(slotB, 0) << 1;
+              condition = offset < offset_top &&
+                md->offset_vector[offset] >= 0;
+              if (condition) break;
+              }
+            else break;
+            }
+
+          /* Scan up for duplicates */
+
+          if (!condition)
+            {
+            slotB = slotA;
+            for (i++; i < md->name_count; i++)
+              {
+              slotB += md->name_entry_size;
+              if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
+                {
+                offset = GET2(slotB, 0) << 1;
+                condition = offset < offset_top &&
+                  md->offset_vector[offset] >= 0;
+                if (condition) break;
+                }
+              else break;
+              }
+            }
+          }
+        }
+
+      /* Chose branch according to the condition */
+
+      ecode += condition? 1 + IMM2_SIZE : GET(ecode, 1);
+      }
+
+    else if (condcode == OP_DEF)     /* DEFINE - always false */
+      {
+      condition = FALSE;
+      ecode += GET(ecode, 1);
+      }
+
+    /* 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. */
+
+    else
+      {
+      md->match_function_type = MATCH_CONDASSERT;
+      RMATCH(eptr, ecode + 1 + LINK_SIZE, 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;
+        ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE + 2);
+        while (*ecode == OP_ALT) ecode += GET(ecode, 1);
+        }
+
+      /* PCRE doesn't allow the effect of (*THEN) to escape beyond an
+      assertion; it is therefore treated as NOMATCH. */
+
+      else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN)
+        {
+        RRETURN(rrc);         /* Need braces because of following else */
+        }
+      else
+        {
+        condition = FALSE;
+        ecode += codelink;
+        }
+      }
+
+    /* We are now at the branch that is to be obeyed. As there is only one, 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 == OP_ALT)
+      {
+      if (op != OP_SCOND)
+        {
+        ecode += 1 + LINK_SIZE;
+        goto TAIL_RECURSE;
+        }
+
+      md->match_function_type = MATCH_CBEGROUP;
+      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM49);
+      RRETURN(rrc);
+      }
+
+     /* Condition false & no alternative; continue after the group. */
+
+    else
+      {
+      ecode += 1 + LINK_SIZE;
+      }
+    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);
+    offset = number << 1;
+
+#ifdef PCRE_DEBUG
+      printf("end bracket %d at *ACCEPT", number);
+      printf("\n");
+#endif
+
+    md->capture_last = number;
+    if (offset >= md->offset_max) md->offset_overflow = TRUE; 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;
+
+    do
+      {
+      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM4);
+      if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
+        {
+        mstart = md->start_match_ptr;   /* In case \K reset it */
+        break;
+        }
+
+      /* PCRE does not allow THEN to escape beyond an assertion; it is treated
+      as NOMATCH. */
+
+      if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
+      ecode += GET(ecode, 1);
+      md->mark = save_mark;
+      }
+    while (*ecode == OP_ALT);
+
+    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 the 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. Encountering SKIP,
+    PRUNE, or COMMIT means we must assume failure without checking subsequent
+    branches. */
+
+    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;
+
+    do
+      {
+      RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM5);
+      md->mark = save_mark;
+      if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) RRETURN(MATCH_NOMATCH);
+      if (rrc == MATCH_SKIP || rrc == MATCH_PRUNE || rrc == MATCH_COMMIT)
+        {
+        do ecode += GET(ecode,1); while (*ecode == OP_ALT);
+        break;
+        }
+
+      /* PCRE does not allow THEN to escape beyond an assertion; it is treated
+      as NOMATCH. */
+
+      if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
+      ecode += GET(ecode,1);
+      }
+    while (*ecode == OP_ALT);
+
+    if (condassert) RRETURN(MATCH_MATCH);  /* Condition assertion */
+
+    ecode += 1 + LINK_SIZE;
+    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;
+#ifdef COMPILE_PCRE8
+      cb.subject          = (PCRE_SPTR)md->start_subject;
+#else
+      cb.subject          = (PCRE_SPTR16)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;
+      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;
+      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.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. 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->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 to escape beyond a recursion; it is treated
+        as NOMATCH. */
+
+        else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN)
+          {
+          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 = number;
+      if (offset >= md->offset_max) md->offset_overflow = TRUE; 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->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 */
+        {
+        md->match_function_type = MATCH_CBEGROUP;
+        RMATCH(eptr, prev, offset_top, md, eptrb, RM50);
+        RRETURN(rrc);
+        }
+      ecode = prev;
+      goto TAIL_RECURSE;
+      }
+    else  /* OP_KETRMAX */
+      {
+      if (*prev >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP;
+      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)) 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))
+      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 a single character type; inline for speed */
+
+    case OP_ANY:
+    if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
+    /* Fall through */
+
+    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 0x000d:
+      if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
+      break;
+
+      case 0x000a:
+      break;
+
+      case 0x000b:
+      case 0x000c:
+      case 0x0085:
+      case 0x2028:
+      case 0x2029:
+      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)
+      {
+      default: break;
+      case 0x09:      /* HT */
+      case 0x20:      /* SPACE */
+      case 0xa0:      /* NBSP */
+      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 */
+      RRETURN(MATCH_NOMATCH);
+      }
+    ecode++;
+    break;
+
+    case OP_HSPACE:
+    if (eptr >= md->end_subject)
+      {
+      SCHECK_PARTIAL();
+      RRETURN(MATCH_NOMATCH);
+      }
+    GETCHARINCTEST(c, eptr);
+    switch(c)
+      {
+      default: RRETURN(MATCH_NOMATCH);
+      case 0x09:      /* HT */
+      case 0x20:      /* SPACE */
+      case 0xa0:      /* NBSP */
+      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 */
+      break;
+      }
+    ecode++;
+    break;
+
+    case OP_NOT_VSPACE:
+    if (eptr >= md->end_subject)
+      {
+      SCHECK_PARTIAL();
+      RRETURN(MATCH_NOMATCH);
+      }
+    GETCHARINCTEST(c, eptr);
+    switch(c)
+      {
+      default: break;
+      case 0x0a:      /* LF */
+      case 0x0b:      /* VT */
+      case 0x0c:      /* FF */
+      case 0x0d:      /* CR */
+      case 0x85:      /* NEL */
+      case 0x2028:    /* LINE SEPARATOR */
+      case 0x2029:    /* PARAGRAPH SEPARATOR */
+      RRETURN(MATCH_NOMATCH);
+      }
+    ecode++;
+    break;
+
+    case OP_VSPACE:
+    if (eptr >= md->end_subject)
+      {
+      SCHECK_PARTIAL();
+      RRETURN(MATCH_NOMATCH);
+      }
+    GETCHARINCTEST(c, eptr);
+    switch(c)
+      {
+      default: RRETURN(MATCH_NOMATCH);
+      case 0x0a:      /* LF */
+      case 0x0b:      /* VT */
+      case 0x0c:      /* FF */
+      case 0x0d:      /* CR */
+      case 0x85:      /* NEL */
+      case 0x2028:    /* LINE SEPARATOR */
+      case 0x2029:    /* PARAGRAPH SEPARATOR */
+      break;
+      }
+    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 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;
+
+        case PT_SPACE:    /* Perl space */
+        if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
+             c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR)
+               == (op == OP_NOTPROP))
+          RRETURN(MATCH_NOMATCH);
+        break;
+
+        case PT_PXSPACE:  /* POSIX space */
+        if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
+             c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
+             c == CHAR_FF || c == CHAR_CR)
+               == (op == OP_NOTPROP))
+          RRETURN(MATCH_NOMATCH);
+        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;
+
+        /* 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);
+      }
+    GETCHARINCTEST(c, eptr);
+    if (UCD_CATEGORY(c) == ucp_M) RRETURN(MATCH_NOMATCH);
+    while (eptr < md->end_subject)
+      {
+      int len = 1;
+      if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
+      if (UCD_CATEGORY(c) != ucp_M) break;
+      eptr += len;
+      }
+    ecode++;
+    break;
+#endif
+
+
+    /* 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). */
+
+    case OP_REF:
+    case OP_REFI:
+    caseless = op == OP_REFI;
+    offset = GET2(ecode, 1) << 1;               /* Doubled ref number */
+    ecode += 1 + IMM2_SIZE;
+
+    /* 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. */
+
+    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 */
+
+    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)
+        {
+        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)
+        {
+        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)
+          {
+          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)
+          {
+          CHECK_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:
+        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 */
+        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;
+            }
+          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++;
+            }
+          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. This opcode is encountered only
+    when UTF-8 mode mode is supported. Nevertheless, we may not be in UTF-8
+    mode, because Unicode properties are supported in non-UTF-8 mode. */
+
+#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:
+        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 */
+        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;
+          }
+        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++ != *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)
+        {
+        if (md->lcc[fc]
+            != TABLE_GET(*eptr, md->lcc, *eptr)) 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
+        {
+        unsigned int 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. */
+
+    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
+        unsigned int 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;
+
+          for(;;)
+            {
+            RMATCH(eptr, ecode, offset_top, md, eptrb, RM23);
+            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+            if (eptr == pp) { RRETURN(MATCH_NOMATCH); }
+#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, 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++)
+        {
+        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)
+        {
+        for (fi = min;; fi++)
+          {
+          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);
+            }
+          if (fc != *eptr && foc != *eptr) RRETURN(MATCH_NOMATCH);
+          eptr++;
+          }
+        /* Control never gets here */
+        }
+      else  /* Maximize */
+        {
+        pp = eptr;
+        for (i = min; i < max; i++)
+          {
+          if (eptr >= md->end_subject)
+            {
+            SCHECK_PARTIAL();
+            break;
+            }
+          if (fc != *eptr && foc != *eptr) break;
+          eptr++;
+          }
+
+        if (possessive) continue;
+
+        while (eptr >= pp)
+          {
+          RMATCH(eptr, ecode, offset_top, md, eptrb, RM25);
+          eptr--;
+          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+          }
+        RRETURN(MATCH_NOMATCH);
+        }
+      /* 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 != *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 != *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 != *eptr) break;
+          eptr++;
+          }
+        if (possessive) continue;
+
+        while (eptr >= pp)
+          {
+          RMATCH(eptr, ecode, offset_top, md, eptrb, RM27);
+          eptr--;
+          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+          }
+        RRETURN(MATCH_NOMATCH);
+        }
+      }
+    /* 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);
+      }
+    ecode++;
+    GETCHARINCTEST(c, eptr);
+    if (op == OP_NOTI)         /* The caseless case */
+      {
+      register unsigned int ch, och;
+      ch = *ecode++;
+#ifdef COMPILE_PCRE8
+      /* ch must be < 128 if UTF is enabled. */
+      och = md->fcc[ch];
+#else
+#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UCP
+      if (utf && ch > 127)
+        och = UCD_OTHERCASE(ch);
+#else
+      if (utf && ch > 127)
+        och = ch;
+#endif /* SUPPORT_UCP */
+      else
+#endif /* SUPPORT_UTF */
+        och = TABLE_GET(ch, md->fcc, ch);
+#endif /* COMPILE_PCRE8 */
+      if (ch == c || och == c) RRETURN(MATCH_NOMATCH);
+      }
+    else    /* Caseful */
+      {
+      if (*ecode++ == c) RRETURN(MATCH_NOMATCH);
+      }
+    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:
+    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, eptr));
+
+    if (op >= OP_NOTSTARI)     /* 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 */
+
+#ifdef SUPPORT_UTF
+      if (utf)
+        {
+        register unsigned int 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
+      /* 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 unsigned int 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
+        /* 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 unsigned int 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;
+          for(;;)
+            {
+            RMATCH(eptr, ecode, offset_top, md, eptrb, RM30);
+            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;
+              }
+            if (fc == *eptr || foc == *eptr) break;
+            eptr++;
+            }
+          if (possessive) continue;
+          while (eptr >= pp)
+            {
+            RMATCH(eptr, ecode, offset_top, md, eptrb, RM31);
+            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+            eptr--;
+            }
+          }
+
+        RRETURN(MATCH_NOMATCH);
+        }
+      /* Control never gets here */
+      }
+
+    /* Caseful comparisons */
+
+    else
+      {
+#ifdef SUPPORT_UTF
+      if (utf)
+        {
+        register unsigned int 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 unsigned int 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 unsigned int 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;
+          for(;;)
+            {
+            RMATCH(eptr, ecode, offset_top, md, eptrb, RM34);
+            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;
+              }
+            if (fc == *eptr) break;
+            eptr++;
+            }
+          if (possessive) continue;
+          while (eptr >= pp)
+            {
+            RMATCH(eptr, ecode, offset_top, md, eptrb, RM35);
+            if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+            eptr--;
+            }
+          }
+
+        RRETURN(MATCH_NOMATCH);
+        }
+      }
+    /* 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;
+
+          case PT_SPACE:    /* Perl space */
+          for (i = 1; i <= min; i++)
+            {
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              RRETURN(MATCH_NOMATCH);
+              }
+            GETCHARINCTEST(c, eptr);
+            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
+                 c == CHAR_FF || c == CHAR_CR)
+                   == prop_fail_result)
+              RRETURN(MATCH_NOMATCH);
+            }
+          break;
+
+          case PT_PXSPACE:  /* POSIX space */
+          for (i = 1; i <= min; i++)
+            {
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              RRETURN(MATCH_NOMATCH);
+              }
+            GETCHARINCTEST(c, eptr);
+            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
+                 c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)
+                   == prop_fail_result)
+              RRETURN(MATCH_NOMATCH);
+            }
+          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;
+
+          /* 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);
+            }
+          GETCHARINCTEST(c, eptr);
+          if (UCD_CATEGORY(c) == ucp_M) RRETURN(MATCH_NOMATCH);
+          while (eptr < md->end_subject)
+            {
+            int len = 1;
+            if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
+            if (UCD_CATEGORY(c) != ucp_M) break;
+            eptr += len;
+            }
+          }
+        }
+
+      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);
+          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 0x000d:
+            if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
+            break;
+
+            case 0x000a:
+            break;
+
+            case 0x000b:
+            case 0x000c:
+            case 0x0085:
+            case 0x2028:
+            case 0x2029:
+            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)
+            {
+            default: break;
+            case 0x09:      /* HT */
+            case 0x20:      /* SPACE */
+            case 0xa0:      /* NBSP */
+            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 */
+            RRETURN(MATCH_NOMATCH);
+            }
+          }
+        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)
+            {
+            default: RRETURN(MATCH_NOMATCH);
+            case 0x09:      /* HT */
+            case 0x20:      /* SPACE */
+            case 0xa0:      /* NBSP */
+            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 */
+            break;
+            }
+          }
+        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)
+            {
+            default: break;
+            case 0x0a:      /* LF */
+            case 0x0b:      /* VT */
+            case 0x0c:      /* FF */
+            case 0x0d:      /* CR */
+            case 0x85:      /* NEL */
+            case 0x2028:    /* LINE SEPARATOR */
+            case 0x2029:    /* PARAGRAPH SEPARATOR */
+            RRETURN(MATCH_NOMATCH);
+            }
+          }
+        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)
+            {
+            default: RRETURN(MATCH_NOMATCH);
+            case 0x0a:      /* LF */
+            case 0x0b:      /* VT */
+            case 0x0c:      /* FF */
+            case 0x0d:      /* CR */
+            case 0x85:      /* NEL */
+            case 0x2028:    /* LINE SEPARATOR */
+            case 0x2029:    /* PARAGRAPH SEPARATOR */
+            break;
+            }
+          }
+        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++)
+          {
+          if (eptr >= md->end_subject)
+            {
+            SCHECK_PARTIAL();
+            RRETURN(MATCH_NOMATCH);
+            }
+          if (*eptr >= 128 || (md->ctypes[*eptr] & 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++)
+          {
+          if (eptr >= md->end_subject)
+            {
+            SCHECK_PARTIAL();
+            RRETURN(MATCH_NOMATCH);
+            }
+          if (*eptr < 128 && (md->ctypes[*eptr] & ctype_space) != 0)
+            RRETURN(MATCH_NOMATCH);
+          eptr++;
+          ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+          }
+        break;
+
+        case OP_WHITESPACE:
+        for (i = 1; i <= min; i++)
+          {
+          if (eptr >= md->end_subject)
+            {
+            SCHECK_PARTIAL();
+            RRETURN(MATCH_NOMATCH);
+            }
+          if (*eptr >= 128 || (md->ctypes[*eptr] & 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++)
+          {
+          if (eptr >= md->end_subject)
+            {
+            SCHECK_PARTIAL();
+            RRETURN(MATCH_NOMATCH);
+            }
+          if (*eptr < 128 && (md->ctypes[*eptr] & ctype_word) != 0)
+            RRETURN(MATCH_NOMATCH);
+          eptr++;
+          ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+          }
+        break;
+
+        case OP_WORDCHAR:
+        for (i = 1; i <= min; i++)
+          {
+          if (eptr >= md->end_subject)
+            {
+            SCHECK_PARTIAL();
+            RRETURN(MATCH_NOMATCH);
+            }
+          if (*eptr >= 128 || (md->ctypes[*eptr] & 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);
+          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 0x000d:
+            if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
+            break;
+
+            case 0x000a:
+            break;
+
+            case 0x000b:
+            case 0x000c:
+            case 0x0085:
+#ifdef COMPILE_PCRE16
+            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;
+            case 0x09:      /* HT */
+            case 0x20:      /* SPACE */
+            case 0xa0:      /* NBSP */
+#ifdef COMPILE_PCRE16
+            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 */
+#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);
+            case 0x09:      /* HT */
+            case 0x20:      /* SPACE */
+            case 0xa0:      /* NBSP */
+#ifdef COMPILE_PCRE16
+            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 */
+#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++)
+            {
+            default: break;
+            case 0x0a:      /* LF */
+            case 0x0b:      /* VT */
+            case 0x0c:      /* FF */
+            case 0x0d:      /* CR */
+            case 0x85:      /* NEL */
+#ifdef COMPILE_PCRE16
+            case 0x2028:    /* LINE SEPARATOR */
+            case 0x2029:    /* PARAGRAPH SEPARATOR */
+#endif
+            RRETURN(MATCH_NOMATCH);
+            }
+          }
+        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);
+            case 0x0a:      /* LF */
+            case 0x0b:      /* VT */
+            case 0x0c:      /* FF */
+            case 0x0d:      /* CR */
+            case 0x85:      /* NEL */
+#ifdef COMPILE_PCRE16
+            case 0x2028:    /* LINE SEPARATOR */
+            case 0x2029:    /* PARAGRAPH SEPARATOR */
+#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 */
+
+          case PT_SPACE:    /* Perl space */
+          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 ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
+                 c == CHAR_FF || c == CHAR_CR)
+                   == prop_fail_result)
+              RRETURN(MATCH_NOMATCH);
+            }
+          /* Control never gets here */
+
+          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);
+            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
+                 c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)
+                   == prop_fail_result)
+              RRETURN(MATCH_NOMATCH);
+            }
+          /* 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 */
+
+          /* 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);
+            }
+          GETCHARINCTEST(c, eptr);
+          if (UCD_CATEGORY(c) == ucp_M) RRETURN(MATCH_NOMATCH);
+          while (eptr < md->end_subject)
+            {
+            int len = 1;
+            if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
+            if (UCD_CATEGORY(c) != ucp_M) break;
+            eptr += len;
+            }
+          }
+        }
+      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 */
+            case OP_ALLANY:
+            case OP_ANYBYTE:
+            break;
+
+            case OP_ANYNL:
+            switch(c)
+              {
+              default: RRETURN(MATCH_NOMATCH);
+              case 0x000d:
+              if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
+              break;
+              case 0x000a:
+              break;
+
+              case 0x000b:
+              case 0x000c:
+              case 0x0085:
+              case 0x2028:
+              case 0x2029:
+              if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+              break;
+              }
+            break;
+
+            case OP_NOT_HSPACE:
+            switch(c)
+              {
+              default: break;
+              case 0x09:      /* HT */
+              case 0x20:      /* SPACE */
+              case 0xa0:      /* NBSP */
+              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 */
+              RRETURN(MATCH_NOMATCH);
+              }
+            break;
+
+            case OP_HSPACE:
+            switch(c)
+              {
+              default: RRETURN(MATCH_NOMATCH);
+              case 0x09:      /* HT */
+              case 0x20:      /* SPACE */
+              case 0xa0:      /* NBSP */
+              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 */
+              break;
+              }
+            break;
+
+            case OP_NOT_VSPACE:
+            switch(c)
+              {
+              default: break;
+              case 0x0a:      /* LF */
+              case 0x0b:      /* VT */
+              case 0x0c:      /* FF */
+              case 0x0d:      /* CR */
+              case 0x85:      /* NEL */
+              case 0x2028:    /* LINE SEPARATOR */
+              case 0x2029:    /* PARAGRAPH SEPARATOR */
+              RRETURN(MATCH_NOMATCH);
+              }
+            break;
+
+            case OP_VSPACE:
+            switch(c)
+              {
+              default: RRETURN(MATCH_NOMATCH);
+              case 0x0a:      /* LF */
+              case 0x0b:      /* VT */
+              case 0x0c:      /* FF */
+              case 0x0d:      /* CR */
+              case 0x85:      /* NEL */
+              case 0x2028:    /* LINE SEPARATOR */
+              case 0x2029:    /* PARAGRAPH SEPARATOR */
+              break;
+              }
+            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 */
+            case OP_ALLANY:
+            case OP_ANYBYTE:
+            break;
+
+            case OP_ANYNL:
+            switch(c)
+              {
+              default: RRETURN(MATCH_NOMATCH);
+              case 0x000d:
+              if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
+              break;
+
+              case 0x000a:
+              break;
+
+              case 0x000b:
+              case 0x000c:
+              case 0x0085:
+#ifdef COMPILE_PCRE16
+              case 0x2028:
+              case 0x2029:
+#endif
+              if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+              break;
+              }
+            break;
+
+            case OP_NOT_HSPACE:
+            switch(c)
+              {
+              default: break;
+              case 0x09:      /* HT */
+              case 0x20:      /* SPACE */
+              case 0xa0:      /* NBSP */
+#ifdef COMPILE_PCRE16
+              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 */
+#endif
+              RRETURN(MATCH_NOMATCH);
+              }
+            break;
+
+            case OP_HSPACE:
+            switch(c)
+              {
+              default: RRETURN(MATCH_NOMATCH);
+              case 0x09:      /* HT */
+              case 0x20:      /* SPACE */
+              case 0xa0:      /* NBSP */
+#ifdef COMPILE_PCRE16
+              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 */
+#endif
+              break;
+              }
+            break;
+
+            case OP_NOT_VSPACE:
+            switch(c)
+              {
+              default: break;
+              case 0x0a:      /* LF */
+              case 0x0b:      /* VT */
+              case 0x0c:      /* FF */
+              case 0x0d:      /* CR */
+              case 0x85:      /* NEL */
+#ifdef COMPILE_PCRE16
+              case 0x2028:    /* LINE SEPARATOR */
+              case 0x2029:    /* PARAGRAPH SEPARATOR */
+#endif
+              RRETURN(MATCH_NOMATCH);
+              }
+            break;
+
+            case OP_VSPACE:
+            switch(c)
+              {
+              default: RRETURN(MATCH_NOMATCH);
+              case 0x0a:      /* LF */
+              case 0x0b:      /* VT */
+              case 0x0c:      /* FF */
+              case 0x0d:      /* CR */
+              case 0x85:      /* NEL */
+#ifdef COMPILE_PCRE16
+              case 0x2028:    /* LINE SEPARATOR */
+              case 0x2029:    /* PARAGRAPH SEPARATOR */
+#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;
+
+          case PT_SPACE:    /* Perl space */
+          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) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
+                 c == CHAR_FF || c == CHAR_CR)
+                 == prop_fail_result)
+              break;
+            eptr+= len;
+            }
+          break;
+
+          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);
+            if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL ||
+                 c == CHAR_VT || c == CHAR_FF || c == CHAR_CR)
+                 == prop_fail_result)
+              break;
+            eptr+= len;
+            }
+          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;
+
+          default:
+          RRETURN(PCRE_ERROR_INTERNAL);
+          }
+
+        /* eptr is now past the end of the maximum run */
+
+        if (possessive) continue;
+        for(;;)
+          {
+          RMATCH(eptr, ecode, offset_top, md, eptrb, RM44);
+          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+          if (eptr-- == pp) break;        /* Stop if tried at original pos */
+          if (utf) BACKCHAR(eptr);
+          }
+        }
+
+      /* 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 = min; i < max; i++)
+          {
+          int len = 1;
+          if (eptr >= md->end_subject)
+            {
+            SCHECK_PARTIAL();
+            break;
+            }
+          if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
+          if (UCD_CATEGORY(c) == ucp_M) break;
+          eptr += len;
+          while (eptr < md->end_subject)
+            {
+            len = 1;
+            if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
+            if (UCD_CATEGORY(c) != ucp_M) break;
+            eptr += len;
+            }
+          }
+
+        /* eptr is now past the end of the maximum run */
+
+        if (possessive) continue;
+
+        for(;;)
+          {
+          RMATCH(eptr, ecode, offset_top, md, eptrb, RM45);
+          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+          if (eptr-- == pp) break;        /* Stop if tried at original pos */
+          for (;;)                        /* Move back over one extended */
+            {
+            if (!utf) c = *eptr; else
+              {
+              BACKCHAR(eptr);
+              GETCHAR(c, eptr);
+              }
+            if (UCD_CATEGORY(c) != ucp_M) break;
+            eptr--;
+            }
+          }
+        }
+
+      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;
+              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;
+              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 == 0x000d)
+              {
+              if (++eptr >= md->end_subject) break;
+              if (*eptr == 0x000a) eptr++;
+              }
+            else
+              {
+              if (c != 0x000a &&
+                  (md->bsr_anycrlf ||
+                   (c != 0x000b && c != 0x000c &&
+                    c != 0x0085 && c != 0x2028 && c != 0x2029)))
+                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)
+              {
+              default: gotspace = FALSE; break;
+              case 0x09:      /* HT */
+              case 0x20:      /* SPACE */
+              case 0xa0:      /* NBSP */
+              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 */
+              gotspace = TRUE;
+              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)
+              {
+              default: gotspace = FALSE; break;
+              case 0x0a:      /* LF */
+              case 0x0b:      /* VT */
+              case 0x0c:      /* FF */
+              case 0x0d:      /* CR */
+              case 0x85:      /* NEL */
+              case 0x2028:    /* LINE SEPARATOR */
+              case 0x2029:    /* PARAGRAPH SEPARATOR */
+              gotspace = TRUE;
+              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);
+          }
+
+        /* eptr is now past the end of the maximum run. If possessive, we are
+        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. */
+
+        if (possessive) continue;
+        for(;;)
+          {
+          RMATCH(eptr, ecode, offset_top, md, eptrb, RM46);
+          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+          if (eptr-- == pp) break;        /* Stop if tried at original pos */
+          BACKCHAR(eptr);
+          if (ctype == OP_ANYNL && eptr > pp  && *eptr == '\n' &&
+              eptr[-1] == '\r') 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;
+            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 == 0x000d)
+              {
+              if (++eptr >= md->end_subject) break;
+              if (*eptr == 0x000a) eptr++;
+              }
+            else
+              {
+              if (c != 0x000a && (md->bsr_anycrlf ||
+                (c != 0x000b && c != 0x000c && c != 0x0085
+#ifdef COMPILE_PCRE16
+                && 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;
+              }
+            c = *eptr;
+            if (c == 0x09 || c == 0x20 || c == 0xa0
+#ifdef COMPILE_PCRE16
+              || c == 0x1680 || c == 0x180e || (c >= 0x2000 && c <= 0x200A)
+              || c == 0x202f || c == 0x205f || c == 0x3000
+#endif
+              ) break;
+            eptr++;
+            }
+          break;
+
+          case OP_HSPACE:
+          for (i = min; i < max; i++)
+            {
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              break;
+              }
+            c = *eptr;
+            if (c != 0x09 && c != 0x20 && c != 0xa0
+#ifdef COMPILE_PCRE16
+              && c != 0x1680 && c != 0x180e && (c < 0x2000 || c > 0x200A)
+              && c != 0x202f && c != 0x205f && c != 0x3000
+#endif
+              ) break;
+            eptr++;
+            }
+          break;
+
+          case OP_NOT_VSPACE:
+          for (i = min; i < max; i++)
+            {
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              break;
+              }
+            c = *eptr;
+            if (c == 0x0a || c == 0x0b || c == 0x0c || c == 0x0d || c == 0x85
+#ifdef COMPILE_PCRE16
+              || c == 0x2028 || c == 0x2029
+#endif
+              ) break;
+            eptr++;
+            }
+          break;
+
+          case OP_VSPACE:
+          for (i = min; i < max; i++)
+            {
+            if (eptr >= md->end_subject)
+              {
+              SCHECK_PARTIAL();
+              break;
+              }
+            c = *eptr;
+            if (c != 0x0a && c != 0x0b && c != 0x0c && c != 0x0d && c != 0x85
+#ifdef COMPILE_PCRE16
+              && c != 0x2028 && c != 0x2029
+#endif
+              ) break;
+            eptr++;
+            }
+          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);
+          }
+
+        /* eptr is now past the end of the maximum run. If possessive, we are
+        done (no backing up). Otherwise, match at this position; anything other
+        than no match is immediately returned. For nomatch, back up one
+        character (byte), unless we are matching \R and the last thing matched
+        was \r\n, in which case, back up two bytes. */
+
+        if (possessive) continue;
+        while (eptr >= pp)
+          {
+          RMATCH(eptr, ecode, offset_top, md, eptrb, RM47);
+          if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+          eptr--;
+          if (ctype == OP_ANYNL && eptr > pp  && *eptr == '\n' &&
+              eptr[-1] == '\r') eptr--;
+          }
+        }
+
+      /* Get here if we can't make it match with any permitted repetitions */
+
+      RRETURN(MATCH_NOMATCH);
+      }
+    /* 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(21)
+#endif
+#ifdef SUPPORT_UTF
+  LBL(16) LBL(18) LBL(20)
+  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)
+#endif  /* SUPPORT_UCP */
+#endif  /* SUPPORT_UTF */
+  default:
+  DPRINTF(("jump error in pcre match: label %d non-existent\n", frame->Xwhere));
+
+printf("+++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
+
+/***************************************************************************
+***************************************************************************/
+
+
+
+/*************************************************
+*         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
+*/
+
+#ifdef 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)
+#else
+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)
+#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 req_char_ptr = start_match - 1;
+
+const pcre_study_data *study;
+const REAL_PCRE *re = (const REAL_PCRE *)argument_re;
+
+/* Check for the special magic call that measures the size of the stack used
+per recursive call of match(). */
+
+if (re == NULL && extra_data == NULL && subject == NULL && length == -999 &&
+    start_offset == -999)
+#ifdef NO_RECURSE
+  return -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 (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;
+      }
+#ifdef COMPILE_PCRE16
+    return (errorcode <= PCRE_UTF16_ERR1 && md->partial > 1)?
+      PCRE_ERROR_SHORTUTF16 : PCRE_ERROR_BADUTF16;
+#else
+    return (errorcode <= PCRE_UTF8_ERR5 && md->partial > 1)?
+      PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8;
+#endif
+    }
+
+  /* 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
+
+/* 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. In particular, JIT does not support partial
+matching. */
+
+#ifdef SUPPORT_JIT
+if (extra_data != NULL
+    && (extra_data->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0
+    && extra_data->executable_jit != NULL
+    && (extra_data->flags & PCRE_EXTRA_TABLES) == 0
+    && (options & ~(PCRE_NO_UTF8_CHECK | PCRE_NOTBOL | PCRE_NOTEOL |
+                    PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART)) == 0)
+  return PRIV(jit_exec)(re, extra_data->executable_jit,
+    (const pcre_uchar *)subject, length, start_offset, options,
+    ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0)
+    ? MATCH_LIMIT : extra_data->match_limit, offsets, offsetcount);
+#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;
+
+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;
+  }
+
+/* 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 = FALSE;
+
+/* 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->offset_overflow = FALSE;
+md->capture_last = -1;
+
+/* 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)
+      {
+      if (first_char != first_char2)
+        while (start_match < end_subject &&
+            *start_match != first_char && *start_match != first_char2)
+          start_match++;
+      else
+        while (start_match < end_subject && *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 &&
+             *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 unsigned int c = *start_match;
+#ifndef COMPILE_PCRE8
+        if (c > 255) c = 255;
+#endif
+        if ((start_bits[c/8] & (1 << (c&7))) == 0)
+          {
+          start_match++;
+#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+          /* In non 8-bit mode, the iteration will stop for
+          characters > 255 at the beginning or not stop at all. */
+          if (utf)
+            ACROSSCHAR(start_match < end_subject, *start_match,
+              start_match++);
+#endif
+          }
+        else break;
+        }
+      }
+    }   /* 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 int pp = *p++;
+            if (pp == req_char || pp == req_char2) { p--; break; }
+            }
+          }
+        else
+          {
+          while (p < end_subject)
+            {
+            if (*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;
+  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;
+
+  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 = TRUE;
+    break;
+
+    /* SKIP passes back the next starting point explicitly, but if it is the
+    same as 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 the ignore SKIP-with-argument flag. */
+
+    case MATCH_NOMATCH:
+    case MATCH_PRUNE:
+    case MATCH_THEN:
+    md->ignore_skip_arg = FALSE;
+    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->offset_overflow = TRUE;
+    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->offset_overflow && 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 = ocount;
+    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));
+  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));
+  return rc;
+  }
+
+/* Handle partial matches - disable any mark data */
+
+if (start_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);
+    }
+  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;
+return rc;
+}
+
+/* End of pcre_exec.c */
diff --git a/src/3rdparty/pcre/pcre_fullinfo.c b/src/3rdparty/pcre/pcre_fullinfo.c
new file mode 100644 (file)
index 0000000..e5e68f3
--- /dev/null
@@ -0,0 +1,202 @@
+/*************************************************
+*      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_fullinfo(), which returns
+information about a compiled pattern. */
+
+
+#ifdef PCRE_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
+*/
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_fullinfo(const pcre *argument_re, const pcre_extra *extra_data,
+  int what, void *where)
+#else
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_fullinfo(const pcre16 *argument_re, const pcre16_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)? re->first_char :
+    ((re->flags & PCRE_STARTLINE) != 0)? -1 : -2;
+  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)? re->req_char : -1;
+  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;
+
+  default: return PCRE_ERROR_BADOPTION;
+  }
+
+return 0;
+}
+
+/* End of pcre_fullinfo.c */
diff --git a/src/3rdparty/pcre/pcre_get.c b/src/3rdparty/pcre/pcre_get.c
new file mode 100644 (file)
index 0000000..daecb69
--- /dev/null
@@ -0,0 +1,587 @@
+/*************************************************
+*      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 PCRE_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
+*/
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_get_stringnumber(const pcre *code, const char *stringname)
+#else
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_get_stringnumber(const pcre16 *code, PCRE_SPTR16 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
+
+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
+*/
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_get_stringtable_entries(const pcre *code, const char *stringname,
+  char **firstptr, char **lastptr)
+#else
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_get_stringtable_entries(const pcre16 *code, PCRE_SPTR16 stringname,
+  PCRE_UCHAR16 **firstptr, PCRE_UCHAR16 **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
+
+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;
+      }
+#ifdef COMPILE_PCRE8
+    *firstptr = (char *)first;
+    *lastptr = (char *)last;
+#else
+    *firstptr = (PCRE_UCHAR16 *)first;
+    *lastptr = (PCRE_UCHAR16 *)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
+*/
+
+#ifdef COMPILE_PCRE8
+static int
+get_first_set(const pcre *code, const char *stringname, int *ovector)
+#else
+static int
+get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector)
+#endif
+{
+const REAL_PCRE *re = (const REAL_PCRE *)code;
+int entrysize;
+pcre_uchar *entry;
+#ifdef COMPILE_PCRE8
+char *first, *last;
+#else
+PCRE_UCHAR16 *first, *last;
+#endif
+
+#ifdef 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);
+#else
+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);
+#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
+*/
+
+#ifdef 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)
+#else
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_copy_substring(PCRE_SPTR16 subject, int *ovector, int stringcount,
+  int stringnumber, PCRE_UCHAR16 *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
+*/
+
+#ifdef 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)
+#else
+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)
+#endif
+{
+int n = get_first_set(code, stringname, ovector);
+if (n <= 0) return n;
+#ifdef COMPILE_PCRE8
+return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
+#else
+return pcre16_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
+*/
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_get_substring_list(const char *subject, int *ovector, int stringcount,
+  const char ***listptr)
+#else
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_get_substring_list(PCRE_SPTR16 subject, int *ovector, int stringcount,
+  PCRE_SPTR16 **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;
+
+#ifdef COMPILE_PCRE8
+*listptr = (const char **)stringlist;
+#else
+*listptr = (PCRE_SPTR16 *)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
+*/
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
+pcre_free_substring_list(const char **pointer)
+#else
+PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
+pcre16_free_substring_list(PCRE_SPTR16 *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
+*/
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_get_substring(const char *subject, int *ovector, int stringcount,
+  int stringnumber, const char **stringptr)
+#else
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_get_substring(PCRE_SPTR16 subject, int *ovector, int stringcount,
+  int stringnumber, PCRE_SPTR16 *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;
+#ifdef COMPILE_PCRE8
+*stringptr = (const char *)substring;
+#else
+*stringptr = (PCRE_SPTR16)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
+*/
+
+#ifdef 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)
+#else
+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)
+#endif
+{
+int n = get_first_set(code, stringname, ovector);
+if (n <= 0) return n;
+#ifdef COMPILE_PCRE8
+return pcre_get_substring(subject, ovector, stringcount, n, stringptr);
+#else
+return pcre16_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
+*/
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
+pcre_free_substring(const char *pointer)
+#else
+PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
+pcre16_free_substring(PCRE_SPTR16 pointer)
+#endif
+{
+(PUBL(free))((void *)pointer);
+}
+
+/* End of pcre_get.c */
diff --git a/src/3rdparty/pcre/pcre_globals.c b/src/3rdparty/pcre/pcre_globals.c
new file mode 100644 (file)
index 0000000..d5b6286
--- /dev/null
@@ -0,0 +1,84 @@
+/*************************************************
+*      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 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 PCRE_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;
+
+#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;
+#endif
+
+/* End of pcre_globals.c */
diff --git a/src/3rdparty/pcre/pcre_internal.h b/src/3rdparty/pcre/pcre_internal.h
new file mode 100644 (file)
index 0000000..e5a4b6a
--- /dev/null
@@ -0,0 +1,2332 @@
+/*************************************************
+*      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 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_" or "_pcre16_" 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. */
+#ifndef COMPILE_PCRE16
+#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 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_UTF8/16 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>
+
+/* 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;
+#elif UINT_MAX == 65535
+  typedef unsigned int pcre_uint16;
+  typedef int pcre_int16;
+#else
+  #error Cannot determine a type for 16-bit unsigned integers
+#endif
+
+#if UINT_MAX == 4294967295
+  typedef unsigned int pcre_uint32;
+  typedef int pcre_int32;
+#elif ULONG_MAX == 4294967295
+  typedef unsigned long int pcre_uint32;
+  typedef long int pcre_int32;
+#else
+  #error Cannot determine a type for 32-bit unsigned 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 HAVE_STDINT_H
+#include <stdint.h>
+#elif 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.
+*/
+
+#ifdef 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])
+
+#else
+
+#ifdef 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 IN_UCHARS(x) ((x) << 1)
+#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_PCRE16 */
+
+#endif /* COMPILE_PCRE8 */
+
+/* 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 && \
+     (p)[0] == NLBLOCK->nl[0] && \
+     (NLBLOCK->nllen == 1 || (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 && \
+     (p)[-NLBLOCK->nllen] == NLBLOCK->nl[0] && \
+     (NLBLOCK->nllen == 1 || (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"
+
+/* 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. */
+
+#ifdef 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
+
+#else /* COMPILE_PCRE8 */
+
+#ifdef COMPILE_PCRE16
+
+#if LINK_SIZE == 2
+
+#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
+
+#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
+
+#else
+#error Unsupported compiling mode
+#endif /* COMPILE_PCRE16 */
+
+#endif /* COMPILE_PCRE8 */
+
+/* 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. */
+
+#ifdef COMPILE_PCRE8
+
+#define IMM2_SIZE 2
+
+#define PUT2(a,n,d)   \
+  a[n] = (d) >> 8; \
+  a[(n)+1] = (d) & 255
+
+#define GET2(a,n) \
+  (((a)[n] << 8) | (a)[(n)+1])
+
+#else /* COMPILE_PCRE8 */
+
+#ifdef COMPILE_PCRE16
+
+#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_PCRE16 */
+
+#endif /* COMPILE_PCRE8 */
+
+#define PUT2INC(a,n,d)  PUT2(a,n,d), a += IMM2_SIZE
+
+/* When UTF encoding is being used, a character is no longer just a single
+character. The macros for character handling generate simple sequences when
+used in character-mode, and more complicated ones for UTF characters.
+GETCHARLENTEST and other macros are not used when UTF is not supported,
+so they are not defined. 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 */
+
+#ifdef 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)
+
+/* 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); \
+    }
+
+/* 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);
+
+/* 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; \
+      } \
+    }
+
+/* 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
+
+#else /* COMPILE_PCRE8 */
+
+#ifdef 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
+
+#endif
+
+#endif /* COMPILE_PCRE8 */
+
+#endif  /* SUPPORT_UTF */
+
+
+/* In case there is no definition of offsetof() provided - though any proper
+Standard C system should have one. */
+
+#ifndef offsetof
+#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field))
+#endif
+
+
+/* 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 now they
+are in a 16-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. */
+
+#ifdef COMPILE_PCRE8
+#define PCRE_MODE          0x0001  /* compiled in 8 bit mode */
+#endif
+#ifdef COMPILE_PCRE16
+#define PCRE_MODE          0x0002  /* compiled in 16 bit mode */
+#endif
+#define PCRE_FIRSTSET      0x0010  /* first_char is set */
+#define PCRE_FCH_CASELESS  0x0020  /* caseless first char */
+#define PCRE_REQCHSET      0x0040  /* req_byte is set */
+#define PCRE_RCH_CASELESS  0x0080  /* caseless requested char */
+#define PCRE_STARTLINE     0x0100  /* start after \n for multiline */
+#define PCRE_NOPARTIAL     0x0200  /* can't use partial with this regex */
+#define PCRE_JCHANGED      0x0400  /* j option used in regex */
+#define PCRE_HASCRORLF     0x0800  /* explicit \r or \n in pattern */
+#define PCRE_HASTHEN       0x1000  /* pattern contains (*THEN) */
+
+/* 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_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)
+
+#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
+
+/* 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' */
+
+/* Negative values for the firstchar and reqchar variables */
+
+#define REQ_UNSET (-2)
+#define REQ_NONE  (-1)
+
+/* 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 on both ASCII and EBCDIC platforms, in non-UTF-mode only. */
+
+#define CHAR_HT                     '\t'
+#define CHAR_VT                     '\v'
+#define CHAR_FF                     '\f'
+#define CHAR_CR                     '\r'
+#define CHAR_NL                     '\n'
+#define CHAR_BS                     '\b'
+#define CHAR_BEL                    '\a'
+#ifdef EBCDIC
+#define CHAR_ESC                    '\047'
+#define CHAR_DEL                    '\007'
+#else
+#define CHAR_ESC                    '\033'
+#define CHAR_DEL                    '\177'
+#endif
+
+#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_NL                      "\n"
+#define STR_BS                      "\b"
+#define STR_BEL                     "\a"
+#ifdef EBCDIC
+#define STR_ESC                     "\047"
+#define STR_DEL                     "\007"
+#else
+#define STR_ESC                     "\033"
+#define STR_DEL                     "\177"
+#endif
+
+#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_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)"
+#ifdef COMPILE_PCRE8
+#define STRING_UTF_RIGHTPAR            "UTF8)"
+#endif
+#ifdef COMPILE_PCRE16
+#define STRING_UTF_RIGHTPAR            "UTF16)"
+#endif
+#define STRING_UCP_RIGHTPAR            "UCP)"
+#define STRING_NO_START_OPT_RIGHTPAR   "NO_START_OPT)"
+
+#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_NL                     '\012'
+#define CHAR_BS                     '\010'
+#define CHAR_BEL                    '\007'
+#define CHAR_ESC                    '\033'
+#define CHAR_DEL                    '\177'
+
+#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_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
+#ifdef COMPILE_PCRE8
+#define STRING_UTF_RIGHTPAR            STR_U STR_T STR_F STR_8 STR_RIGHT_PARENTHESIS
+#endif
+#ifdef COMPILE_PCRE16
+#define STRING_UTF_RIGHTPAR            STR_U STR_T STR_F STR_1 STR_6 STR_RIGHT_PARENTHESIS
+#endif
+#define STRING_UCP_RIGHTPAR            STR_U STR_C STR_P 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
+
+#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_NL
+#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 */
+
+/* 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_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
+their negation. 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, when 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.
+
+The final escape must be ESC_REF as subsequent values are used for
+backreferences (\1, \2, \3, etc). 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,
+       ESC_REF };
+
+/* Opcode table: 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.
+
+*** NOTE NOTE NOTE *** Whenever this list is updated, the two macro definitions
+that follow must also be updated to match. There are also tables called
+"coptable" and "poptable" in pcre_dfa_exec.c that must be updated. */
+
+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 */
+  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 */
+
+  OP_CIRC,           /* 25 Start of line - not multiline */
+  OP_CIRCM,          /* 26 Start of line - multiline */
+  OP_DOLL,           /* 27 End of line - not multiline */
+  OP_DOLLM,          /* 28 End of line - multiline */
+  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. */
+
+  /**** Single 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 */
+
+  /**** Single 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 single 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 single 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 */
+
+  /* End of quantifier opcodes */
+
+  OP_CLASS,          /* 106 Match a character class, chars < 256 only */
+  OP_NCLASS,         /* 107 Same, but the bitmap was created from a negative
+                              class - the difference is relevant only when a
+                              character > 255 is encountered. */
+  OP_XCLASS,         /* 108 Extended class for handling > 255 chars within the
+                              class. This does both positive and negative. */
+  OP_REF,            /* 109 Match a back reference, casefully */
+  OP_REFI,           /* 110 Match a back reference, caselessly */
+  OP_RECURSE,        /* 111 Match a numbered subpattern (possibly recursive) */
+  OP_CALLOUT,        /* 112 Call out to external function if provided */
+
+  OP_ALT,            /* 113 Start of alternation */
+  OP_KET,            /* 114 End of group that doesn't have an unbounded repeat */
+  OP_KETRMAX,        /* 115 These two must remain together and in this */
+  OP_KETRMIN,        /* 116 order. They are for groups the repeat for ever. */
+  OP_KETRPOS,        /* 117 Possessive unlimited repeat. */
+
+  /* The assertions must come before BRA, CBRA, ONCE, and COND, and the four
+  asserts must remain in order. */
+
+  OP_REVERSE,        /* 118 Move pointer back - used in lookbehind assertions */
+  OP_ASSERT,         /* 119 Positive lookahead */
+  OP_ASSERT_NOT,     /* 120 Negative lookahead */
+  OP_ASSERTBACK,     /* 121 Positive lookbehind */
+  OP_ASSERTBACK_NOT, /* 122 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,           /* 123 Atomic group, contains captures */
+  OP_ONCE_NC,        /* 124 Atomic group containing no captures */
+  OP_BRA,            /* 125 Start of non-capturing bracket */
+  OP_BRAPOS,         /* 126 Ditto, with unlimited, possessive repeat */
+  OP_CBRA,           /* 127 Start of capturing bracket */
+  OP_CBRAPOS,        /* 128 Ditto, with unlimited, possessive repeat */
+  OP_COND,           /* 129 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,           /* 130 Start of non-capturing bracket, check empty  */
+  OP_SBRAPOS,        /* 131 Ditto, with unlimited, possessive repeat */
+  OP_SCBRA,          /* 132 Start of capturing bracket, check empty */
+  OP_SCBRAPOS,       /* 133 Ditto, with unlimited, possessive repeat */
+  OP_SCOND,          /* 134 Conditional group, check empty */
+
+  /* The next two pairs must (respectively) be kept together. */
+
+  OP_CREF,           /* 135 Used to hold a capture number as condition */
+  OP_NCREF,          /* 136 Same, but generated by a name reference*/
+  OP_RREF,           /* 137 Used to hold a recursion number as condition */
+  OP_NRREF,          /* 138 Same, but generated by a name reference*/
+  OP_DEF,            /* 139 The DEFINE condition */
+
+  OP_BRAZERO,        /* 140 These two must remain together and in this */
+  OP_BRAMINZERO,     /* 141 order. */
+  OP_BRAPOSZERO,     /* 142 */
+
+  /* These are backtracking control verbs */
+
+  OP_MARK,           /* 143 always has an argument */
+  OP_PRUNE,          /* 144 */
+  OP_PRUNE_ARG,      /* 145 same, but with argument */
+  OP_SKIP,           /* 146 */
+  OP_SKIP_ARG,       /* 147 same, but with argument */
+  OP_THEN,           /* 148 */
+  OP_THEN_ARG,       /* 149 same, but with argument */
+  OP_COMMIT,         /* 150 */
+
+  /* These are forced failure and success verbs */
+
+  OP_FAIL,           /* 151 */
+  OP_ACCEPT,         /* 152 */
+  OP_ASSERT_ACCEPT,  /* 153 Used inside assertions */
+  OP_CLOSE,          /* 154 Used before OP_ACCEPT to close open captures */
+
+  /* This is used to skip a subpattern with a {0} quantifier */
+
+  OP_SKIPZERO,       /* 155 */
+
+  /* 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 "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",                     \
+  "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 nref", "Cond rec", "Cond nrec", "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+(32/sizeof(pcre_uchar)),     /* CLASS                                  */ \
+  1+(32/sizeof(pcre_uchar)),     /* NCLASS                                 */ \
+  0,                             /* XCLASS - variable length               */ \
+  1+IMM2_SIZE,                   /* REF                                    */ \
+  1+IMM2_SIZE,                   /* REFI                                   */ \
+  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+IMM2_SIZE,      /* CREF, NCREF                            */ \
+  1+IMM2_SIZE, 1+IMM2_SIZE,      /* RREF, NRREF                            */ \
+  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 and OP_NRREF 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, ERRCOUNT };
+
+/* 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. For the case of compiled-on-4 and run-on-8, we include an extra
+pointer that is always NULL. For future-proofing, a few dummy fields were
+originally included - even though you can never get this planning right - but
+there is only one left now.
+
+NOTE NOTE NOTE:
+Because people can now save and re-use compiled patterns, any additions to this
+structure should be made at the end, and something earlier (e.g. a new
+flag in the options or one of the dummy fields) should indicate that the new
+fields are present. Currently PCRE always sets the dummy fields to zero.
+NOTE NOTE NOTE
+*/
+
+#ifdef COMPILE_PCRE8
+#define REAL_PCRE real_pcre
+#else
+#define REAL_PCRE real_pcre16
+#endif
+
+typedef struct REAL_PCRE {
+  pcre_uint32 magic_number;
+  pcre_uint32 size;               /* Total that was malloced */
+  pcre_uint32 options;            /* Public options */
+  pcre_uint16 flags;              /* Private flags */
+  pcre_uint16 dummy1;             /* For future use */
+  pcre_uint16 top_bracket;
+  pcre_uint16 top_backref;
+  pcre_uint16 first_char;         /* Starting character */
+  pcre_uint16 req_char;           /* This character must be seen */
+  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 */
+
+  const pcre_uint8 *tables;       /* Pointer to tables or NULL for std */
+  const pcre_uint8 *nullpad;      /* NULL padding */
+} REAL_PCRE;
+
+/* 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 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 */
+  open_capitem *open_caps;          /* Chain of open capture items */
+  pcre_uchar *hwm;                  /* High watermark of workspace */
+  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  workspace_size;              /* Size of workspace */
+  int  bracount;                    /* Count of capturing parens as we compile */
+  int  final_bracount;              /* Saved value after first pass */
+  int  top_backref;                 /* Maximum back reference */
+  unsigned int backref_map;         /* Bitmap of low back refs */
+  int  assert_depth;                /* Depth of nested assertions */
+  int  external_options;            /* External (initial) options */
+  int  external_flags;              /* External flag bits to be set */
+  int  req_varyopt;                 /* "After variable item" flag for reqbyte */
+  BOOL had_accept;                  /* (*ACCEPT) encountered */
+  BOOL check_lookbehind;            /* Lookbehinds need later checking */
+  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) */
+  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 */
+  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 */
+  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   offset_overflow;         /* Set if too many extractions */
+  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) */
+  BOOL   ignore_skip_arg;         /* For re-run when SKIP name not found */
+  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 */
+  int    capture_last;            /* Most recent capture number */
+  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 */
+} 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 prefix */
+
+#ifdef COMPILE_PCRE8
+#ifndef PUBL
+#define PUBL(name) pcre_##name
+#endif
+#ifndef PRIV
+#define PRIV(name) _pcre_##name
+#endif
+#else /* COMPILE_PCRE8 */
+#ifdef COMPILE_PCRE16
+#ifndef PUBL
+#define PUBL(name) pcre16_##name
+#endif
+#ifndef PRIV
+#define PRIV(name) _pcre16_##name
+#endif
+#else
+#error Unsupported compiling mode
+#endif /* COMPILE_PCRE16 */
+#endif /* COMPILE_PCRE8 */
+
+/* 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(default_tables)[];
+
+extern const pcre_uint8     PRIV(OP_lengths)[];
+
+
+/* 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. */
+#ifdef 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)
+
+#else
+
+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_PCRE8 */
+
+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 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)(int, const pcre_uchar *, BOOL);
+
+#ifdef SUPPORT_JIT
+extern void              PRIV(jit_compile)(const REAL_PCRE *, PUBL(extra) *);
+extern int               PRIV(jit_exec)(const REAL_PCRE *, void *,
+                           const pcre_uchar *, int, 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;
+  pcre_uint8 chartype;
+  pcre_int32 other_case;
+} ucd_record;
+
+extern const ucd_record  PRIV(ucd_records)[];
+extern const pcre_uint8  PRIV(ucd_stage1)[];
+extern const pcre_uint16 PRIV(ucd_stage2)[];
+extern const int         PRIV(ucp_gentype)[];
+#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)[(ch) / UCD_BLOCK_SIZE] * \
+        UCD_BLOCK_SIZE + (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_OTHERCASE(ch) (ch + GET_UCD(ch)->other_case)
+
+#endif /* SUPPORT_UCP */
+
+#endif
+
+/* End of pcre_internal.h */
diff --git a/src/3rdparty/pcre/pcre_jit_compile.c b/src/3rdparty/pcre/pcre_jit_compile.c
new file mode 100644 (file)
index 0000000..f3d240d
--- /dev/null
@@ -0,0 +1,6915 @@
+/*************************************************
+*      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
+
+  The machine code generator part (this module) was written by Zoltan Herczeg
+                      Copyright (c) 2010-2012
+
+-----------------------------------------------------------------------------
+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 PCRE_HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+#ifdef 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
+
+/* Allocate memory on the stack. Fast, but limited size. */
+#define LOCAL_SPACE_SIZE 32768
+
+#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 fallback_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 hot path (expected path), and the other is called as
+the 'fallback' path. Branch instructions are expesive for all CPUs, so we avoid taken
+branches on the hot path.
+
+ Greedy star operator (*) :
+   Hot path: match happens.
+   Fallback path: match failed.
+ Non-greedy star operator (*?) :
+   Hot path: no need to perform a match.
+   Fallback 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 hot path
+ '(' hot path (pushing arguments to the stack)
+ B hot path
+ ')' hot path (pushing arguments to the stack)
+ D hot path
+ return with successful match
+
+ D fallback path
+ ')' fallback path (If we arrived from "C" jump to the fallback of "C")
+ B fallback path
+ C expected path
+ jump to D hot path
+ C fallback path
+ A fallback path
+
+ Notice, that the order of fallback 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 fallback code path. The fallback code path must check
+ whether there is a next alternative. If so, it needs to jump back to
+ the hot path eventually. Otherwise it needs to clear out its own stack
+ frame and continue the execution on the fallback code paths.
+*/
+
+/*
+Saved stack frames:
+
+Atomic blocks and asserts require reloading the values of local variables
+when the fallback mechanism performed. Because of OP_RECURSE, the locals
+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 locals 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 *ptr;
+  /* Everything else after. */
+  int offsetcount;
+  int calllimit;
+  pcre_uint8 notbol;
+  pcre_uint8 noteol;
+  pcre_uint8 notempty;
+  pcre_uint8 notempty_atstart;
+} jit_arguments;
+
+typedef struct executable_function {
+  void *executable_func;
+  PUBL(jit_callback) callback;
+  void *userdata;
+  sljit_uw executable_size;
+} executable_function;
+
+typedef struct jump_list {
+  struct sljit_jump *jump;
+  struct jump_list *next;
+} jump_list;
+
+enum stub_types { stack_alloc };
+
+typedef struct stub_list {
+  enum stub_types type;
+  int data;
+  struct sljit_jump *start;
+  struct sljit_label *leave;
+  struct stub_list *next;
+} stub_list;
+
+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_hotpath, and contains
+the aguments for compile_fallbackpath. Must be the first member
+of its descendants. */
+typedef struct fallback_common {
+  /* Concatenation stack. */
+  struct fallback_common *prev;
+  jump_list *nextfallbacks;
+  /* Internal stack (for component operators). */
+  struct fallback_common *top;
+  jump_list *topfallbacks;
+  /* Opcode pointer. */
+  pcre_uchar *cc;
+} fallback_common;
+
+typedef struct assert_fallback {
+  fallback_common common;
+  jump_list *condfailed;
+  /* Less than 0 (-1) if a frame is not needed. */
+  int framesize;
+  /* Points to our private memory word on the stack. */
+  int localptr;
+  /* For iterators. */
+  struct sljit_label *hotpath;
+} assert_fallback;
+
+typedef struct bracket_fallback {
+  fallback_common common;
+  /* Where to coninue if an alternative is successfully matched. */
+  struct sljit_label *althotpath;
+  /* For rmin and rmax iterators. */
+  struct sljit_label *recursivehotpath;
+  /* For greedy ? operator. */
+  struct sljit_label *zerohotpath;
+  /* Contains the branches of a failed condition. */
+  union {
+    /* Both for OP_COND, OP_SCOND. */
+    jump_list *condfailed;
+    assert_fallback *assert;
+    /* For OP_ONCE. -1 if not needed. */
+    int framesize;
+  } u;
+  /* Points to our private memory word on the stack. */
+  int localptr;
+} bracket_fallback;
+
+typedef struct bracketpos_fallback {
+  fallback_common common;
+  /* Points to our private memory word on the stack. */
+  int localptr;
+  /* Reverting stack is needed. */
+  int framesize;
+  /* Allocated stack size. */
+  int stacksize;
+} bracketpos_fallback;
+
+typedef struct braminzero_fallback {
+  fallback_common common;
+  struct sljit_label *hotpath;
+} braminzero_fallback;
+
+typedef struct iterator_fallback {
+  fallback_common common;
+  /* Next iteration. */
+  struct sljit_label *hotpath;
+} iterator_fallback;
+
+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. */
+  int start;
+} recurse_entry;
+
+typedef struct recurse_fallback {
+  fallback_common common;
+} recurse_fallback;
+
+typedef struct compiler_common {
+  struct sljit_compiler *compiler;
+  pcre_uchar *start;
+  int localsize;
+  int *localptrs;
+  const pcre_uint8 *fcc;
+  sljit_w lcc;
+  int cbraptr;
+  int nltype;
+  int newline;
+  int bsr_nltype;
+  int endonly;
+  sljit_w ctypes;
+  sljit_uw name_table;
+  sljit_w name_count;
+  sljit_w name_entry_size;
+  struct sljit_label *acceptlabel;
+  stub_list *stubs;
+  recurse_entry *entries;
+  recurse_entry *currententry;
+  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;
+  BOOL jscript_compat;
+#ifdef SUPPORT_UTF
+  BOOL utf;
+#ifdef SUPPORT_UCP
+  BOOL use_ucp;
+#endif
+  jump_list *utfreadchar;
+#ifdef COMPILE_PCRE8
+  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_i asint;
+    sljit_uh asushort;
+#ifdef COMPILE_PCRE8
+    sljit_ub asbyte;
+    sljit_ub asuchars[4];
+#else
+#ifdef COMPILE_PCRE16
+    sljit_uh asuchars[2];
+#endif
+#endif
+  } c;
+  union {
+    sljit_i asint;
+    sljit_uh asushort;
+#ifdef COMPILE_PCRE8
+    sljit_ub asbyte;
+    sljit_ub asuchars[4];
+#else
+#ifdef COMPILE_PCRE16
+    sljit_uh asuchars[2];
+#endif
+#endif
+  } oc;
+#endif
+} compare_context;
+
+enum {
+  frame_end = 0,
+  frame_setstrbegin = -1
+};
+
+/* Undefine sljit macros. */
+#undef CMP
+
+/* Used for accessing the elements of the stack. */
+#define STACK(i)      ((-(i) - 1) * (int)sizeof(sljit_w))
+
+#define TMP1          SLJIT_TEMPORARY_REG1
+#define TMP2          SLJIT_TEMPORARY_REG3
+#define TMP3          SLJIT_TEMPORARY_EREG2
+#define STR_PTR       SLJIT_SAVED_REG1
+#define STR_END       SLJIT_SAVED_REG2
+#define STACK_TOP     SLJIT_TEMPORARY_REG2
+#define STACK_LIMIT   SLJIT_SAVED_REG3
+#define ARGUMENTS     SLJIT_SAVED_EREG1
+#define CALL_COUNT    SLJIT_SAVED_EREG2
+#define RETURN_ADDR   SLJIT_TEMPORARY_EREG1
+
+/* Locals layout. */
+/* These two locals can be used by the current opcode. */
+#define LOCALS0          (0 * sizeof(sljit_w))
+#define LOCALS1          (1 * sizeof(sljit_w))
+/* Two local variables for possessive quantifiers (char1 cannot use them). */
+#define POSSESSIVE0      (2 * sizeof(sljit_w))
+#define POSSESSIVE1      (3 * sizeof(sljit_w))
+/* Head of the last recursion. */
+#define RECURSIVE_HEAD   (4 * sizeof(sljit_w))
+/* Max limit of recursions. */
+#define CALL_LIMIT       (5 * sizeof(sljit_w))
+/* Last known position of the requested byte. */
+#define REQ_CHAR_PTR     (6 * sizeof(sljit_w))
+/* End pointer of the first line. */
+#define FIRSTLINE_END    (7 * sizeof(sljit_w))
+/* 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    (8 * sizeof(sljit_w))
+#define OVECTOR(i)       (OVECTOR_START + (i) * sizeof(sljit_w))
+#define OVECTOR_PRIV(i)  (common->cbraptr + (i) * sizeof(sljit_w))
+#define PRIV_DATA(cc)    (common->localptrs[(cc) - common->start])
+
+#ifdef COMPILE_PCRE8
+#define MOV_UCHAR  SLJIT_MOV_UB
+#define MOVU_UCHAR SLJIT_MOVU_UB
+#else
+#ifdef COMPILE_PCRE16
+#define MOV_UCHAR  SLJIT_MOV_UH
+#define MOVU_UCHAR SLJIT_MOVU_UH
+#else
+#error Unsupported compiling mode
+#endif
+#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 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 COND_VALUE(op, dst, dstw, type) \
+  sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type))
+
+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;
+}
+
+/* Functions whose might need modification for all new supported opcodes:
+ next_opcode
+ get_localspace
+ set_localptrs
+ get_framesize
+ init_frame
+ get_localsize
+ copy_locals
+ compile_hotpath
+ compile_fallbackpath
+*/
+
+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_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_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:
+  case OP_CRSTAR:
+  case OP_CRMINSTAR:
+  case OP_CRPLUS:
+  case OP_CRMINPLUS:
+  case OP_CRQUERY:
+  case OP_CRMINQUERY:
+  case OP_DEF:
+  case OP_BRAZERO:
+  case OP_BRAMINZERO:
+  case OP_BRAPOSZERO:
+  case OP_FAIL:
+  case OP_ACCEPT:
+  case OP_ASSERT_ACCEPT:
+  case OP_SKIPZERO:
+  return cc + 1;
+
+  case OP_ANYBYTE:
+#ifdef SUPPORT_UTF
+  if (common->utf) return NULL;
+#endif
+  return cc + 1;
+
+  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_POSSTAR:
+  case OP_POSPLUS:
+  case OP_POSQUERY:
+  case OP_STARI:
+  case OP_MINSTARI:
+  case OP_PLUSI:
+  case OP_MINPLUSI:
+  case OP_QUERYI:
+  case OP_MINQUERYI:
+  case OP_POSSTARI:
+  case OP_POSPLUSI:
+  case OP_POSQUERYI:
+  case OP_NOTSTAR:
+  case OP_NOTMINSTAR:
+  case OP_NOTPLUS:
+  case OP_NOTMINPLUS:
+  case OP_NOTQUERY:
+  case OP_NOTMINQUERY:
+  case OP_NOTPOSSTAR:
+  case OP_NOTPOSPLUS:
+  case OP_NOTPOSQUERY:
+  case OP_NOTSTARI:
+  case OP_NOTMINSTARI:
+  case OP_NOTPLUSI:
+  case OP_NOTMINPLUSI:
+  case OP_NOTQUERYI:
+  case OP_NOTMINQUERYI:
+  case OP_NOTPOSSTARI:
+  case OP_NOTPOSPLUSI:
+  case OP_NOTPOSQUERYI:
+  cc += 2;
+#ifdef SUPPORT_UTF
+  if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+  return cc;
+
+  case OP_UPTO:
+  case OP_MINUPTO:
+  case OP_EXACT:
+  case OP_POSUPTO:
+  case OP_UPTOI:
+  case OP_MINUPTOI:
+  case OP_EXACTI:
+  case OP_POSUPTOI:
+  case OP_NOTUPTO:
+  case OP_NOTMINUPTO:
+  case OP_NOTEXACT:
+  case OP_NOTPOSUPTO:
+  case OP_NOTUPTOI:
+  case OP_NOTMINUPTOI:
+  case OP_NOTEXACTI:
+  case OP_NOTPOSUPTOI:
+  cc += 2 + IMM2_SIZE;
+#ifdef SUPPORT_UTF
+  if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+  return cc;
+
+  case OP_NOTPROP:
+  case OP_PROP:
+  return cc + 1 + 2;
+
+  case OP_TYPEUPTO:
+  case OP_TYPEMINUPTO:
+  case OP_TYPEEXACT:
+  case OP_TYPEPOSUPTO:
+  case OP_REF:
+  case OP_REFI:
+  case OP_CREF:
+  case OP_NCREF:
+  case OP_RREF:
+  case OP_NRREF:
+  case OP_CLOSE:
+  cc += 1 + IMM2_SIZE;
+  return cc;
+
+  case OP_CRRANGE:
+  case OP_CRMINRANGE:
+  return cc + 1 + 2 * IMM2_SIZE;
+
+  case OP_CLASS:
+  case OP_NCLASS:
+  return cc + 1 + 32 / sizeof(pcre_uchar);
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+  case OP_XCLASS:
+  return cc + GET(cc, 1);
+#endif
+
+  case OP_RECURSE:
+  case OP_ASSERT:
+  case OP_ASSERT_NOT:
+  case OP_ASSERTBACK:
+  case OP_ASSERTBACK_NOT:
+  case OP_REVERSE:
+  case OP_ONCE:
+  case OP_ONCE_NC:
+  case OP_BRA:
+  case OP_BRAPOS:
+  case OP_COND:
+  case OP_SBRA:
+  case OP_SBRAPOS:
+  case OP_SCOND:
+  case OP_ALT:
+  case OP_KET:
+  case OP_KETRMAX:
+  case OP_KETRMIN:
+  case OP_KETRPOS:
+  return cc + 1 + LINK_SIZE;
+
+  case OP_CBRA:
+  case OP_CBRAPOS:
+  case OP_SCBRA:
+  case OP_SCBRAPOS:
+  return cc + 1 + LINK_SIZE + IMM2_SIZE;
+
+  default:
+  return NULL;
+  }
+}
+
+static int get_localspace(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)
+{
+int localspace = 0;
+pcre_uchar *alternative;
+/* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
+while (cc < ccend)
+  {
+  switch(*cc)
+    {
+    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:
+    localspace += sizeof(sljit_w);
+    cc += 1 + LINK_SIZE;
+    break;
+
+    case OP_CBRAPOS:
+    case OP_SCBRAPOS:
+    localspace += sizeof(sljit_w);
+    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)
+      localspace += sizeof(sljit_w);
+    cc += 1 + LINK_SIZE;
+    break;
+
+    default:
+    cc = next_opcode(common, cc);
+    if (cc == NULL)
+      return -1;
+    break;
+    }
+  }
+return localspace;
+}
+
+static void set_localptrs(compiler_common *common, int localptr, pcre_uchar *ccend)
+{
+pcre_uchar *cc = common->start;
+pcre_uchar *alternative;
+while (cc < ccend)
+  {
+  switch(*cc)
+    {
+    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->localptrs[cc - common->start] = localptr;
+    localptr += sizeof(sljit_w);
+    cc += 1 + LINK_SIZE;
+    break;
+
+    case OP_CBRAPOS:
+    case OP_SCBRAPOS:
+    common->localptrs[cc - common->start] = localptr;
+    localptr += sizeof(sljit_w);
+    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)
+      {
+      common->localptrs[cc - common->start] = localptr;
+      localptr += sizeof(sljit_w);
+      }
+    cc += 1 + LINK_SIZE;
+    break;
+
+    default:
+    cc = next_opcode(common, cc);
+    SLJIT_ASSERT(cc != NULL);
+    break;
+    }
+  }
+}
+
+/* Returns with -1 if no need for frame. */
+static int get_framesize(compiler_common *common, pcre_uchar *cc, BOOL recursive)
+{
+pcre_uchar *ccend = bracketend(cc);
+int length = 0;
+BOOL possessive = FALSE;
+BOOL setsom_found = FALSE;
+
+if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))
+  {
+  length = 3;
+  possessive = TRUE;
+  }
+
+cc = next_opcode(common, cc);
+SLJIT_ASSERT(cc != NULL);
+while (cc < ccend)
+  switch(*cc)
+    {
+    case OP_SET_SOM:
+    case OP_RECURSE:
+    if (!setsom_found)
+      {
+      length += 2;
+      setsom_found = TRUE;
+      }
+    cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE;
+    break;
+
+    case OP_CBRA:
+    case OP_CBRAPOS:
+    case OP_SCBRA:
+    case OP_SCBRAPOS:
+    length += 3;
+    cc += 1 + LINK_SIZE + IMM2_SIZE;
+    break;
+
+    default:
+    cc = next_opcode(common, cc);
+    SLJIT_ASSERT(cc != NULL);
+    break;
+    }
+
+/* Possessive quantifiers can use a special case. */
+if (SLJIT_UNLIKELY(possessive) && length == 3)
+  return -1;
+
+if (length > 0)
+  return length + 1;
+return -1;
+}
+
+static void init_frame(compiler_common *common, pcre_uchar *cc, int stackpos, int stacktop, BOOL recursive)
+{
+DEFINE_COMPILER;
+pcre_uchar *ccend = bracketend(cc);
+BOOL setsom_found = FALSE;
+int offset;
+
+/* >= 1 + shortest item size (2) */
+SLJIT_UNUSED_ARG(stacktop);
+SLJIT_ASSERT(stackpos >= stacktop + 2);
+
+stackpos = STACK(stackpos);
+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:
+    case OP_RECURSE:
+    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, frame_setstrbegin);
+      stackpos += (int)sizeof(sljit_w);
+      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
+      stackpos += (int)sizeof(sljit_w);
+      setsom_found = TRUE;
+      }
+    cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE;
+    break;
+
+    case OP_CBRA:
+    case OP_CBRAPOS:
+    case OP_SCBRA:
+    case OP_SCBRAPOS:
+    offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
+    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));
+    stackpos += (int)sizeof(sljit_w);
+    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_w);
+    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);
+    stackpos += (int)sizeof(sljit_w);
+
+    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, frame_end);
+SLJIT_ASSERT(stackpos == STACK(stacktop));
+}
+
+static SLJIT_INLINE int get_localsize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)
+{
+int localsize = 2;
+pcre_uchar *alternative;
+/* Calculate the sum of the local variables. */
+while (cc < ccend)
+  {
+  switch(*cc)
+    {
+    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:
+    localsize++;
+    cc += 1 + LINK_SIZE;
+    break;
+
+    case OP_CBRA:
+    case OP_SCBRA:
+    localsize++;
+    cc += 1 + LINK_SIZE + IMM2_SIZE;
+    break;
+
+    case OP_CBRAPOS:
+    case OP_SCBRAPOS:
+    localsize += 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)
+      localsize++;
+    cc += 1 + LINK_SIZE;
+    break;
+
+    default:
+    cc = next_opcode(common, cc);
+    SLJIT_ASSERT(cc != NULL);
+    break;
+    }
+  }
+SLJIT_ASSERT(cc == ccend);
+return localsize;
+}
+
+static void copy_locals(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend,
+  BOOL save, int stackptr, int stacktop)
+{
+DEFINE_COMPILER;
+int srcw[2];
+int count;
+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 += sizeof(sljit_w);
+  if (stackptr < stacktop)
+    {
+    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
+    stackptr += sizeof(sljit_w);
+    tmp1empty = FALSE;
+    }
+  if (stackptr < stacktop)
+    {
+    OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
+    stackptr += sizeof(sljit_w);
+    tmp2empty = FALSE;
+    }
+  /* The tmp1next must be TRUE in either way. */
+  }
+
+while (status != end)
+  {
+  count = 0;
+  switch(status)
+    {
+    case start:
+    SLJIT_ASSERT(save);
+    count = 1;
+    srcw[0] = RECURSIVE_HEAD;
+    status = loop;
+    break;
+
+    case loop:
+    if (cc >= ccend)
+      {
+      status = end;
+      break;
+      }
+
+    switch(*cc)
+      {
+      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] = PRIV_DATA(cc);
+      SLJIT_ASSERT(srcw[0] != 0);
+      cc += 1 + LINK_SIZE;
+      break;
+
+      case OP_CBRA:
+      case OP_SCBRA:
+      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[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
+      srcw[0] = PRIV_DATA(cc);
+      SLJIT_ASSERT(srcw[0] != 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] = PRIV_DATA(cc);
+        SLJIT_ASSERT(srcw[0] != 0);
+        }
+      cc += 1 + LINK_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_w);
+          }
+        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_w);
+          }
+        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_w);
+          }
+        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_w);
+          }
+        tmp1next = TRUE;
+        }
+      }
+    }
+  }
+
+if (save)
+  {
+  if (tmp1next)
+    {
+    if (!tmp1empty)
+      {
+      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
+      stackptr += sizeof(sljit_w);
+      }
+    if (!tmp2empty)
+      {
+      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
+      stackptr += sizeof(sljit_w);
+      }
+    }
+  else
+    {
+    if (!tmp2empty)
+      {
+      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
+      stackptr += sizeof(sljit_w);
+      }
+    if (!tmp1empty)
+      {
+      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
+      stackptr += sizeof(sljit_w);
+      }
+    }
+  }
+SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty)));
+}
+
+static SLJIT_INLINE BOOL ispowerof2(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 */
+  sljit_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, enum stub_types type, int data, struct sljit_jump *start)
+{
+DEFINE_COMPILER;
+stub_list* list_item = sljit_alloc_memory(compiler, sizeof(stub_list));
+
+if (list_item)
+  {
+  list_item->type = type;
+  list_item->data = data;
+  list_item->start = start;
+  list_item->leave = 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);
+  switch(list_item->type)
+    {
+    case stack_alloc:
+    add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL));
+    break;
+    }
+  JUMPTO(SLJIT_JUMP, list_item->leave);
+  list_item = list_item->next;
+  }
+common->stubs = NULL;
+}
+
+static SLJIT_INLINE void decrease_call_count(compiler_common *common)
+{
+DEFINE_COMPILER;
+
+OP2(SLJIT_SUB | SLJIT_SET_E, CALL_COUNT, 0, CALL_COUNT, 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_w));
+#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, stack_alloc, 0, 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_w));
+}
+
+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. */
+/* TMP1 returns with begin - 1. */
+OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1));
+if (length < 8)
+  {
+  for (i = 0; i < length; i++)
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_TEMPORARY_REG1, 0);
+  }
+else
+  {
+  OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START - sizeof(sljit_w));
+  OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length);
+  loop = LABEL();
+  OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(sljit_w), SLJIT_TEMPORARY_REG1, 0);
+  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1);
+  JUMPTO(SLJIT_C_NOT_ZERO, loop);
+  }
+}
+
+static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)
+{
+DEFINE_COMPILER;
+struct sljit_label *loop;
+struct sljit_jump *earlyexit;
+
+/* 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_TEMPORARY_REG1, 0, ARGUMENTS, 0);
+OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount));
+OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));
+OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin));
+OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START);
+/* Unlikely, but possible */
+earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0);
+loop = LABEL();
+OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), 0, SLJIT_TEMPORARY_REG1, 0);
+OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_SAVED_REG1, 0, SLJIT_IMM, sizeof(sljit_w));
+/* Copy the integer value to the output buffer */
+#ifdef COMPILE_PCRE16
+OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1);
+#endif
+OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_SAVED_REG2, 0);
+OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1);
+JUMPTO(SLJIT_C_NOT_ZERO, loop);
+JUMPHERE(earlyexit);
+
+/* Calculate the return value, which is the maximum ovector value. */
+if (topbracket > 1)
+  {
+  OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START + topbracket * 2 * sizeof(sljit_w));
+  OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1);
+
+  /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */
+  loop = LABEL();
+  OP1(SLJIT_MOVU, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), -(2 * (sljit_w)sizeof(sljit_w)));
+  OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1);
+  CMPTO(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG3, 0, loop);
+  OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_TEMPORARY_REG2, 0);
+  }
+else
+  OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
+}
+
+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 (!ispowerof2(bit))
+  return 0;
+
+#ifdef 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;
+
+#else /* COMPILE_PCRE8 */
+
+#ifdef COMPILE_PCRE16
+#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_PCRE16 */
+
+#endif /* COMPILE_PCRE8 */
+}
+
+static SLJIT_INLINE void check_input_end(compiler_common *common, jump_list **fallbacks)
+{
+DEFINE_COMPILER;
+add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+}
+
+static void read_char(compiler_common *common)
+{
+/* Reads the character into TMP1, updates STR_PTR.
+Does not check STR_END. TMP2 Destroyed. */
+DEFINE_COMPILER;
+#ifdef SUPPORT_UTF
+struct sljit_jump *jump;
+#endif
+
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+#ifdef SUPPORT_UTF
+if (common->utf)
+  {
+#ifdef COMPILE_PCRE8
+  jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
+#else
+#ifdef COMPILE_PCRE16
+  jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
+#endif
+#endif /* COMPILE_PCRE8 */
+  add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
+  JUMPHERE(jump);
+  }
+#endif
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+}
+
+static void peek_char(compiler_common *common)
+{
+/* Reads the character into TMP1, keeps STR_PTR.
+Does not check STR_END. TMP2 Destroyed. */
+DEFINE_COMPILER;
+#ifdef SUPPORT_UTF
+struct sljit_jump *jump;
+#endif
+
+OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+#ifdef SUPPORT_UTF
+if (common->utf)
+  {
+#ifdef COMPILE_PCRE8
+  jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
+#else
+#ifdef COMPILE_PCRE16
+  jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
+#endif
+#endif /* COMPILE_PCRE8 */
+  add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL));
+  OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+  JUMPHERE(jump);
+  }
+#endif
+}
+
+static void read_char8_type(compiler_common *common)
+{
+/* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
+DEFINE_COMPILER;
+#if defined SUPPORT_UTF || defined COMPILE_PCRE16
+struct sljit_jump *jump;
+#endif
+
+#ifdef SUPPORT_UTF
+if (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));
+#ifdef COMPILE_PCRE8
+  /* 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);
+  add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL));
+  JUMPHERE(jump);
+#else
+#ifdef COMPILE_PCRE16
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
+  jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
+  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
+  JUMPHERE(jump);
+  /* Skip low surrogate if necessary. */
+  OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xfc00);
+  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xd800);
+  COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
+  OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
+  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+#endif
+#endif /* COMPILE_PCRE8 */
+  return;
+  }
+#endif
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+#ifdef COMPILE_PCRE16
+/* 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);
+#ifdef COMPILE_PCRE16
+JUMPHERE(jump);
+#endif
+}
+
+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_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;
+  }
+#endif
+#if defined SUPPORT_UTF && 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);
+  COND_VALUE(SLJIT_MOV, TMP1, 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
+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 **fallbacks, BOOL jumpiftrue)
+{
+/* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */
+DEFINE_COMPILER;
+
+if (nltype == NLTYPE_ANY)
+  {
+  add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
+  add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
+  }
+else if (nltype == NLTYPE_ANYCRLF)
+  {
+  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_CR);
+  COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
+  COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
+  add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
+  }
+else
+  {
+  SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256);
+  add_jump(compiler, fallbacks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
+  }
+}
+
+#ifdef SUPPORT_UTF
+
+#ifdef 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 - 1 in TMP2. */
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
+/* Searching for the first zero. */
+OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
+jump = JUMP(SLJIT_C_NOT_ZERO);
+/* Two byte sequence. */
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1f);
+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(SLJIT_MOV, TMP2, 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, 0x10);
+jump = JUMP(SLJIT_C_NOT_ZERO);
+/* Three byte sequence. */
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0f);
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 12);
+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
+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(2));
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+JUMPHERE(jump);
+
+/* Four byte sequence. */
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x07);
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 18);
+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2));
+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(3));
+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(3));
+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, 1, 5, 5, common->localsize);
+
+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);
+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);
+compare = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
+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);
+JUMPHERE(jump);
+
+/* We only have types for characters less than 256. */
+OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(utf8_table4) - 0xc0);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+
+#else /* COMPILE_PCRE8 */
+
+#ifdef COMPILE_PCRE16
+static void do_utfreadchar(compiler_common *common)
+{
+/* Fast decoding a UTF-16 character. TMP1 contains the first 16 bit char
+of the character (>= 0xd800). Return char value in TMP1, length - 1 in TMP2. */
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+
+sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
+jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xdc00);
+/* Do nothing, only return. */
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(jump);
+/* Combine two 16 bit characters. */
+OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+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_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 10);
+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3ff);
+OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000);
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+}
+#endif /* COMPILE_PCRE16 */
+
+#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, 1, 5, 5, common->localsize);
+OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
+OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_w)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_w)PRIV(ucd_stage2));
+OP1(SLJIT_MOV_UH, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_w)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;
+#ifdef SUPPORT_UTF
+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. */
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STR_PTR, 0);
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_END, 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);
+    OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_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), FIRSTLINE_END, STR_PTR, 0);
+    read_char(common);
+    check_newlinechar(common, common->nltype, &newline, TRUE);
+    CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0);
+    set_jumps(newline, LABEL());
+    }
+
+  JUMPHERE(end);
+  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
+  }
+
+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);
+  COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
+#ifdef COMPILE_PCRE16
+  OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+#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_PCRE8
+if (common->utf)
+  {
+  singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
+  OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
+  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+  JUMPHERE(singlechar);
+  }
+#endif
+#if defined SUPPORT_UTF && 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);
+  COND_VALUE(SLJIT_MOV, TMP1, 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
+JUMPHERE(start);
+
+if (newlinecheck)
+  {
+  JUMPHERE(end);
+  JUMPHERE(nl);
+  }
+
+return mainloop;
+}
+
+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 *leave;
+struct sljit_jump *found;
+pcre_uchar oc, bit;
+
+if (firstline)
+  {
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
+  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
+  }
+
+start = LABEL();
+leave = 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 (ispowerof2(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);
+    COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
+    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc);
+    COND_VALUE(SLJIT_OR | SLJIT_SET_E, 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));
+#if defined SUPPORT_UTF && 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_w)PRIV(utf8_table4) - 0xc0);
+  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+  }
+#endif
+#if defined SUPPORT_UTF && 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);
+  COND_VALUE(SLJIT_MOV, TMP1, 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
+JUMPTO(SLJIT_JUMP, start);
+JUMPHERE(found);
+JUMPHERE(leave);
+
+if (firstline)
+  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
+}
+
+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 *leave;
+struct sljit_jump *foundcr = NULL;
+struct sljit_jump *notfoundnl;
+jump_list *newline = NULL;
+
+if (firstline)
+  {
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
+  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_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);
+  COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER_EQUAL);
+#ifdef COMPILE_PCRE16
+  OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
+#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));
+  leave = 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(leave);
+  JUMPHERE(firstchar);
+  JUMPHERE(lastchar);
+
+  if (firstline)
+    OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
+  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();
+read_char(common);
+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)
+  {
+  leave = 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);
+  COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
+#ifdef COMPILE_PCRE16
+  OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+#endif
+  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+  JUMPHERE(notfoundnl);
+  JUMPHERE(leave);
+  }
+JUMPHERE(lastchar);
+JUMPHERE(firstchar);
+
+if (firstline)
+  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
+}
+
+static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_uw start_bits, BOOL firstline)
+{
+DEFINE_COMPILER;
+struct sljit_label *start;
+struct sljit_jump *leave;
+struct sljit_jump *found;
+#ifndef COMPILE_PCRE8
+struct sljit_jump *jump;
+#endif
+
+if (firstline)
+  {
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
+  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
+  }
+
+start = LABEL();
+leave = 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
+#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), 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));
+#if defined SUPPORT_UTF && 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_w)PRIV(utf8_table4) - 0xc0);
+  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+  }
+#endif
+#if defined SUPPORT_UTF && 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);
+  COND_VALUE(SLJIT_MOV, TMP1, 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
+JUMPTO(SLJIT_JUMP, start);
+JUMPHERE(found);
+JUMPHERE(leave);
+
+if (firstline)
+  OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
+}
+
+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_uchar oc, bit;
+
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), 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 (ispowerof2(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), 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, 1, 5, 5, common->localsize);
+OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0);
+
+/* Drop frames until we reach STACK_TOP. */
+mainloop = LABEL();
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0);
+jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);
+OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_LOCALS_REG, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
+OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_w), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_w));
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_w));
+JUMPTO(SLJIT_JUMP, mainloop);
+
+JUMPHERE(jump);
+jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);
+/* End of dropping frames. */
+sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
+
+JUMPHERE(jump);
+jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setstrbegin);
+/* Set string begin. */
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);
+JUMPTO(SLJIT_JUMP, mainloop);
+
+JUMPHERE(jump);
+/* Unknown command. */
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
+JUMPTO(SLJIT_JUMP, mainloop);
+}
+
+static void check_wordboundary(compiler_common *common)
+{
+DEFINE_COMPILER;
+struct sljit_jump *beginend;
+#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, 1, 5, 5, common->localsize);
+/* 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);
+beginend = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0);
+skip_char_back(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);
+  COND_VALUE(SLJIT_MOV, TMP2, 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);
+  COND_VALUE(SLJIT_OR, 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(beginend);
+
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
+beginend = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+peek_char(common);
+
+/* 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);
+  COND_VALUE(SLJIT_MOV, TMP2, 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);
+  COND_VALUE(SLJIT_OR, 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 */
+  }
+JUMPHERE(beginend);
+
+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 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, 1, 5, 5, common->localsize);
+
+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);
+COND_VALUE(SLJIT_MOV, TMP2, 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
+#ifdef COMPILE_PCRE8
+if (common->utf)
+  {
+#endif
+  COND_VALUE(SLJIT_OR, 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 */
+COND_VALUE(SLJIT_OR | SLJIT_SET_E, 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, 1, 5, 5, common->localsize);
+
+OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);
+COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
+OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
+COND_VALUE(SLJIT_OR, 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
+#ifdef COMPILE_PCRE8
+if (common->utf)
+  {
+#endif
+  COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680);
+  COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e);
+  COND_VALUE(SLJIT_OR, 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);
+  COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
+  COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
+  COND_VALUE(SLJIT_OR, 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 */
+COND_VALUE(SLJIT_OR | SLJIT_SET_E, 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, 1, 5, 5, common->localsize);
+
+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);
+COND_VALUE(SLJIT_MOV, TMP2, 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
+#ifdef COMPILE_PCRE8
+if (common->utf)
+  {
+#endif
+  COND_VALUE(SLJIT_OR | SLJIT_SET_E, 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 */
+COND_VALUE(SLJIT_OR | SLJIT_SET_E, 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, 1, 5, 5, common->localsize);
+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, 1, 5, 5, common->localsize);
+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. */
+int c1, c2;
+const pcre_uchar *src2 = args->ptr;
+const pcre_uchar *end2 = args->end;
+
+while (src1 < end1)
+  {
+  if (src2 >= end2)
+    return 0;
+  GETCHARINC(c1, src1);
+  GETCHARINC(c2, src2);
+  if (c1 != c2 && c1 != UCD_OTHERCASE(c2)) return 0;
+  }
+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 **fallbacks)
+{
+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. */
+#ifdef COMPILE_PCRE8
+  othercasechar = cc + (othercasebit >> 8);
+  othercasebit &= 0xff;
+#else
+#ifdef COMPILE_PCRE16
+  othercasechar = cc + (othercasebit >> 9);
+  if ((othercasebit & 0x100) != 0)
+    othercasebit = (othercasebit & 0xff) << 8;
+  else
+    othercasebit &= 0xff;
+#endif
+#endif
+  }
+
+if (context->sourcereg == -1)
+  {
+#ifdef 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);
+#else
+#ifdef 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(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
+#endif
+#endif /* COMPILE_PCRE8 */
+  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
+
+  /* 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++;
+
+#ifdef 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);
+#ifdef COMPILE_PCRE8
+    else if (context->length >= 2)
+      OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
+    else if (context->length >= 1)
+      OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
+#else
+    else if (context->length >= 2)
+      OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
+#endif
+    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, fallbacks, 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, fallbacks, 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, fallbacks, 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. */
+#ifdef COMPILE_PCRE8
+  if (context->length > 0)
+    OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
+#else
+  if (context->length > 0)
+    OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
+#endif
+  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, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit));
+    }
+  else
+    add_jump(compiler, fallbacks, 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_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \
+    else \
+      OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \
+    } \
+  typeoffset = (value);
+
+#define SET_CHAR_OFFSET(value) \
+  if ((value) != charoffset) \
+    { \
+    if ((value) > charoffset) \
+      OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (value) - charoffset); \
+    else \
+      OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, charoffset - (value)); \
+    } \
+  charoffset = (value);
+
+static void compile_xclass_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks)
+{
+DEFINE_COMPILER;
+jump_list *found = NULL;
+jump_list **list = (*cc & XCL_NOT) == 0 ? &found : fallbacks;
+unsigned int c;
+int compares;
+struct sljit_jump *jump = NULL;
+pcre_uchar *ccbegin;
+#ifdef SUPPORT_UCP
+BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;
+BOOL charsaved = FALSE;
+int typereg = TMP1, scriptreg = TMP1;
+unsigned int typeoffset;
+#endif
+int invertcmp, numberofcmps;
+unsigned int charoffset;
+
+/* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */
+check_input_end(common, fallbacks);
+read_char(common);
+
+if ((*cc++ & XCL_MAP) != 0)
+  {
+  OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
+#ifndef COMPILE_PCRE8
+  jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
+#elif defined SUPPORT_UTF
+  if (common->utf)
+    jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
+#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_w)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));
+
+#ifndef COMPILE_PCRE8
+  JUMPHERE(jump);
+#elif defined SUPPORT_UTF
+  if (common->utf)
+    JUMPHERE(jump);
+#endif
+  OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
+#ifdef SUPPORT_UCP
+  charsaved = TRUE;
+#endif
+  cc += 32 / sizeof(pcre_uchar);
+  }
+
+/* Scanning the necessary info. */
+ccbegin = cc;
+compares = 0;
+while (*cc != XCL_END)
+  {
+  compares++;
+  if (*cc == XCL_SINGLE)
+    {
+    cc += 2;
+#ifdef SUPPORT_UTF
+    if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+#ifdef SUPPORT_UCP
+    needschar = TRUE;
+#endif
+    }
+  else if (*cc == XCL_RANGE)
+    {
+    cc += 2;
+#ifdef SUPPORT_UTF
+    if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+    cc++;
+#ifdef SUPPORT_UTF
+    if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+#ifdef SUPPORT_UCP
+    needschar = TRUE;
+#endif
+    }
+#ifdef SUPPORT_UCP
+  else
+    {
+    SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
+    cc++;
+    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:
+      needstype = TRUE;
+      needschar = TRUE;
+      break;
+
+      default:
+      SLJIT_ASSERT_STOP();
+      break;
+      }
+    cc += 2;
+    }
+#endif
+  }
+
+#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_w)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_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
+      OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM1(TMP2), 0);
+      }
+    }
+  }
+#endif
+
+/* Generating code. */
+cc = ccbegin;
+charoffset = 0;
+numberofcmps = 0;
+#ifdef SUPPORT_UCP
+typeoffset = 0;
+#endif
+
+while (*cc != XCL_END)
+  {
+  compares--;
+  invertcmp = (compares == 0 && list != fallbacks);
+  jump = NULL;
+
+  if (*cc == XCL_SINGLE)
+    {
+    cc ++;
+#ifdef SUPPORT_UTF
+    if (common->utf)
+      {
+      GETCHARINC(c, cc);
+      }
+    else
+#endif
+      c = *cc++;
+
+    if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
+      {
+      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
+      COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
+      numberofcmps++;
+      }
+    else if (numberofcmps > 0)
+      {
+      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
+      COND_VALUE(SLJIT_OR | SLJIT_SET_E, 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, c - charoffset);
+      numberofcmps = 0;
+      }
+    }
+  else if (*cc == XCL_RANGE)
+    {
+    cc ++;
+#ifdef SUPPORT_UTF
+    if (common->utf)
+      {
+      GETCHARINC(c, cc);
+      }
+    else
+#endif
+      c = *cc++;
+    SET_CHAR_OFFSET(c);
+#ifdef SUPPORT_UTF
+    if (common->utf)
+      {
+      GETCHARINC(c, cc);
+      }
+    else
+#endif
+      c = *cc++;
+    if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
+      {
+      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
+      COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
+      numberofcmps++;
+      }
+    else if (numberofcmps > 0)
+      {
+      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
+      COND_VALUE(SLJIT_OR | SLJIT_SET_E, 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, c - charoffset);
+      numberofcmps = 0;
+      }
+    }
+#ifdef SUPPORT_UCP
+  else
+    {
+    if (*cc == XCL_NOTPROP)
+      invertcmp ^= 0x1;
+    cc++;
+    switch(*cc)
+      {
+      case PT_ANY:
+      if (list != fallbacks)
+        {
+        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);
+      COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);
+      COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
+      OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);
+      COND_VALUE(SLJIT_OR | SLJIT_SET_E, 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:
+      if (*cc == PT_SPACE)
+        {
+        OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
+        jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 11 - charoffset);
+        }
+      SET_CHAR_OFFSET(9);
+      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 13 - 9);
+      COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
+      if (*cc == PT_SPACE)
+        JUMPHERE(jump);
+
+      SET_TYPE_OFFSET(ucp_Zl);
+      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
+      COND_VALUE(SLJIT_OR | SLJIT_SET_E, 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, CHAR_UNDERSCORE - charoffset);
+      COND_VALUE(SLJIT_MOV, TMP2, 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);
+      COND_VALUE((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, 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);
+      COND_VALUE(SLJIT_OR | SLJIT_SET_E, 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 : fallbacks, jump);
+  }
+
+if (found != NULL)
+  set_jumps(found, LABEL());
+}
+
+#undef SET_TYPE_OFFSET
+#undef SET_CHAR_OFFSET
+
+#endif
+
+static pcre_uchar *compile_char1_hotpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **fallbacks)
+{
+DEFINE_COMPILER;
+int length;
+unsigned int c, oc, bit;
+compare_context context;
+struct sljit_jump *jump[4];
+#ifdef SUPPORT_UTF
+struct sljit_label *label;
+#ifdef SUPPORT_UCP
+pcre_uchar propdata[5];
+#endif
+#endif
+
+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, fallbacks, 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, fallbacks, 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, fallbacks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
+  return cc;
+
+  case OP_NOT_DIGIT:
+  case OP_DIGIT:
+  check_input_end(common, fallbacks);
+  read_char8_type(common);
+  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
+  add_jump(compiler, fallbacks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
+  return cc;
+
+  case OP_NOT_WHITESPACE:
+  case OP_WHITESPACE:
+  check_input_end(common, fallbacks);
+  read_char8_type(common);
+  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
+  add_jump(compiler, fallbacks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
+  return cc;
+
+  case OP_NOT_WORDCHAR:
+  case OP_WORDCHAR:
+  check_input_end(common, fallbacks);
+  read_char8_type(common);
+  OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
+  add_jump(compiler, fallbacks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
+  return cc;
+
+  case OP_ANY:
+  check_input_end(common, fallbacks);
+  read_char(common);
+  if (common->nltype == NLTYPE_FIXED && common->newline > 255)
+    {
+    jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
+    jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+    add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff));
+    JUMPHERE(jump[1]);
+    JUMPHERE(jump[0]);
+    }
+  else
+    check_newlinechar(common, common->nltype, fallbacks, TRUE);
+  return cc;
+
+  case OP_ALLANY:
+  check_input_end(common, fallbacks);
+#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));
+#ifdef COMPILE_PCRE8
+    jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
+    OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0);
+    OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+#else /* COMPILE_PCRE8 */
+#ifdef 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);
+    COND_VALUE(SLJIT_MOV, TMP1, 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_PCRE16 */
+#endif /* COMPILE_PCRE8 */
+    JUMPHERE(jump[0]);
+    return cc;
+    }
+#endif
+  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+  return cc;
+
+  case OP_ANYBYTE:
+  check_input_end(common, fallbacks);
+  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] = 0;
+  propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP;
+  propdata[2] = cc[0];
+  propdata[3] = cc[1];
+  propdata[4] = XCL_END;
+  compile_xclass_hotpath(common, propdata, fallbacks);
+  return cc + 2;
+#endif
+#endif
+
+  case OP_ANYNL:
+  check_input_end(common, fallbacks);
+  read_char(common);
+  jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
+  jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+  OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
+  jump[2] = 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[3] = JUMP(SLJIT_JUMP);
+  JUMPHERE(jump[0]);
+  check_newlinechar(common, common->bsr_nltype, fallbacks, FALSE);
+  JUMPHERE(jump[1]);
+  JUMPHERE(jump[2]);
+  JUMPHERE(jump[3]);
+  return cc;
+
+  case OP_NOT_HSPACE:
+  case OP_HSPACE:
+  check_input_end(common, fallbacks);
+  read_char(common);
+  add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
+  add_jump(compiler, fallbacks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
+  return cc;
+
+  case OP_NOT_VSPACE:
+  case OP_VSPACE:
+  check_input_end(common, fallbacks);
+  read_char(common);
+  add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
+  add_jump(compiler, fallbacks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
+  return cc;
+
+#ifdef SUPPORT_UCP
+  case OP_EXTUNI:
+  check_input_end(common, fallbacks);
+  read_char(common);
+  add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
+  OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);
+  add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc));
+
+  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));
+  OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);
+  CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc, label);
+
+  OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
+  JUMPHERE(jump[0]);
+  return cc;
+#endif
+
+  case OP_EODN:
+  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));
+    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
+    OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
+    add_jump(compiler, fallbacks, 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, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
+    add_jump(compiler, fallbacks, 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, fallbacks, 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, fallbacks, 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, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0));
+      add_jump(compiler, fallbacks, 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(common);
+      add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
+      add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
+      add_jump(compiler, fallbacks, 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]);
+  return cc;
+
+  case OP_EOD:
+  add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
+  return cc;
+
+  case OP_CIRC:
+  OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
+  add_jump(compiler, fallbacks, 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, fallbacks, 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, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+  jump[0] = JUMP(SLJIT_JUMP);
+  JUMPHERE(jump[1]);
+
+  add_jump(compiler, fallbacks, CMP(SLJIT_C_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, fallbacks, 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, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
+    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
+    }
+  else
+    {
+    skip_char_back(common);
+    read_char(common);
+    check_newlinechar(common, common->nltype, fallbacks, 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, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+
+  if (!common->endonly)
+    compile_char1_hotpath(common, OP_EODN, cc, fallbacks);
+  else
+    add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0));
+  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, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+  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));
+    add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0));
+    OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+    OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
+    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
+    add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
+    }
+  else
+    {
+    peek_char(common);
+    check_newlinechar(common, common->nltype, fallbacks, 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 (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, fallbacks, 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, fallbacks);
+    }
+  check_input_end(common, fallbacks);
+  read_char(common);
+#ifdef SUPPORT_UTF
+  if (common->utf)
+    {
+    GETCHAR(c, cc);
+    }
+  else
+#endif
+    c = *cc;
+  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c);
+  COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
+  OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c));
+  COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
+  add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));
+  return cc + length;
+
+  case OP_NOT:
+  case OP_NOTI:
+  check_input_end(common, fallbacks);
+  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, fallbacks, 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, fallbacks, 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_w)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);
+      read_char(common);
+      }
+    }
+  else
+#endif /* SUPPORT_UTF */
+    {
+    read_char(common);
+    c = *cc;
+    }
+
+  if (type == OP_NOT || !char_has_othercase(common, cc))
+    add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
+  else
+    {
+    oc = char_othercase(common, c);
+    bit = c ^ oc;
+    if (ispowerof2(bit))
+      {
+      OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
+      add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
+      }
+    else
+      {
+      add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
+      add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc));
+      }
+    }
+  return cc + 1;
+
+  case OP_CLASS:
+  case OP_NCLASS:
+  check_input_end(common, fallbacks);
+  read_char(common);
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+  jump[0] = NULL;
+#ifdef COMPILE_PCRE8
+  /* This check only affects 8 bit mode. In other modes, we
+  always need to compare the value with 255. */
+  if (common->utf)
+#endif /* COMPILE_PCRE8 */
+    {
+    jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
+    if (type == OP_CLASS)
+      {
+      add_jump(compiler, fallbacks, 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_w)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, fallbacks, JUMP(SLJIT_C_ZERO));
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+  if (jump[0] != NULL)
+    JUMPHERE(jump[0]);
+#endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
+  return cc + 32 / sizeof(pcre_uchar);
+
+#if defined SUPPORT_UTF || defined COMPILE_PCRE16
+  case OP_XCLASS:
+  compile_xclass_hotpath(common, cc + LINK_SIZE, fallbacks);
+  return cc + GET(cc, 0) - 1;
+#endif
+
+  case OP_REVERSE:
+  length = GET(cc, 0);
+  SLJIT_ASSERT(length > 0);
+  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, fallbacks, 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);
+    return cc + LINK_SIZE;
+    }
+#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, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0));
+  return cc + LINK_SIZE;
+  }
+SLJIT_ASSERT_STOP();
+return cc;
+}
+
+static SLJIT_INLINE pcre_uchar *compile_charn_hotpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **fallbacks)
+{
+/* 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, fallbacks, 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, fallbacks); while (context.length > 0);
+  return cc;
+  }
+
+/* A non-fixed length character will be checked if length == 0. */
+return compile_char1_hotpath(common, *cc, cc + 1, fallbacks);
+}
+
+static struct sljit_jump *compile_ref_checks(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks)
+{
+DEFINE_COMPILER;
+int offset = GET2(cc, 1) << 1;
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
+if (!common->jscript_compat)
+  {
+  if (fallbacks == NULL)
+    {
+    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
+    COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
+    OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
+    COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
+    return JUMP(SLJIT_C_NOT_ZERO);
+    }
+  add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
+  }
+return CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
+}
+
+/* Forward definitions. */
+static void compile_hotpath(compiler_common *, pcre_uchar *, pcre_uchar *, fallback_common *);
+static void compile_fallbackpath(compiler_common *, struct fallback_common *);
+
+#define PUSH_FALLBACK(size, ccstart, error) \
+  do \
+    { \
+    fallback = sljit_alloc_memory(compiler, (size)); \
+    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
+      return error; \
+    memset(fallback, 0, size); \
+    fallback->prev = parent->top; \
+    fallback->cc = (ccstart); \
+    parent->top = fallback; \
+    } \
+  while (0)
+
+#define PUSH_FALLBACK_NOVALUE(size, ccstart) \
+  do \
+    { \
+    fallback = sljit_alloc_memory(compiler, (size)); \
+    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
+      return; \
+    memset(fallback, 0, size); \
+    fallback->prev = parent->top; \
+    fallback->cc = (ccstart); \
+    parent->top = fallback; \
+    } \
+  while (0)
+
+#define FALLBACK_AS(type) ((type*)fallback)
+
+static pcre_uchar *compile_ref_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks, BOOL withchecks, BOOL emptyfail)
+{
+DEFINE_COMPILER;
+int offset = GET2(cc, 1) << 1;
+struct sljit_jump *jump = NULL;
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
+if (withchecks && !common->jscript_compat)
+  add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
+
+#if defined SUPPORT_UTF && defined SUPPORT_UCP
+if (common->utf && *cc == OP_REFI)
+  {
+  SLJIT_ASSERT(TMP1 == SLJIT_TEMPORARY_REG1 && STACK_TOP == SLJIT_TEMPORARY_REG2 && TMP2 == SLJIT_TEMPORARY_REG3);
+  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
+  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_TEMPORARY_REG2, 0, ARGUMENTS, 0);
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, 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);
+  add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
+  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
+  }
+else
+#endif /* SUPPORT_UTF && SUPPORT_UCP */
+  {
+  OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0);
+  if (withchecks)
+    jump = JUMP(SLJIT_C_ZERO);
+  OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+
+  add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
+  add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
+  add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+  }
+
+if (jump != NULL)
+  {
+  if (emptyfail)
+    add_jump(compiler, fallbacks, jump);
+  else
+    JUMPHERE(jump);
+  }
+return cc + 1 + IMM2_SIZE;
+}
+
+static SLJIT_INLINE pcre_uchar *compile_ref_iterator_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)
+{
+DEFINE_COMPILER;
+fallback_common *fallback;
+pcre_uchar type;
+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_FALLBACK(sizeof(iterator_fallback), cc, NULL);
+
+type = cc[1 + IMM2_SIZE];
+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);
+    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_w));
+    zerolength = compile_ref_checks(common, ccbegin, NULL);
+    /* Restore if not zero length. */
+    OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
+    }
+  else
+    {
+    allocate_stack(common, 1);
+    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+    zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks);
+    }
+
+  if (min > 1 || max > 1)
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);
+
+  label = LABEL();
+  compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, 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);
+  FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
+
+  decrease_call_count(common);
+  return cc;
+  }
+
+allocate_stack(common, 2);
+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)
+  {
+  zerolength = compile_ref_checks(common, ccbegin, NULL);
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+  jump = JUMP(SLJIT_JUMP);
+  }
+else
+  zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks);
+
+FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
+if (max > 0)
+  add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));
+
+compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, 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, FALLBACK_AS(iterator_fallback)->hotpath);
+  }
+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);
+
+decrease_call_count(common);
+return cc;
+}
+
+static SLJIT_INLINE pcre_uchar *compile_recurse_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)
+{
+DEFINE_COMPILER;
+fallback_common *fallback;
+recurse_entry *entry = common->entries;
+recurse_entry *prev = NULL;
+int start = GET(cc, 1);
+
+PUSH_FALLBACK(sizeof(recurse_fallback), cc, NULL);
+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;
+  }
+
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
+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, &fallback->topfallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0));
+return cc + 1 + LINK_SIZE;
+}
+
+static pcre_uchar *compile_assert_hotpath(compiler_common *common, pcre_uchar *cc, assert_fallback *fallback, BOOL conditional)
+{
+DEFINE_COMPILER;
+int framesize;
+int localptr;
+fallback_common altfallback;
+pcre_uchar *ccbegin;
+pcre_uchar opcode;
+pcre_uchar bra = OP_BRA;
+jump_list *tmp = NULL;
+jump_list **target = (conditional) ? &fallback->condfailed : &fallback->common.topfallbacks;
+jump_list **found;
+/* Saving previous accept variables. */
+struct sljit_label *save_acceptlabel = common->acceptlabel;
+struct sljit_jump *jump;
+struct sljit_jump *brajump = NULL;
+jump_list *save_accept = common->accept;
+
+if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
+  {
+  SLJIT_ASSERT(!conditional);
+  bra = *cc;
+  cc++;
+  }
+localptr = PRIV_DATA(cc);
+SLJIT_ASSERT(localptr != 0);
+framesize = get_framesize(common, cc, FALSE);
+fallback->framesize = framesize;
+fallback->localptr = localptr;
+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 fallback 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)
+  {
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
+  allocate_stack(common, 1);
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+  }
+else
+  {
+  allocate_stack(common, framesize + 2);
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+  OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(framesize + 1));
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
+  init_frame(common, ccbegin, framesize + 1, 2, FALSE);
+  }
+
+memset(&altfallback, 0, sizeof(fallback_common));
+while (1)
+  {
+  common->acceptlabel = NULL;
+  common->accept = NULL;
+  altfallback.top = NULL;
+  altfallback.topfallbacks = NULL;
+
+  if (*ccbegin == OP_ALT)
+    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+
+  altfallback.cc = ccbegin;
+  compile_hotpath(common, ccbegin + 1 + LINK_SIZE, cc, &altfallback);
+  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+    {
+    common->acceptlabel = save_acceptlabel;
+    common->accept = save_accept;
+    return NULL;
+    }
+  common->acceptlabel = LABEL();
+  if (common->accept != NULL)
+    set_jumps(common->accept, common->acceptlabel);
+
+  /* Reset stack. */
+  if (framesize < 0)
+    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+  else {
+    if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional)
+      {
+      /* We don't need to keep the STR_PTR, only the previous localptr. */
+      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_w));
+      }
+    else
+      {
+      OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+      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), 0);
+    else if (bra == OP_BRAZERO)
+      {
+      if (framesize < 0)
+        OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
+      else
+        {
+        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
+        OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_w));
+        OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
+        }
+      OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
+      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), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
+      }
+    }
+  add_jump(compiler, found, JUMP(SLJIT_JUMP));
+
+  compile_fallbackpath(common, altfallback.top);
+  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+    {
+    common->acceptlabel = save_acceptlabel;
+    common->accept = save_accept;
+    return NULL;
+    }
+  set_jumps(altfallback.topfallbacks, LABEL());
+
+  if (*cc != OP_ALT)
+    break;
+
+  ccbegin = cc;
+  cc += GET(cc, 1);
+  }
+/* None of them matched. */
+
+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)
+      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+    else
+      free_stack(common, 1);
+    }
+  else
+    {
+    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
+    /* The topmost item should be 0. */
+    if (bra == OP_BRAZERO)
+      {
+      free_stack(common, framesize + 1);
+      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+      }
+    else
+      free_stack(common, framesize + 2);
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, 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), 0);
+    /* 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_w));
+    else if (bra == OP_BRAMINZERO)
+      {
+      OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
+      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 localptr. */
+      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_w));
+      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
+      }
+    else
+      {
+      /* We don't need to keep the STR_PTR, only the previous localptr. */
+      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_w));
+      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0);
+      }
+    }
+
+  if (bra == OP_BRAZERO)
+    {
+    fallback->hotpath = LABEL();
+    sljit_set_label(jump, fallback->hotpath);
+    }
+  else if (bra == OP_BRAMINZERO)
+    {
+    JUMPTO(SLJIT_JUMP, fallback->hotpath);
+    JUMPHERE(brajump);
+    if (framesize >= 0)
+      {
+      OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+      add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
+      }
+    set_jumps(fallback->common.topfallbacks, LABEL());
+    }
+  }
+else
+  {
+  /* AssertNot is successful. */
+  if (framesize < 0)
+    {
+    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+    if (bra != OP_BRA)
+      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+    else
+      free_stack(common, 1);
+    }
+  else
+    {
+    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
+    /* The topmost item should be 0. */
+    if (bra != OP_BRA)
+      {
+      free_stack(common, framesize + 1);
+      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+      }
+    else
+      free_stack(common, framesize + 2);
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
+    }
+
+  if (bra == OP_BRAZERO)
+    fallback->hotpath = LABEL();
+  else if (bra == OP_BRAMINZERO)
+    {
+    JUMPTO(SLJIT_JUMP, fallback->hotpath);
+    JUMPHERE(brajump);
+    }
+
+  if (bra != OP_BRA)
+    {
+    SLJIT_ASSERT(found == &fallback->common.topfallbacks);
+    set_jumps(fallback->common.topfallbacks, LABEL());
+    fallback->common.topfallbacks = NULL;
+    }
+  }
+
+common->acceptlabel = save_acceptlabel;
+common->accept = save_accept;
+return cc + 1 + LINK_SIZE;
+}
+
+static sljit_w SLJIT_CALL do_searchovector(sljit_w refno, sljit_w* locals, pcre_uchar *name_table)
+{
+int condition = FALSE;
+pcre_uchar *slotA = name_table;
+pcre_uchar *slotB;
+sljit_w name_count = locals[LOCALS0 / sizeof(sljit_w)];
+sljit_w name_entry_size = locals[LOCALS1 / sizeof(sljit_w)];
+sljit_w no_capture;
+int i;
+
+locals += OVECTOR_START / sizeof(sljit_w);
+no_capture = locals[1];
+
+for (i = 0; i < name_count; i++)
+  {
+  if (GET2(slotA, 0) == refno) break;
+  slotA += name_entry_size;
+  }
+
+if (i < name_count)
+  {
+  /* Found a name for the number - there can be only one; duplicate names
+  for different numbers are allowed, but not vice versa. First scan down
+  for duplicates. */
+
+  slotB = slotA;
+  while (slotB > name_table)
+    {
+    slotB -= name_entry_size;
+    if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
+      {
+      condition = locals[GET2(slotB, 0) << 1] != no_capture;
+      if (condition) break;
+      }
+    else break;
+    }
+
+  /* Scan up for duplicates */
+  if (!condition)
+    {
+    slotB = slotA;
+    for (i++; i < name_count; i++)
+      {
+      slotB += name_entry_size;
+      if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
+        {
+        condition = locals[GET2(slotB, 0) << 1] != no_capture;
+        if (condition) break;
+        }
+      else break;
+      }
+    }
+  }
+return condition;
+}
+
+static sljit_w SLJIT_CALL do_searchgroups(sljit_w recno, sljit_w* locals, pcre_uchar *name_table)
+{
+int condition = FALSE;
+pcre_uchar *slotA = name_table;
+pcre_uchar *slotB;
+sljit_w name_count = locals[LOCALS0 / sizeof(sljit_w)];
+sljit_w name_entry_size = locals[LOCALS1 / sizeof(sljit_w)];
+sljit_w group_num = locals[POSSESSIVE0 / sizeof(sljit_w)];
+int i;
+
+for (i = 0; i < name_count; i++)
+  {
+  if (GET2(slotA, 0) == recno) break;
+  slotA += name_entry_size;
+  }
+
+if (i < name_count)
+  {
+  /* Found a name for the number - there can be only one; duplicate
+  names for different numbers are allowed, but not vice versa. First
+  scan down for duplicates. */
+
+  slotB = slotA;
+  while (slotB > name_table)
+    {
+    slotB -= name_entry_size;
+    if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
+      {
+      condition = GET2(slotB, 0) == group_num;
+      if (condition) break;
+      }
+    else break;
+    }
+
+  /* Scan up for duplicates */
+  if (!condition)
+    {
+    slotB = slotA;
+    for (i++; i < name_count; i++)
+      {
+      slotB += name_entry_size;
+      if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0)
+        {
+        condition = GET2(slotB, 0) == group_num;
+        if (condition) break;
+        }
+      else break;
+      }
+    }
+  }
+return condition;
+}
+
+/*
+  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_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)
+{
+DEFINE_COMPILER;
+fallback_common *fallback;
+pcre_uchar opcode;
+int localptr = 0;
+int offset = 0;
+int stacksize;
+pcre_uchar *ccbegin;
+pcre_uchar *hotpath;
+pcre_uchar bra = OP_BRA;
+pcre_uchar ket;
+assert_fallback *assert;
+BOOL has_alternatives;
+struct sljit_jump *jump;
+struct sljit_jump *skip;
+struct sljit_label *rmaxlabel = NULL;
+struct sljit_jump *braminzerojump = NULL;
+
+PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL);
+
+if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
+  {
+  bra = *cc;
+  cc++;
+  opcode = *cc;
+  }
+
+opcode = *cc;
+ccbegin = cc;
+hotpath = ccbegin + 1 + LINK_SIZE;
+
+if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF)
+  {
+  /* Drop this bracket_fallback. */
+  parent->top = fallback->prev;
+  return bracketend(cc);
+  }
+
+ket = *(bracketend(cc) - 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) || SLJIT_UNLIKELY(opcode == OP_SCOND))
+  {
+  has_alternatives = (*hotpath == OP_RREF) ? FALSE : TRUE;
+  if (*hotpath == OP_NRREF)
+    {
+    stacksize = GET2(hotpath, 1);
+    if (common->currententry == NULL || stacksize == RREF_ANY)
+      has_alternatives = FALSE;
+    else if (common->currententry->start == 0)
+      has_alternatives = stacksize != 0;
+    else
+      has_alternatives = stacksize != GET2(common->start, common->currententry->start + 1 + LINK_SIZE);
+    }
+  }
+
+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);
+  localptr = OVECTOR_PRIV(offset);
+  offset <<= 1;
+  FALLBACK_AS(bracket_fallback)->localptr = localptr;
+  hotpath += IMM2_SIZE;
+  }
+else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND)
+  {
+  /* Other brackets simply allocate the next entry. */
+  localptr = PRIV_DATA(ccbegin);
+  SLJIT_ASSERT(localptr != 0);
+  FALLBACK_AS(bracket_fallback)->localptr = localptr;
+  if (opcode == OP_ONCE)
+    FALLBACK_AS(bracket_fallback)->u.framesize = get_framesize(common, ccbegin, FALSE);
+  }
+
+/* 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 fallback path! (Since the hot-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);
+    braminzerojump = 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 || FALLBACK_AS(bracket_fallback)->u.framesize < 0)
+        {
+        /* When we come from outside, localptr contains the previous STR_PTR. */
+        braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+        }
+      else
+        {
+        /* Except when the whole stack frame must be saved. */
+        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+        braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (FALLBACK_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w));
+        }
+      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 (ket == OP_KETRMIN)
+  FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL();
+
+if (ket == OP_KETRMAX)
+  {
+  rmaxlabel = LABEL();
+  if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA)
+    FALLBACK_AS(bracket_fallback)->althotpath = rmaxlabel;
+  }
+
+/* Handling capturing brackets and alternatives. */
+if (opcode == OP_ONCE)
+  {
+  if (FALLBACK_AS(bracket_fallback)->u.framesize < 0)
+    {
+    /* Neither capturing brackets nor recursions are not found in the block. */
+    if (ket == OP_KETRMIN)
+      {
+      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+      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), TMP2, 0);
+      OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
+      }
+    else if (ket == OP_KETRMAX || has_alternatives)
+      {
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
+      allocate_stack(common, 1);
+      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+      }
+    else
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
+    }
+  else
+    {
+    if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives)
+      {
+      allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 2);
+      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+      OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize + 1));
+      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
+      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
+      init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize + 1, 2, FALSE);
+      }
+    else
+      {
+      allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 1);
+      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+      OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize));
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
+      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
+      init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize, 1, FALSE);
+      }
+    }
+  }
+else if (opcode == OP_CBRA || opcode == OP_SCBRA)
+  {
+  /* Saving the previous values. */
+  allocate_stack(common, 3);
+  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);
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0);
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);
+  }
+else if (opcode == OP_SBRA || opcode == OP_SCOND)
+  {
+  /* Saving the previous value. */
+  OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+  allocate_stack(common, 1);
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, 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 (*hotpath == OP_CREF)
+    {
+    SLJIT_ASSERT(has_alternatives);
+    add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed),
+      CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(hotpath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
+    hotpath += 1 + IMM2_SIZE;
+    }
+  else if (*hotpath == OP_NCREF)
+    {
+    SLJIT_ASSERT(has_alternatives);
+    stacksize = GET2(hotpath, 1);
+    jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(stacksize << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
+
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0);
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count);
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size);
+    OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize);
+    OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0);
+    OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table);
+    sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchovector));
+    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
+    add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0));
+
+    JUMPHERE(jump);
+    hotpath += 1 + IMM2_SIZE;
+    }
+  else if (*hotpath == OP_RREF || *hotpath == OP_NRREF)
+    {
+    /* Never has other case. */
+    FALLBACK_AS(bracket_fallback)->u.condfailed = NULL;
+
+    stacksize = GET2(hotpath, 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 == GET2(common->start, common->currententry->start + 1 + LINK_SIZE);
+
+    if (*hotpath == OP_RREF || stacksize || common->currententry == NULL)
+      {
+      SLJIT_ASSERT(!has_alternatives);
+      if (stacksize != 0)
+        hotpath += 1 + IMM2_SIZE;
+      else
+        {
+        if (*cc == OP_ALT)
+          {
+          hotpath = cc + 1 + LINK_SIZE;
+          cc += GET(cc, 1);
+          }
+        else
+          hotpath = cc;
+        }
+      }
+    else
+      {
+      SLJIT_ASSERT(has_alternatives);
+
+      stacksize = GET2(hotpath, 1);
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0);
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count);
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size);
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, GET2(common->start, common->currententry->start + 1 + LINK_SIZE));
+      OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize);
+      OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0);
+      OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table);
+      sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchgroups));
+      OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
+      add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0));
+      hotpath += 1 + IMM2_SIZE;
+      }
+    }
+  else
+    {
+    SLJIT_ASSERT(has_alternatives && *hotpath >= OP_ASSERT && *hotpath <= OP_ASSERTBACK_NOT);
+    /* Similar code as PUSH_FALLBACK macro. */
+    assert = sljit_alloc_memory(compiler, sizeof(assert_fallback));
+    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+      return NULL;
+    memset(assert, 0, sizeof(assert_fallback));
+    assert->common.cc = hotpath;
+    FALLBACK_AS(bracket_fallback)->u.assert = assert;
+    hotpath = compile_assert_hotpath(common, hotpath, assert, TRUE);
+    }
+  }
+
+compile_hotpath(common, hotpath, cc, fallback);
+if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+  return NULL;
+
+if (opcode == OP_ONCE)
+  {
+  if (FALLBACK_AS(bracket_fallback)->u.framesize < 0)
+    {
+    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+    /* 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 localptr. */
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0);
+      }
+    }
+  else
+    {
+    stacksize = (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) ? 2 : 1;
+    OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (FALLBACK_AS(bracket_fallback)->u.framesize + stacksize) * sizeof(sljit_w));
+    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));
+      }
+    }
+  }
+
+stacksize = 0;
+if (ket != OP_KET || bra != OP_BRA)
+  stacksize++;
+if (has_alternatives && opcode != OP_ONCE)
+  stacksize++;
+
+if (stacksize > 0)
+  allocate_stack(common, stacksize);
+
+stacksize = 0;
+if (ket != OP_KET)
+  {
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
+  stacksize++;
+  }
+else if (bra != OP_BRA)
+  {
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
+  stacksize++;
+  }
+
+if (has_alternatives)
+  {
+  if (opcode != OP_ONCE)
+    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
+  if (ket != OP_KETRMAX)
+    FALLBACK_AS(bracket_fallback)->althotpath = LABEL();
+  }
+
+/* Must be after the hotpath label. */
+if (offset != 0)
+  {
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0);
+  }
+
+if (ket == OP_KETRMAX)
+  {
+  if (opcode == OP_ONCE || opcode >= OP_SBRA)
+    {
+    if (has_alternatives)
+      FALLBACK_AS(bracket_fallback)->althotpath = LABEL();
+    /* Checking zero-length iteration. */
+    if (opcode != OP_ONCE)
+      CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0, rmaxlabel);
+    else
+      /* TMP2 must contain the starting STR_PTR. */
+      CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel);
+    }
+  else
+    JUMPTO(SLJIT_JUMP, rmaxlabel);
+  FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL();
+  }
+
+if (bra == OP_BRAZERO)
+  FALLBACK_AS(bracket_fallback)->zerohotpath = LABEL();
+
+if (bra == OP_BRAMINZERO)
+  {
+  /* This is a fallback path! (From the viewpoint of OP_BRAMINZERO) */
+  JUMPTO(SLJIT_JUMP, ((braminzero_fallback*)parent)->hotpath);
+  if (braminzerojump != NULL)
+    {
+    JUMPHERE(braminzerojump);
+    /* We need to release the end pointer to perform the
+    fallback for the zero-length iteration. When
+    framesize is < 0, OP_ONCE will do the release itself. */
+    if (opcode == OP_ONCE && FALLBACK_AS(bracket_fallback)->u.framesize >= 0)
+      {
+      OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+      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 fallback. */
+  }
+
+if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)
+  decrease_call_count(common);
+
+/* Skip the other alternatives. */
+while (*cc == OP_ALT)
+  cc += GET(cc, 1);
+cc += 1 + LINK_SIZE;
+return cc;
+}
+
+static pcre_uchar *compile_bracketpos_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)
+{
+DEFINE_COMPILER;
+fallback_common *fallback;
+pcre_uchar opcode;
+int localptr;
+int cbraprivptr = 0;
+int framesize;
+int stacksize;
+int offset = 0;
+BOOL zero = FALSE;
+pcre_uchar *ccbegin = NULL;
+int stack;
+struct sljit_label *loop = NULL;
+struct jump_list *emptymatch = NULL;
+
+PUSH_FALLBACK(sizeof(bracketpos_fallback), cc, NULL);
+if (*cc == OP_BRAPOSZERO)
+  {
+  zero = TRUE;
+  cc++;
+  }
+
+opcode = *cc;
+localptr = PRIV_DATA(cc);
+SLJIT_ASSERT(localptr != 0);
+FALLBACK_AS(bracketpos_fallback)->localptr = localptr;
+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);
+  cbraprivptr = OVECTOR_PRIV(offset);
+  offset <<= 1;
+  ccbegin = cc + 1 + LINK_SIZE + IMM2_SIZE;
+  break;
+
+  default:
+  SLJIT_ASSERT_STOP();
+  break;
+  }
+
+framesize = get_framesize(common, cc, FALSE);
+FALLBACK_AS(bracketpos_fallback)->framesize = framesize;
+if (framesize < 0)
+  {
+  stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 2 : 1;
+  if (!zero)
+    stacksize++;
+  FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize;
+  allocate_stack(common, stacksize);
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
+
+  if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
+    {
+    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);
+    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
+    }
+  else
+    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+
+  if (!zero)
+    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 1);
+  }
+else
+  {
+  stacksize = framesize + 1;
+  if (!zero)
+    stacksize++;
+  if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS)
+    stacksize++;
+  FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize;
+  allocate_stack(common, stacksize);
+
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+  OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1));
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
+  stack = 0;
+  if (!zero)
+    {
+    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1);
+    stack++;
+    }
+  if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS)
+    {
+    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, stacksize - 1, stacksize - framesize, FALSE);
+  }
+
+if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
+
+loop = LABEL();
+while (*cc != OP_KETRPOS)
+  {
+  fallback->top = NULL;
+  fallback->topfallbacks = NULL;
+  cc += GET(cc, 1);
+
+  compile_hotpath(common, ccbegin, cc, fallback);
+  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+    return NULL;
+
+  if (framesize < 0)
+    {
+    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+
+    if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
+      {
+      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);
+      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 (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
+      {
+      OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, stacksize * sizeof(sljit_w));
+      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);
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
+      }
+    else
+      {
+      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+      OP2(SLJIT_ADD, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_w));
+      if (opcode == OP_SBRAPOS)
+        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w));
+      OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w), 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);
+      }
+    }
+  JUMPTO(SLJIT_JUMP, loop);
+  flush_stubs(common);
+
+  compile_fallbackpath(common, fallback->top);
+  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+    return NULL;
+  set_jumps(fallback->topfallbacks, LABEL());
+
+  if (framesize < 0)
+    {
+    if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
+      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 (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
+      {
+      /* Last alternative. */
+      if (*cc == OP_KETRPOS)
+        OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
+      }
+    else
+      {
+      OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+      OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w));
+      }
+    }
+
+  if (*cc == OP_KETRPOS)
+    break;
+  ccbegin = cc + 1 + LINK_SIZE;
+  }
+
+fallback->topfallbacks = NULL;
+if (!zero)
+  {
+  if (framesize < 0)
+    add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0));
+  else /* TMP2 is set to [localptr] above. */
+    add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_w), SLJIT_IMM, 0));
+  }
+
+/* None of them matched. */
+set_jumps(emptymatch, LABEL());
+decrease_call_count(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 *arg1, int *arg2, 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_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
+    {
+    SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE);
+    *arg1 = GET2(cc, (class_len + IMM2_SIZE));
+    *arg2 = GET2(cc, class_len);
+
+    if (*arg2 == 0)
+      {
+      SLJIT_ASSERT(*arg1 != 0);
+      *opcode = (*opcode == OP_CRRANGE) ? OP_UPTO : OP_MINUPTO;
+      }
+    if (*arg1 == *arg2)
+      *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)
+  {
+  *arg1 = 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_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)
+{
+DEFINE_COMPILER;
+fallback_common *fallback;
+pcre_uchar opcode;
+pcre_uchar type;
+int arg1 = -1, arg2 = -1;
+pcre_uchar* end;
+jump_list *nomatch = NULL;
+struct sljit_jump *jump = NULL;
+struct sljit_label *label;
+
+PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL);
+
+cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, &end);
+
+switch(opcode)
+  {
+  case OP_STAR:
+  case OP_PLUS:
+  case OP_UPTO:
+  case OP_CRRANGE:
+  if (type == OP_ANYNL || type == OP_EXTUNI)
+    {
+    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_hotpath(common, type, cc, &fallback->topfallbacks);
+    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 && arg2 > 0)
+        CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2, label);
+      if (opcode == OP_UPTO || (opcode == OP_CRRANGE && arg1 > 0))
+        jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, arg1);
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
+      }
+
+    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
+    {
+    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, 1);
+    label = LABEL();
+    compile_char1_hotpath(common, type, cc, &nomatch);
+    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+    if (opcode <= OP_PLUS || (opcode == OP_CRRANGE && arg1 == 0))
+      {
+      OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
+      JUMPTO(SLJIT_JUMP, label);
+      }
+    else
+      {
+      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, arg1 + 1, label);
+      }
+    set_jumps(nomatch, LABEL());
+    if (opcode == OP_PLUS || opcode == OP_CRRANGE)
+      add_jump(compiler, &fallback->topfallbacks,
+        CMP(SLJIT_C_LESS, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, opcode == OP_PLUS ? 2 : arg2 + 1));
+    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+    }
+  FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
+  break;
+
+  case OP_MINSTAR:
+  case OP_MINPLUS:
+  allocate_stack(common, 1);
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+  if (opcode == OP_MINPLUS)
+    add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP));
+  FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
+  break;
+
+  case OP_MINUPTO:
+  case OP_CRMINRANGE:
+  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, 1);
+  if (opcode == OP_CRMINRANGE)
+    add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP));
+  FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
+  break;
+
+  case OP_QUERY:
+  case OP_MINQUERY:
+  allocate_stack(common, 1);
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+  if (opcode == OP_QUERY)
+    compile_char1_hotpath(common, type, cc, &fallback->topfallbacks);
+  FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
+  break;
+
+  case OP_EXACT:
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1);
+  label = LABEL();
+  compile_char1_hotpath(common, type, cc, &fallback->topfallbacks);
+  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);
+  CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);
+  break;
+
+  case OP_POSSTAR:
+  case OP_POSPLUS:
+  case OP_POSUPTO:
+  if (opcode != OP_POSSTAR)
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1);
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
+  label = LABEL();
+  compile_char1_hotpath(common, type, cc, &nomatch);
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
+  if (opcode != OP_POSUPTO)
+    {
+    if (opcode == OP_POSPLUS)
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2);
+    JUMPTO(SLJIT_JUMP, label);
+    }
+  else
+    {
+    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);
+    CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);
+    }
+  set_jumps(nomatch, LABEL());
+  if (opcode == OP_POSPLUS)
+    add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_LESS, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2));
+  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
+  break;
+
+  case OP_POSQUERY:
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
+  compile_char1_hotpath(common, type, cc, &nomatch);
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
+  set_jumps(nomatch, LABEL());
+  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
+  break;
+
+  default:
+  SLJIT_ASSERT_STOP();
+  break;
+  }
+
+decrease_call_count(common);
+return end;
+}
+
+static SLJIT_INLINE pcre_uchar *compile_fail_accept_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent)
+{
+DEFINE_COMPILER;
+fallback_common *fallback;
+
+PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL);
+
+if (*cc == OP_FAIL)
+  {
+  add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP));
+  return cc + 1;
+  }
+
+if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL)
+  {
+  /* No need to check notempty conditions. */
+  if (common->acceptlabel == NULL)
+    add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));
+  else
+    JUMPTO(SLJIT_JUMP, common->acceptlabel);
+  return cc + 1;
+  }
+
+if (common->acceptlabel == 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->acceptlabel);
+OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
+add_jump(compiler, &fallback->topfallbacks, 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->acceptlabel == 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->acceptlabel);
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+if (common->acceptlabel == 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->acceptlabel);
+add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP));
+return cc + 1;
+}
+
+static SLJIT_INLINE pcre_uchar *compile_close_hotpath(compiler_common *common, pcre_uchar *cc)
+{
+DEFINE_COMPILER;
+int offset = GET2(cc, 1);
+
+/* Data will be discarded anyway... */
+if (common->currententry != NULL)
+  return cc + 1 + IMM2_SIZE;
+
+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);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
+return cc + 1 + IMM2_SIZE;
+}
+
+static void compile_hotpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, fallback_common *parent)
+{
+DEFINE_COMPILER;
+fallback_common *fallback;
+
+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_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);
+    break;
+
+    case OP_SET_SOM:
+    PUSH_FALLBACK_NOVALUE(sizeof(fallback_common), cc);
+    allocate_stack(common, 1);
+    OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
+    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
+    cc++;
+    break;
+
+    case OP_CHAR:
+    case OP_CHARI:
+    cc = compile_charn_hotpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);
+    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_hotpath(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_CRMINRANGE)
+      cc = compile_iterator_hotpath(common, cc, parent);
+    else
+      cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);
+    break;
+
+#if defined SUPPORT_UTF || defined COMPILE_PCRE16
+    case OP_XCLASS:
+    if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRMINRANGE)
+      cc = compile_iterator_hotpath(common, cc, parent);
+    else
+      cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);
+    break;
+#endif
+
+    case OP_REF:
+    case OP_REFI:
+    if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRMINRANGE)
+      cc = compile_ref_iterator_hotpath(common, cc, parent);
+    else
+      cc = compile_ref_hotpath(common, cc, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks, TRUE, FALSE);
+    break;
+
+    case OP_RECURSE:
+    cc = compile_recurse_hotpath(common, cc, parent);
+    break;
+
+    case OP_ASSERT:
+    case OP_ASSERT_NOT:
+    case OP_ASSERTBACK:
+    case OP_ASSERTBACK_NOT:
+    PUSH_FALLBACK_NOVALUE(sizeof(assert_fallback), cc);
+    cc = compile_assert_hotpath(common, cc, FALLBACK_AS(assert_fallback), FALSE);
+    break;
+
+    case OP_BRAMINZERO:
+    PUSH_FALLBACK_NOVALUE(sizeof(braminzero_fallback), 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);
+      }
+    FALLBACK_AS(braminzero_fallback)->hotpath = LABEL();
+    if (cc[1] > OP_ASSERTBACK_NOT)
+      decrease_call_count(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_hotpath(common, cc, parent);
+    break;
+
+    case OP_BRAZERO:
+    if (cc[1] > OP_ASSERTBACK_NOT)
+      cc = compile_bracket_hotpath(common, cc, parent);
+    else
+      {
+      PUSH_FALLBACK_NOVALUE(sizeof(assert_fallback), cc);
+      cc = compile_assert_hotpath(common, cc, FALLBACK_AS(assert_fallback), FALSE);
+      }
+    break;
+
+    case OP_BRAPOS:
+    case OP_CBRAPOS:
+    case OP_SBRAPOS:
+    case OP_SCBRAPOS:
+    case OP_BRAPOSZERO:
+    cc = compile_bracketpos_hotpath(common, cc, parent);
+    break;
+
+    case OP_FAIL:
+    case OP_ACCEPT:
+    case OP_ASSERT_ACCEPT:
+    cc = compile_fail_accept_hotpath(common, cc, parent);
+    break;
+
+    case OP_CLOSE:
+    cc = compile_close_hotpath(common, cc);
+    break;
+
+    case OP_SKIPZERO:
+    cc = bracketend(cc + 1);
+    break;
+
+    default:
+    SLJIT_ASSERT_STOP();
+    return;
+    }
+  if (cc == NULL)
+    return;
+  }
+SLJIT_ASSERT(cc == ccend);
+}
+
+#undef PUSH_FALLBACK
+#undef PUSH_FALLBACK_NOVALUE
+#undef FALLBACK_AS
+
+#define COMPILE_FALLBACKPATH(current) \
+  do \
+    { \
+    compile_fallbackpath(common, (current)); \
+    if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
+      return; \
+    } \
+  while (0)
+
+#define CURRENT_AS(type) ((type*)current)
+
+static void compile_iterator_fallbackpath(compiler_common *common, struct fallback_common *current)
+{
+DEFINE_COMPILER;
+pcre_uchar *cc = current->cc;
+pcre_uchar opcode;
+pcre_uchar type;
+int arg1 = -1, arg2 = -1;
+struct sljit_label *label = NULL;
+struct sljit_jump *jump = NULL;
+
+cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, NULL);
+
+switch(opcode)
+  {
+  case OP_STAR:
+  case OP_PLUS:
+  case OP_UPTO:
+  case OP_CRRANGE:
+  if (type == OP_ANYNL || type == OP_EXTUNI)
+    {
+    set_jumps(current->topfallbacks, 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_fallback)->hotpath);
+    }
+  else
+    {
+    if (opcode == OP_STAR || opcode == OP_UPTO)
+      arg2 = 0;
+    else if (opcode == OP_PLUS)
+      arg2 = 1;
+    jump = CMP(SLJIT_C_LESS_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, arg2 + 1);
+    OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
+    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+    skip_char_back(common);
+    OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+    JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);
+    if (opcode == OP_PLUS || opcode == OP_CRRANGE)
+      set_jumps(current->topfallbacks, LABEL());
+    JUMPHERE(jump);
+    free_stack(common, 2);
+    }
+  break;
+
+  case OP_MINSTAR:
+  case OP_MINPLUS:
+  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+  if (opcode == OP_MINPLUS)
+    {
+    set_jumps(current->topfallbacks, LABEL());
+    current->topfallbacks = NULL;
+    }
+  compile_char1_hotpath(common, type, cc, &current->topfallbacks);
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+  JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);
+  set_jumps(current->topfallbacks, LABEL());
+  free_stack(common, 1);
+  break;
+
+  case OP_MINUPTO:
+  case OP_CRMINRANGE:
+  if (opcode == OP_CRMINRANGE)
+    {
+    set_jumps(current->topfallbacks, LABEL());
+    current->topfallbacks = NULL;
+    label = LABEL();
+    }
+  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+  compile_char1_hotpath(common, type, cc, &current->topfallbacks);
+
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+  OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
+
+  if (opcode == OP_CRMINRANGE)
+    CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2 + 1, label);
+
+  if (opcode == OP_CRMINRANGE && arg1 == 0)
+    JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);
+  else
+    CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 2, CURRENT_AS(iterator_fallback)->hotpath);
+
+  set_jumps(current->topfallbacks, LABEL());
+  free_stack(common, 2);
+  break;
+
+  case OP_QUERY:
+  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+  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(iterator_fallback)->hotpath);
+  jump = JUMP(SLJIT_JUMP);
+  set_jumps(current->topfallbacks, LABEL());
+  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+  JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);
+  JUMPHERE(jump);
+  free_stack(common, 1);
+  break;
+
+  case OP_MINQUERY:
+  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+  jump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
+  compile_char1_hotpath(common, type, cc, &current->topfallbacks);
+  JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);
+  set_jumps(current->topfallbacks, LABEL());
+  JUMPHERE(jump);
+  free_stack(common, 1);
+  break;
+
+  case OP_EXACT:
+  case OP_POSPLUS:
+  set_jumps(current->topfallbacks, LABEL());
+  break;
+
+  case OP_POSSTAR:
+  case OP_POSQUERY:
+  case OP_POSUPTO:
+  break;
+
+  default:
+  SLJIT_ASSERT_STOP();
+  break;
+  }
+}
+
+static void compile_ref_iterator_fallbackpath(compiler_common *common, struct fallback_common *current)
+{
+DEFINE_COMPILER;
+pcre_uchar *cc = current->cc;
+pcre_uchar type;
+
+type = cc[1 + IMM2_SIZE];
+if ((type & 0x1) == 0)
+  {
+  set_jumps(current->topfallbacks, 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_fallback)->hotpath);
+  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_fallback)->hotpath);
+set_jumps(current->topfallbacks, LABEL());
+free_stack(common, 2);
+}
+
+static void compile_recurse_fallbackpath(compiler_common *common, struct fallback_common *current)
+{
+DEFINE_COMPILER;
+
+set_jumps(current->topfallbacks, LABEL());
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+free_stack(common, 1);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);
+}
+
+static void compile_assert_fallbackpath(compiler_common *common, struct fallback_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->topfallbacks == NULL);
+  OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+  }
+
+if (CURRENT_AS(assert_fallback)->framesize < 0)
+  {
+  set_jumps(current->topfallbacks, 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_fallback)->hotpath);
+    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_fallback)->hotpath);
+    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_fallback)->localptr);
+  add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_fallback)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_fallback)->framesize * sizeof(sljit_w));
+
+  set_jumps(current->topfallbacks, LABEL());
+  }
+else
+  set_jumps(current->topfallbacks, 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_w));
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
+  JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_fallback)->hotpath);
+  JUMPHERE(brajump);
+  }
+}
+
+static void compile_bracket_fallbackpath(compiler_common *common, struct fallback_common *current)
+{
+DEFINE_COMPILER;
+int opcode;
+int offset = 0;
+int localptr = CURRENT_AS(bracket_fallback)->localptr;
+int stacksize;
+int count;
+pcre_uchar *cc = current->cc;
+pcre_uchar *ccbegin;
+pcre_uchar *ccprev;
+jump_list *jumplist = NULL;
+jump_list *jumplistitem = NULL;
+pcre_uchar bra = OP_BRA;
+pcre_uchar ket;
+assert_fallback *assert;
+BOOL has_alternatives;
+struct sljit_jump *brazero = NULL;
+struct sljit_jump *once = NULL;
+struct sljit_jump *cond = NULL;
+struct sljit_label *rminlabel = NULL;
+
+if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
+  {
+  bra = *cc;
+  cc++;
+  }
+
+opcode = *cc;
+ccbegin = cc;
+ket = *(bracketend(ccbegin) - 1 - LINK_SIZE);
+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_fallback)->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;
+
+if (ket == OP_KETRMAX)
+  {
+  if (bra != OP_BRAZERO)
+    free_stack(common, 1);
+  else
+    {
+    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 (opcode >= OP_SBRA || opcode == OP_ONCE)
+      {
+      /* Checking zero-length iteration. */
+      if (opcode != OP_ONCE || CURRENT_AS(bracket_fallback)->u.framesize < 0)
+        CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, CURRENT_AS(bracket_fallback)->recursivehotpath);
+      else
+        {
+        OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+        CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w), CURRENT_AS(bracket_fallback)->recursivehotpath);
+        }
+      if (opcode != OP_ONCE)
+        free_stack(common, 1);
+      }
+    else
+      JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->recursivehotpath);
+    }
+  rminlabel = LABEL();
+  }
+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);
+  }
+
+if (SLJIT_UNLIKELY(opcode == OP_ONCE))
+  {
+  if (CURRENT_AS(bracket_fallback)->u.framesize >= 0)
+    {
+    OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+    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);
+
+    jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list));
+    if (SLJIT_UNLIKELY(!jumplistitem))
+      return;
+    jumplist = jumplistitem;
+    jumplistitem->next = NULL;
+    jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 1);
+    }
+  }
+else if (*cc == OP_ALT)
+  {
+  /* Build a jump list. Get the last successfully matched branch index. */
+  OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+  free_stack(common, 1);
+  count = 1;
+  do
+    {
+    /* Append as the last item. */
+    if (jumplist != NULL)
+      {
+      jumplistitem->next = sljit_alloc_memory(compiler, sizeof(jump_list));
+      jumplistitem = jumplistitem->next;
+      }
+    else
+      {
+      jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list));
+      jumplist = jumplistitem;
+      }
+
+    if (SLJIT_UNLIKELY(!jumplistitem))
+      return;
+
+    jumplistitem->next = NULL;
+    jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, count++);
+    cc += GET(cc, 1);
+    }
+  while (*cc == OP_ALT);
+
+  cc = ccbegin + GET(ccbegin, 1);
+  }
+
+COMPILE_FALLBACKPATH(current->top);
+if (current->topfallbacks)
+  set_jumps(current->topfallbacks, 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_fallback)->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->localptr);
+      add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w));
+      }
+    cond = JUMP(SLJIT_JUMP);
+    set_jumps(CURRENT_AS(bracket_fallback)->u.assert->condfailed, LABEL());
+    }
+  else if (CURRENT_AS(bracket_fallback)->u.condfailed != NULL)
+    {
+    SLJIT_ASSERT(has_alternatives);
+    cond = JUMP(SLJIT_JUMP);
+    set_jumps(CURRENT_AS(bracket_fallback)->u.condfailed, LABEL());
+    }
+  else
+    SLJIT_ASSERT(!has_alternatives);
+  }
+
+if (has_alternatives)
+  {
+  count = 1;
+  do
+    {
+    current->top = NULL;
+    current->topfallbacks = NULL;
+    current->nextfallbacks = NULL;
+    if (*cc == OP_ALT)
+      {
+      ccprev = cc + 1 + LINK_SIZE;
+      cc += GET(cc, 1);
+      if (opcode != OP_COND && opcode != OP_SCOND)
+        {
+        if (localptr != 0 && opcode != OP_ONCE)
+          OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+        else
+          OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+        }
+      compile_hotpath(common, ccprev, cc, current);
+      if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+        return;
+      }
+
+    /* Instructions after the current alternative is succesfully matched. */
+    /* There is a similar code in compile_bracket_hotpath. */
+    if (opcode == OP_ONCE)
+      {
+      if (CURRENT_AS(bracket_fallback)->u.framesize < 0)
+        {
+        OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+        /* 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 localptr. */
+          OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0);
+          }
+        }
+      else
+        {
+        OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (CURRENT_AS(bracket_fallback)->u.framesize + 2) * sizeof(sljit_w));
+        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));
+          }
+        }
+      }
+
+    stacksize = 0;
+    if (opcode != OP_ONCE)
+      stacksize++;
+    if (ket != OP_KET || bra != OP_BRA)
+      stacksize++;
+
+    if (stacksize > 0) {
+      if (opcode != OP_ONCE || CURRENT_AS(bracket_fallback)->u.framesize >= 0)
+        allocate_stack(common, stacksize);
+      else
+        {
+        /* We know we have place at least for one item on the top of the stack. */
+        SLJIT_ASSERT(stacksize == 1);
+        OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
+        }
+    }
+
+    stacksize = 0;
+    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 (opcode != OP_ONCE)
+      OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, count++);
+
+    if (offset != 0)
+      {
+      OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0);
+      }
+
+    JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->althotpath);
+
+    if (opcode != OP_ONCE)
+      {
+      SLJIT_ASSERT(jumplist);
+      JUMPHERE(jumplist->jump);
+      jumplist = jumplist->next;
+      }
+
+    COMPILE_FALLBACKPATH(current->top);
+    if (current->topfallbacks)
+      set_jumps(current->topfallbacks, LABEL());
+    SLJIT_ASSERT(!current->nextfallbacks);
+    }
+  while (*cc == OP_ALT);
+  SLJIT_ASSERT(!jumplist);
+
+  if (cond != NULL)
+    {
+    SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND);
+    assert = CURRENT_AS(bracket_fallback)->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->localptr);
+      add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+      OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w));
+      }
+    JUMPHERE(cond);
+    }
+
+  /* Free the STR_PTR. */
+  if (localptr == 0)
+    free_stack(common, 1);
+  }
+
+if (offset != 0)
+  {
+  /* Using both tmp register is better for instruction scheduling. */
+  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);
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), STACK(2));
+  free_stack(common, 3);
+  }
+else if (opcode == OP_SBRA || opcode == OP_SCOND)
+  {
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), STACK(0));
+  free_stack(common, 1);
+  }
+else if (opcode == OP_ONCE)
+  {
+  cc = ccbegin + GET(ccbegin, 1);
+  if (CURRENT_AS(bracket_fallback)->u.framesize >= 0)
+    {
+    /* Reset head and drop saved frame. */
+    stacksize = (ket == OP_KETRMAX || ket == OP_KETRMIN || *cc == OP_ALT) ? 2 : 1;
+    free_stack(common, CURRENT_AS(bracket_fallback)->u.framesize + stacksize);
+    }
+  else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN))
+    {
+    /* The STR_PTR must be released. */
+    free_stack(common, 1);
+    }
+
+  JUMPHERE(once);
+  /* Restore previous localptr */
+  if (CURRENT_AS(bracket_fallback)->u.framesize >= 0)
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_fallback)->u.framesize * sizeof(sljit_w));
+  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), localptr, TMP1, 0);
+    }
+  }
+
+if (ket == OP_KETRMAX)
+  {
+  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(bracket_fallback)->recursivehotpath);
+  if (bra == OP_BRAZERO)
+    {
+    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
+    JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->zerohotpath);
+    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 fallback, 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, rminlabel);
+  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_fallback)->zerohotpath);
+  JUMPHERE(brazero);
+  }
+}
+
+static void compile_bracketpos_fallbackpath(compiler_common *common, struct fallback_common *current)
+{
+DEFINE_COMPILER;
+int offset;
+struct sljit_jump *jump;
+
+if (CURRENT_AS(bracketpos_fallback)->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);
+    OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
+    }
+  set_jumps(current->topfallbacks, LABEL());
+  free_stack(common, CURRENT_AS(bracketpos_fallback)->stacksize);
+  return;
+  }
+
+OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_fallback)->localptr);
+add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+
+if (current->topfallbacks)
+  {
+  jump = JUMP(SLJIT_JUMP);
+  set_jumps(current->topfallbacks, LABEL());
+  /* Drop the stack frame. */
+  free_stack(common, CURRENT_AS(bracketpos_fallback)->stacksize);
+  JUMPHERE(jump);
+  }
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_fallback)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_fallback)->framesize * sizeof(sljit_w));
+}
+
+static void compile_braminzero_fallbackpath(compiler_common *common, struct fallback_common *current)
+{
+assert_fallback fallback;
+
+current->top = NULL;
+current->topfallbacks = NULL;
+current->nextfallbacks = NULL;
+if (current->cc[1] > OP_ASSERTBACK_NOT)
+  {
+  /* Manual call of compile_bracket_hotpath and compile_bracket_fallbackpath. */
+  compile_bracket_hotpath(common, current->cc, current);
+  compile_bracket_fallbackpath(common, current->top);
+  }
+else
+  {
+  memset(&fallback, 0, sizeof(fallback));
+  fallback.common.cc = current->cc;
+  fallback.hotpath = CURRENT_AS(braminzero_fallback)->hotpath;
+  /* Manual call of compile_assert_hotpath. */
+  compile_assert_hotpath(common, current->cc, &fallback, FALSE);
+  }
+SLJIT_ASSERT(!current->nextfallbacks && !current->topfallbacks);
+}
+
+static void compile_fallbackpath(compiler_common *common, struct fallback_common *current)
+{
+DEFINE_COMPILER;
+
+while (current)
+  {
+  if (current->nextfallbacks != NULL)
+    set_jumps(current->nextfallbacks, 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_fallbackpath(common, current);
+    break;
+
+    case OP_REF:
+    case OP_REFI:
+    compile_ref_iterator_fallbackpath(common, current);
+    break;
+
+    case OP_RECURSE:
+    compile_recurse_fallbackpath(common, current);
+    break;
+
+    case OP_ASSERT:
+    case OP_ASSERT_NOT:
+    case OP_ASSERTBACK:
+    case OP_ASSERTBACK_NOT:
+    compile_assert_fallbackpath(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_fallbackpath(common, current);
+    break;
+
+    case OP_BRAZERO:
+    if (current->cc[1] > OP_ASSERTBACK_NOT)
+      compile_bracket_fallbackpath(common, current);
+    else
+      compile_assert_fallbackpath(common, current);
+    break;
+
+    case OP_BRAPOS:
+    case OP_CBRAPOS:
+    case OP_SBRAPOS:
+    case OP_SCBRAPOS:
+    case OP_BRAPOSZERO:
+    compile_bracketpos_fallbackpath(common, current);
+    break;
+
+    case OP_BRAMINZERO:
+    compile_braminzero_fallbackpath(common, current);
+    break;
+
+    case OP_FAIL:
+    case OP_ACCEPT:
+    case OP_ASSERT_ACCEPT:
+    set_jumps(current->topfallbacks, LABEL());
+    break;
+
+    default:
+    SLJIT_ASSERT_STOP();
+    break;
+    }
+  current = current->prev;
+  }
+}
+
+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);
+int localsize = get_localsize(common, ccbegin, ccend);
+int framesize = get_framesize(common, cc, TRUE);
+int alternativesize;
+BOOL needsframe;
+fallback_common altfallback;
+struct sljit_jump *jump;
+
+SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS);
+needsframe = framesize >= 0;
+if (!needsframe)
+  framesize = 0;
+alternativesize = *(cc + GET(cc, 1)) == OP_ALT ? 1 : 0;
+
+SLJIT_ASSERT(common->currententry->entry == NULL);
+common->currententry->entry = LABEL();
+set_jumps(common->currententry->calls, common->currententry->entry);
+
+sljit_emit_fast_enter(compiler, TMP2, 0, 1, 5, 5, common->localsize);
+allocate_stack(common, localsize + framesize + alternativesize);
+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(localsize + framesize + alternativesize - 1), TMP2, 0);
+copy_locals(common, ccbegin, ccend, TRUE, localsize + framesize + alternativesize, framesize + alternativesize);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), RECURSIVE_HEAD, STACK_TOP, 0);
+if (needsframe)
+  init_frame(common, cc, framesize + alternativesize - 1, alternativesize, FALSE);
+
+if (alternativesize > 0)
+  OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
+
+memset(&altfallback, 0, sizeof(fallback_common));
+common->acceptlabel = NULL;
+common->accept = NULL;
+altfallback.cc = ccbegin;
+cc += GET(cc, 1);
+while (1)
+  {
+  altfallback.top = NULL;
+  altfallback.topfallbacks = NULL;
+
+  if (altfallback.cc != ccbegin)
+    OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
+
+  compile_hotpath(common, altfallback.cc, cc, &altfallback);
+  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+    return;
+
+  add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));
+
+  compile_fallbackpath(common, altfallback.top);
+  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+    return;
+  set_jumps(altfallback.topfallbacks, LABEL());
+
+  if (*cc != OP_ALT)
+    break;
+
+  altfallback.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);
+
+set_jumps(common->accept, LABEL());
+OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), RECURSIVE_HEAD);
+if (needsframe)
+  {
+  OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
+  OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w));
+  add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
+  OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w));
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP3, 0);
+  }
+OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1);
+
+JUMPHERE(jump);
+copy_locals(common, ccbegin, ccend, FALSE, localsize + framesize + alternativesize, framesize + alternativesize);
+free_stack(common, localsize + framesize + alternativesize);
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_w));
+OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), RECURSIVE_HEAD, TMP2, 0);
+sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0);
+}
+
+#undef COMPILE_FALLBACKPATH
+#undef CURRENT_AS
+
+void
+PRIV(jit_compile)(const REAL_PCRE *re, PUBL(extra) *extra)
+{
+struct sljit_compiler *compiler;
+fallback_common rootfallback;
+compiler_common common_data;
+compiler_common *common = &common_data;
+const pcre_uint8 *tables = re->tables;
+pcre_study_data *study;
+pcre_uchar *ccend;
+executable_function *function;
+void *executable_func;
+sljit_uw executable_size;
+struct sljit_label *leave;
+struct sljit_label *mainloop = NULL;
+struct sljit_label *empty_match_found;
+struct sljit_label *empty_match_fallback;
+struct sljit_jump *alloc_error;
+struct sljit_jump *reqbyte_notfound = NULL;
+struct sljit_jump *empty_match;
+
+SLJIT_ASSERT((extra->flags & PCRE_EXTRA_STUDY_DATA) != 0);
+study = extra->study_data;
+
+if (!tables)
+  tables = PRIV(default_tables);
+
+memset(&rootfallback, 0, sizeof(fallback_common));
+rootfallback.cc = (pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size;
+
+common->compiler = NULL;
+common->start = rootfallback.cc;
+common->cbraptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_w);
+common->fcc = tables + fcc_offset;
+common->lcc = (sljit_w)(tables + lcc_offset);
+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;
+  }
+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->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
+common->ctypes = (sljit_w)(tables + ctypes_offset);
+common->name_table = (sljit_w)((pcre_uchar *)re + re->name_table_offset);
+common->name_count = re->name_count;
+common->name_entry_size = re->name_entry_size;
+common->acceptlabel = NULL;
+common->stubs = NULL;
+common->entries = NULL;
+common->currententry = NULL;
+common->accept = NULL;
+common->calllimit = NULL;
+common->stackalloc = NULL;
+common->revertframes = NULL;
+common->wordboundary = NULL;
+common->anynewline = NULL;
+common->hspace = NULL;
+common->vspace = NULL;
+common->casefulcmp = NULL;
+common->caselesscmp = NULL;
+common->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
+#ifdef SUPPORT_UTF
+/* PCRE_UTF16 has 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
+common->utfreadchar = NULL;
+#ifdef COMPILE_PCRE8
+common->utfreadtype8 = NULL;
+#endif
+#endif /* SUPPORT_UTF */
+#ifdef SUPPORT_UCP
+common->getucd = NULL;
+#endif
+ccend = bracketend(rootfallback.cc);
+SLJIT_ASSERT(*rootfallback.cc == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET);
+common->localsize = get_localspace(common, rootfallback.cc, ccend);
+if (common->localsize < 0)
+  return;
+common->localsize += common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w);
+if (common->localsize > SLJIT_MAX_LOCAL_SIZE)
+  return;
+common->localptrs = (int*)SLJIT_MALLOC((ccend - rootfallback.cc) * sizeof(int));
+if (!common->localptrs)
+  return;
+memset(common->localptrs, 0, (ccend - rootfallback.cc) * sizeof(int));
+set_localptrs(common, common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w), ccend);
+
+compiler = sljit_create_compiler();
+if (!compiler)
+  {
+  SLJIT_FREE(common->localptrs);
+  return;
+  }
+common->compiler = compiler;
+
+/* Main pcre_jit_exec entry. */
+sljit_emit_enter(compiler, 1, 5, 5, common->localsize);
+
+/* Register init. */
+reset_ovector(common, (re->top_bracket + 1) * 2);
+if ((re->flags & PCRE_REQCHSET) != 0)
+  OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR, SLJIT_TEMPORARY_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_SI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, calllimit));
+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), CALL_LIMIT, TMP1, 0);
+
+/* Main part of the matching */
+if ((re->options & PCRE_ANCHORED) == 0)
+  {
+  mainloop = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0);
+  /* Forward search if possible. */
+  if ((re->flags & PCRE_FIRSTSET) != 0)
+    fast_forward_first_char(common, 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, (sljit_uw)study->start_bits, (re->options & PCRE_FIRSTLINE) != 0);
+  }
+if ((re->flags & PCRE_REQCHSET) != 0)
+  reqbyte_notfound = search_requested_char(common, 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, CALL_COUNT, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT);
+
+compile_hotpath(common, rootfallback.cc, ccend, &rootfallback);
+if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+  {
+  sljit_free_compiler(compiler);
+  SLJIT_FREE(common->localptrs);
+  return;
+  }
+
+empty_match = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
+empty_match_found = LABEL();
+
+common->acceptlabel = LABEL();
+if (common->accept != NULL)
+  set_jumps(common->accept, common->acceptlabel);
+
+/* This means we have a match. Update the ovector. */
+copy_ovector(common, re->top_bracket + 1);
+leave = LABEL();
+sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);
+
+empty_match_fallback = LABEL();
+compile_fallbackpath(common, rootfallback.top);
+if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+  {
+  sljit_free_compiler(compiler);
+  SLJIT_FREE(common->localptrs);
+  return;
+  }
+
+SLJIT_ASSERT(rootfallback.prev == NULL);
+
+/* Check we have remaining characters. */
+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
+
+if ((re->options & PCRE_ANCHORED) == 0)
+  {
+  if ((re->options & PCRE_FIRSTLINE) == 0)
+    {
+    if (study != NULL && study->minlength > 1)
+      {
+      OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength));
+      CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_END, 0, mainloop);
+      }
+    else
+      CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);
+    }
+  else
+    {
+    if (study != NULL && study->minlength > 1)
+      {
+      OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength));
+      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);
+      COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER);
+      OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
+      COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_GREATER_EQUAL);
+      JUMPTO(SLJIT_C_ZERO, mainloop);
+      }
+    else
+      CMPTO(SLJIT_C_LESS, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, mainloop);
+    }
+  }
+
+if (reqbyte_notfound != NULL)
+  JUMPHERE(reqbyte_notfound);
+/* Copy OVECTOR(1) to OVECTOR(0) */
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
+JUMPTO(SLJIT_JUMP, leave);
+
+flush_stubs(common);
+
+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_fallback);
+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);
+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);
+JUMPTO(SLJIT_JUMP, empty_match_fallback);
+
+common->currententry = common->entries;
+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->localptrs);
+    return;
+    }
+  flush_stubs(common);
+  common->currententry = common->currententry->next;
+  }
+
+/* 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, 1, 5, 5, common->localsize);
+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));
+alloc_error = 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(alloc_error);
+/* 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, leave);
+
+/* Call limit reached. */
+set_jumps(common->calllimit, LABEL());
+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT);
+JUMPTO(SLJIT_JUMP, leave);
+
+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);
+  }
+#ifdef SUPPORT_UTF
+if (common->utfreadchar != NULL)
+  {
+  set_jumps(common->utfreadchar, LABEL());
+  do_utfreadchar(common);
+  }
+#ifdef COMPILE_PCRE8
+if (common->utfreadtype8 != NULL)
+  {
+  set_jumps(common->utfreadtype8, LABEL());
+  do_utfreadtype8(common);
+  }
+#endif
+#endif /* COMPILE_PCRE8 */
+#ifdef SUPPORT_UCP
+if (common->getucd != NULL)
+  {
+  set_jumps(common->getucd, LABEL());
+  do_getucd(common);
+  }
+#endif
+
+SLJIT_FREE(common->localptrs);
+executable_func = sljit_generate_code(compiler);
+executable_size = sljit_get_generated_code_size(compiler);
+sljit_free_compiler(compiler);
+if (executable_func == NULL)
+  return;
+
+function = SLJIT_MALLOC(sizeof(executable_function));
+if (function == NULL)
+  {
+  /* This case is highly unlikely since we just recently
+  freed a lot of memory. Although not impossible. */
+  sljit_free_code(executable_func);
+  return;
+  }
+
+function->executable_func = executable_func;
+function->executable_size = executable_size;
+function->callback = NULL;
+function->userdata = NULL;
+extra->executable_jit = function;
+extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT;
+}
+
+static int jit_machine_stack_exec(jit_arguments *arguments, executable_function *function)
+{
+union {
+   void* executable_func;
+   jit_function call_executable_func;
+} convert_executable_func;
+pcre_uint8 local_area[LOCAL_SPACE_SIZE];
+struct sljit_stack local_stack;
+
+local_stack.top = (sljit_w)&local_area;
+local_stack.base = local_stack.top;
+local_stack.limit = local_stack.base + LOCAL_SPACE_SIZE;
+local_stack.max_limit = local_stack.limit;
+arguments->stack = &local_stack;
+convert_executable_func.executable_func = function->executable_func;
+return convert_executable_func.call_executable_func(arguments);
+}
+
+int
+PRIV(jit_exec)(const REAL_PCRE *re, void *executable_func,
+  const pcre_uchar *subject, int length, int start_offset, int options,
+  int match_limit, int *offsets, int offsetcount)
+{
+executable_function *function = (executable_function*)executable_func;
+union {
+   void* executable_func;
+   jit_function call_executable_func;
+} convert_executable_func;
+jit_arguments arguments;
+int maxoffsetcount;
+int retval;
+
+/* Sanity checks should be handled by pcre_exec. */
+arguments.stack = NULL;
+arguments.str = subject + start_offset;
+arguments.begin = subject;
+arguments.end = subject + length;
+arguments.calllimit = match_limit; /* JIT decreases this value less times. */
+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;
+
+/* pcre_exec() rounds offsetcount 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 (offsetcount != 2)
+  offsetcount = ((offsetcount - (offsetcount % 3)) * 2) / 3;
+maxoffsetcount = (re->top_bracket + 1) * 2;
+if (offsetcount > maxoffsetcount)
+  offsetcount = maxoffsetcount;
+arguments.offsetcount = offsetcount;
+
+if (function->callback)
+  arguments.stack = (struct sljit_stack*)function->callback(function->userdata);
+else
+  arguments.stack = (struct sljit_stack*)function->userdata;
+
+if (arguments.stack == NULL)
+  retval = jit_machine_stack_exec(&arguments, function);
+else
+  {
+  convert_executable_func.executable_func = function->executable_func;
+  retval = convert_executable_func.call_executable_func(&arguments);
+  }
+
+if (retval * 2 > offsetcount)
+  retval = 0;
+return retval;
+}
+
+void
+PRIV(jit_free)(void *executable_func)
+{
+executable_function *function = (executable_function*)executable_func;
+sljit_free_code(function->executable_func);
+SLJIT_FREE(function);
+}
+
+int
+PRIV(jit_get_size)(void *executable_func)
+{
+return ((executable_function*)executable_func)->executable_size;
+}
+
+const char*
+PRIV(jit_get_target)(void)
+{
+return sljit_get_platform_name();
+}
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DECL pcre_jit_stack *
+pcre_jit_stack_alloc(int startsize, int maxsize)
+#else
+PCRE_EXP_DECL pcre16_jit_stack *
+pcre16_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);
+}
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DECL void
+pcre_jit_stack_free(pcre_jit_stack *stack)
+#else
+PCRE_EXP_DECL void
+pcre16_jit_stack_free(pcre16_jit_stack *stack)
+#endif
+{
+sljit_free_stack((struct sljit_stack*)stack);
+}
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DECL void
+pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
+#else
+PCRE_EXP_DECL void
+pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)
+#endif
+{
+executable_function *function;
+if (extra != NULL &&
+    (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
+    extra->executable_jit != NULL)
+  {
+  function = (executable_function*)extra->executable_jit;
+  function->callback = callback;
+  function->userdata = userdata;
+  }
+}
+
+#else  /* SUPPORT_JIT */
+
+/* These are dummy functions to avoid linking errors when JIT support is not
+being compiled. */
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DECL pcre_jit_stack *
+pcre_jit_stack_alloc(int startsize, int maxsize)
+#else
+PCRE_EXP_DECL pcre16_jit_stack *
+pcre16_jit_stack_alloc(int startsize, int maxsize)
+#endif
+{
+(void)startsize;
+(void)maxsize;
+return NULL;
+}
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DECL void
+pcre_jit_stack_free(pcre_jit_stack *stack)
+#else
+PCRE_EXP_DECL void
+pcre16_jit_stack_free(pcre16_jit_stack *stack)
+#endif
+{
+(void)stack;
+}
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DECL void
+pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
+#else
+PCRE_EXP_DECL void
+pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)
+#endif
+{
+(void)extra;
+(void)callback;
+(void)userdata;
+}
+
+#endif
+
+/* End of pcre_jit_compile.c */
diff --git a/src/3rdparty/pcre/pcre_maketables.c b/src/3rdparty/pcre/pcre_maketables.c
new file mode 100644 (file)
index 0000000..caacdba
--- /dev/null
@@ -0,0 +1,148 @@
+/*************************************************
+*      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 PCRE_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
+*/
+
+#ifdef COMPILE_PCRE8
+const unsigned char *
+pcre_maketables(void)
+#else
+const unsigned char *
+pcre16_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:]. 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 exclude VT from the white
+space chars, because Perl doesn't recognize it as such for \s and for comments
+within regexes. */
+
+for (i = 0; i < 256; i++)
+  {
+  int x = 0;
+  if (i != 0x0b && 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/src/3rdparty/pcre/pcre_newline.c b/src/3rdparty/pcre/pcre_newline.c
new file mode 100644 (file)
index 0000000..8ee2a6e
--- /dev/null
@@ -0,0 +1,184 @@
+/*************************************************
+*      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 PCRE_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)
+{
+int c;
+(void)utf;
+#ifdef SUPPORT_UTF
+if (utf)
+  {
+  GETCHAR(c, ptr);
+  }
+else
+#endif  /* SUPPORT_UTF */
+  c = *ptr;
+
+if (type == NLTYPE_ANYCRLF) switch(c)
+  {
+  case 0x000a: *lenptr = 1; return TRUE;             /* LF */
+  case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1;
+               return TRUE;                          /* CR */
+  default: return FALSE;
+  }
+
+/* NLTYPE_ANY */
+
+else switch(c)
+  {
+  case 0x000a:                                       /* LF */
+  case 0x000b:                                       /* VT */
+  case 0x000c: *lenptr = 1; return TRUE;             /* FF */
+  case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1;
+               return TRUE;                          /* CR */
+#ifdef COMPILE_PCRE8
+  case 0x0085: *lenptr = utf? 2 : 1; return TRUE;    /* NEL */
+  case 0x2028:                                       /* LS */
+  case 0x2029: *lenptr = 3; return TRUE;             /* PS */
+#else
+  case 0x0085:                                       /* NEL */
+  case 0x2028:                                       /* LS */
+  case 0x2029: *lenptr = 1; return TRUE;             /* PS */
+#endif /* COMPILE_PCRE8 */
+  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)
+{
+int c;
+(void)utf;
+ptr--;
+#ifdef SUPPORT_UTF
+if (utf)
+  {
+  BACKCHAR(ptr);
+  GETCHAR(c, ptr);
+  }
+else
+#endif  /* SUPPORT_UTF */
+  c = *ptr;
+
+if (type == NLTYPE_ANYCRLF) switch(c)
+  {
+  case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1;
+               return TRUE;                         /* LF */
+  case 0x000d: *lenptr = 1; return TRUE;            /* CR */
+  default: return FALSE;
+  }
+
+else switch(c)
+  {
+  case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1;
+               return TRUE;                         /* LF */
+  case 0x000b:                                      /* VT */
+  case 0x000c:                                      /* FF */
+  case 0x000d: *lenptr = 1; return TRUE;            /* CR */
+#ifdef COMPILE_PCRE8
+  case 0x0085: *lenptr = utf? 2 : 1; return TRUE;   /* NEL */
+  case 0x2028:                                      /* LS */
+  case 0x2029: *lenptr = 3; return TRUE;            /* PS */
+#else
+  case 0x0085:                                       /* NEL */
+  case 0x2028:                                       /* LS */
+  case 0x2029: *lenptr = 1; return TRUE;             /* PS */
+#endif /* COMPILE_PCRE8 */
+  default: return FALSE;
+  }
+}
+
+/* End of pcre_newline.c */
diff --git a/src/3rdparty/pcre/pcre_ord2utf8.c b/src/3rdparty/pcre/pcre_ord2utf8.c
new file mode 100644 (file)
index 0000000..6afd235
--- /dev/null
@@ -0,0 +1,97 @@
+/*************************************************
+*      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 UTF8 string. */
+
+#ifdef PCRE_HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+
+/*************************************************
+*       Convert character value to UTF-8         *
+*************************************************/
+
+/* This function takes an integer value in the range 0 - 0x10ffff
+and encodes it as a UTF-8 character in 1 to 6 pcre_uchars.
+
+Arguments:
+  cvalue     the character value
+  buffer     pointer to buffer for result - at least 6 pcre_uchars long
+
+Returns:     number of characters placed in the buffer
+*/
+
+int
+PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer)
+{
+#ifdef SUPPORT_UTF
+
+register int i, j;
+
+/* Checking invalid cvalue character, encoded as invalid UTF-16 character.
+Should never happen in practice. */
+if ((cvalue & 0xf800) == 0xd800 || cvalue >= 0x110000)
+  cvalue = 0xfffe;
+
+for (i = 0; i < PRIV(utf8_table1_size); i++)
+  if ((int)cvalue <= PRIV(utf8_table1)[i]) break;
+buffer += i;
+for (j = i; j > 0; j--)
+ {
+ *buffer-- = 0x80 | (cvalue & 0x3f);
+ cvalue >>= 6;
+ }
+*buffer = PRIV(utf8_table2)[i] | cvalue;
+return i + 1;
+
+#else
+
+(void)(cvalue);  /* Keep compiler happy; this function won't ever be */
+(void)(buffer);  /* called when SUPPORT_UTF is not defined. */
+return 0;
+
+#endif
+}
+
+/* End of pcre_ord2utf8.c */
diff --git a/src/3rdparty/pcre/pcre_refcount.c b/src/3rdparty/pcre/pcre_refcount.c
new file mode 100644 (file)
index 0000000..263a1e1
--- /dev/null
@@ -0,0 +1,89 @@
+/*************************************************
+*      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 PCRE_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
+*/
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre_refcount(pcre *argument_re, int adjust)
+#else
+PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
+pcre16_refcount(pcre16 *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/src/3rdparty/pcre/pcre_string_utils.c b/src/3rdparty/pcre/pcre_string_utils.c
new file mode 100644 (file)
index 0000000..d454553
--- /dev/null
@@ -0,0 +1,168 @@
+/*************************************************
+*      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 an internal function that is used to match an extended
+class. It is used by both pcre_exec() and pcre_def_exec(). */
+
+
+#ifdef PCRE_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 an 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;
+}
+
+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;
+}
+
+/* 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/src/3rdparty/pcre/pcre_study.c b/src/3rdparty/pcre/pcre_study.c
new file mode 100644 (file)
index 0000000..6b6edc3
--- /dev/null
@@ -0,0 +1,1527 @@
+/*************************************************
+*      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 PCRE_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:
+  code            pointer to start of group (the bracket)
+  startcode       pointer to start of the whole pattern
+  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 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 int 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(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_NCREF:
+    case OP_RREF:
+    case OP_NRREF:
+    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 */
+
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+    case OP_XCLASS:
+    cc += GET(cc, 1) - PRIV(OP_lengths)[OP_CLASS];
+    /* Fall through */
+#endif
+
+    case OP_CLASS:
+    case OP_NCLASS:
+    cc += PRIV(OP_lengths)[OP_CLASS];
+
+    switch (*cc)
+      {
+      case OP_CRPLUS:
+      case OP_CRMINPLUS:
+      branchlength++;
+      /* Fall through */
+
+      case OP_CRSTAR:
+      case OP_CRMINSTAR:
+      case OP_CRQUERY:
+      case OP_CRMINQUERY:
+      cc++;
+      break;
+
+      case OP_CRRANGE:
+      case OP_CRMINRANGE:
+      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_REF:
+    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(cs, startcode, options, recurse_depth);
+        }
+      }
+    else d = 0;
+    cc += 1 + IMM2_SIZE;
+
+    /* Handle repeated back references */
+
+    switch (*cc)
+      {
+      case OP_CRSTAR:
+      case OP_CRMINSTAR:
+      case OP_CRQUERY:
+      case OP_CRMINQUERY:
+      min = 0;
+      cc++;
+      break;
+
+      case OP_CRPLUS:
+      case OP_CRMINPLUS:
+      min = 1;
+      cc++;
+      break;
+
+      case OP_CRRANGE:
+      case OP_CRMINRANGE:
+      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(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 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)
+{
+unsigned int 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
+  return p;
+  }
+#endif
+
+/* 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
+
+#ifdef COMPILE_PCRE16
+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
+  return p;
+  }
+#endif
+
+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, int table_limit,
+  compile_data *cd)
+{
+register int 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, int table_limit,
+  compile_data *cd)
+{
+register int 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 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 int 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_DOLL:
+      case OP_DOLLM:
+      case OP_END:
+      case OP_EOD:
+      case OP_EODN:
+      case OP_EXTUNI:
+      case OP_FAIL:
+      case OP_MARK:
+      case OP_NCREF:
+      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_NRREF:
+      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:
+#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+      case OP_XCLASS:
+#endif
+      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(0x09);
+      SET_BIT(0x20);
+#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 */
+#endif
+#ifdef COMPILE_PCRE16
+        SET_BIT(0xA0);
+        SET_BIT(0xFF);  /* For characters > 255 */
+#endif
+        }
+      else
+#endif /* SUPPORT_UTF */
+        {
+        SET_BIT(0xA0);
+#ifdef COMPILE_PCRE16
+        SET_BIT(0xFF);  /* For characters > 255 */
+#endif
+        }
+      try_next = FALSE;
+      break;
+
+      case OP_ANYNL:
+      case OP_VSPACE:
+      SET_BIT(0x0A);
+      SET_BIT(0x0B);
+      SET_BIT(0x0C);
+      SET_BIT(0x0D);
+#ifdef SUPPORT_UTF
+      if (utf)
+        {
+#ifdef COMPILE_PCRE8
+        SET_BIT(0xC2);  /* For U+0085 */
+        SET_BIT(0xE2);  /* For U+2028, U+2029 */
+#endif
+#ifdef COMPILE_PCRE16
+        SET_BIT(0x85);
+        SET_BIT(0xFF);  /* For characters > 255 */
+#endif
+        }
+      else
+#endif /* SUPPORT_UTF */
+        {
+        SET_BIT(0x85);
+#ifdef COMPILE_PCRE16
+        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. */
+
+      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. */
+
+      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(0x09);
+        SET_BIT(0x20);
+#ifdef COMPILE_PCRE8
+        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 */
+#endif
+#ifdef COMPILE_PCRE16
+          SET_BIT(0xA0);
+          SET_BIT(0xFF);  /* For characters > 255 */
+#endif
+          }
+        else
+#endif /* SUPPORT_UTF */
+          SET_BIT(0xA0);
+        break;
+
+        case OP_ANYNL:
+        case OP_VSPACE:
+        SET_BIT(0x0A);
+        SET_BIT(0x0B);
+        SET_BIT(0x0C);
+        SET_BIT(0x0D);
+#ifdef COMPILE_PCRE8
+        if (utf)
+          {
+#ifdef COMPILE_PCRE8
+          SET_BIT(0xC2);  /* For U+0085 */
+          SET_BIT(0xE2);  /* For U+2028, U+2029 */
+#endif
+#ifdef COMPILE_PCRE16
+          SET_BIT(0x85);
+          SET_BIT(0xFF);  /* For characters > 255 */
+#endif
+          }
+        else
+#endif /* SUPPORT_UTF */
+          SET_BIT(0x85);
+        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 have to
+        ensure it gets set as not whitespace. */
+
+        case OP_NOT_WHITESPACE:
+        set_nottype_bits(start_bits, cbit_space, table_limit, cd);
+        start_bits[1] |= 0x08;
+        break;
+
+        /* The cbit_space table has vertical tab as whitespace; we have to
+        avoid setting it. */
+
+        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;
+        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. */
+
+      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
+#ifdef COMPILE_PCRE16
+      SET_BIT(0xFF);                         /* For characters > 255 */
+#endif
+      /* Fall through */
+
+      case OP_CLASS:
+        {
+        pcre_uint8 *map;
+        tcode++;
+        map = (pcre_uint8 *)tcode;
+
+        /* 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 (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. */
+
+        tcode += 32 / sizeof(pcre_uchar);
+        switch (*tcode)
+          {
+          case OP_CRSTAR:
+          case OP_CRMINSTAR:
+          case OP_CRQUERY:
+          case OP_CRMINQUERY:
+          tcode++;
+          break;
+
+          case OP_CRRANGE:
+          case OP_CRMINRANGE:
+          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
+*/
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DEFN pcre_extra * PCRE_CALL_CONVENTION
+pcre_study(const pcre *external_re, int options, const char **errorptr)
+#else
+PCRE_EXP_DEFN pcre16_extra * PCRE_CALL_CONVENTION
+pcre16_study(const pcre16 *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)
+  {
+#ifdef COMPILE_PCRE8
+  *errorptr = "argument is compiled in 16 bit mode";
+#else
+  *errorptr = "argument is compiled in 8 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;
+
+#ifdef COMPILE_PCRE8
+  if (tables == NULL)
+    (void)pcre_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
+    (void *)(&tables));
+#else
+  if (tables == NULL)
+    (void)pcre16_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(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, 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
+#ifdef SUPPORT_JIT
+    || (options & PCRE_STUDY_JIT_COMPILE) != 0
+#endif
+  )
+  {
+  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. */
+
+#ifdef SUPPORT_JIT
+  extra->executable_jit = NULL;
+  if ((options & PCRE_STUDY_JIT_COMPILE) != 0) PRIV(jit_compile)(re, extra);
+  if (study->flags == 0 && (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) == 0)
+    {
+#ifdef COMPILE_PCRE8
+    pcre_free_study(extra);
+#endif
+#ifdef COMPILE_PCRE16
+    pcre16_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
+*/
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DEFN void
+pcre_free_study(pcre_extra *extra)
+#else
+PCRE_EXP_DEFN void
+pcre16_free_study(pcre16_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/src/3rdparty/pcre/pcre_tables.c b/src/3rdparty/pcre/pcre_tables.c
new file mode 100644 (file)
index 0000000..9e449f8
--- /dev/null
@@ -0,0 +1,568 @@
+/*************************************************
+*      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 PCRE_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 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)
+
+/* These tables are also required by pcretest in 16 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_PCRE16)*/
+
+#ifdef SUPPORT_UTF
+
+/* Table to translate from particular type value to the general value. */
+
+const int 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 */
+};
+
+#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_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_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_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_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_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_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_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_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_Shavian0
+  STRING_Sinhala0
+  STRING_Sk0
+  STRING_Sm0
+  STRING_So0
+  STRING_Sundanese0
+  STRING_Syloti_Nagri0
+  STRING_Syriac0
+  STRING_Tagalog0
+  STRING_Tagbanwa0
+  STRING_Tai_Le0
+  STRING_Tai_Tham0
+  STRING_Tai_Viet0
+  STRING_Tamil0
+  STRING_Telugu0
+  STRING_Thaana0
+  STRING_Thai0
+  STRING_Tibetan0
+  STRING_Tifinagh0
+  STRING_Ugaritic0
+  STRING_Vai0
+  STRING_Xan0
+  STRING_Xps0
+  STRING_Xsp0
+  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_Cham },
+  { 136, PT_SC, ucp_Cherokee },
+  { 145, PT_PC, ucp_Cn },
+  { 148, PT_PC, ucp_Co },
+  { 151, PT_SC, ucp_Common },
+  { 158, PT_SC, ucp_Coptic },
+  { 165, PT_PC, ucp_Cs },
+  { 168, PT_SC, ucp_Cuneiform },
+  { 178, PT_SC, ucp_Cypriot },
+  { 186, PT_SC, ucp_Cyrillic },
+  { 195, PT_SC, ucp_Deseret },
+  { 203, PT_SC, ucp_Devanagari },
+  { 214, PT_SC, ucp_Egyptian_Hieroglyphs },
+  { 235, PT_SC, ucp_Ethiopic },
+  { 244, PT_SC, ucp_Georgian },
+  { 253, PT_SC, ucp_Glagolitic },
+  { 264, PT_SC, ucp_Gothic },
+  { 271, PT_SC, ucp_Greek },
+  { 277, PT_SC, ucp_Gujarati },
+  { 286, PT_SC, ucp_Gurmukhi },
+  { 295, PT_SC, ucp_Han },
+  { 299, PT_SC, ucp_Hangul },
+  { 306, PT_SC, ucp_Hanunoo },
+  { 314, PT_SC, ucp_Hebrew },
+  { 321, PT_SC, ucp_Hiragana },
+  { 330, PT_SC, ucp_Imperial_Aramaic },
+  { 347, PT_SC, ucp_Inherited },
+  { 357, PT_SC, ucp_Inscriptional_Pahlavi },
+  { 379, PT_SC, ucp_Inscriptional_Parthian },
+  { 402, PT_SC, ucp_Javanese },
+  { 411, PT_SC, ucp_Kaithi },
+  { 418, PT_SC, ucp_Kannada },
+  { 426, PT_SC, ucp_Katakana },
+  { 435, PT_SC, ucp_Kayah_Li },
+  { 444, PT_SC, ucp_Kharoshthi },
+  { 455, PT_SC, ucp_Khmer },
+  { 461, PT_GC, ucp_L },
+  { 463, PT_LAMP, 0 },
+  { 466, PT_SC, ucp_Lao },
+  { 470, PT_SC, ucp_Latin },
+  { 476, PT_SC, ucp_Lepcha },
+  { 483, PT_SC, ucp_Limbu },
+  { 489, PT_SC, ucp_Linear_B },
+  { 498, PT_SC, ucp_Lisu },
+  { 503, PT_PC, ucp_Ll },
+  { 506, PT_PC, ucp_Lm },
+  { 509, PT_PC, ucp_Lo },
+  { 512, PT_PC, ucp_Lt },
+  { 515, PT_PC, ucp_Lu },
+  { 518, PT_SC, ucp_Lycian },
+  { 525, PT_SC, ucp_Lydian },
+  { 532, PT_GC, ucp_M },
+  { 534, PT_SC, ucp_Malayalam },
+  { 544, PT_SC, ucp_Mandaic },
+  { 552, PT_PC, ucp_Mc },
+  { 555, PT_PC, ucp_Me },
+  { 558, PT_SC, ucp_Meetei_Mayek },
+  { 571, PT_PC, ucp_Mn },
+  { 574, PT_SC, ucp_Mongolian },
+  { 584, PT_SC, ucp_Myanmar },
+  { 592, PT_GC, ucp_N },
+  { 594, PT_PC, ucp_Nd },
+  { 597, PT_SC, ucp_New_Tai_Lue },
+  { 609, PT_SC, ucp_Nko },
+  { 613, PT_PC, ucp_Nl },
+  { 616, PT_PC, ucp_No },
+  { 619, PT_SC, ucp_Ogham },
+  { 625, PT_SC, ucp_Ol_Chiki },
+  { 634, PT_SC, ucp_Old_Italic },
+  { 645, PT_SC, ucp_Old_Persian },
+  { 657, PT_SC, ucp_Old_South_Arabian },
+  { 675, PT_SC, ucp_Old_Turkic },
+  { 686, PT_SC, ucp_Oriya },
+  { 692, PT_SC, ucp_Osmanya },
+  { 700, PT_GC, ucp_P },
+  { 702, PT_PC, ucp_Pc },
+  { 705, PT_PC, ucp_Pd },
+  { 708, PT_PC, ucp_Pe },
+  { 711, PT_PC, ucp_Pf },
+  { 714, PT_SC, ucp_Phags_Pa },
+  { 723, PT_SC, ucp_Phoenician },
+  { 734, PT_PC, ucp_Pi },
+  { 737, PT_PC, ucp_Po },
+  { 740, PT_PC, ucp_Ps },
+  { 743, PT_SC, ucp_Rejang },
+  { 750, PT_SC, ucp_Runic },
+  { 756, PT_GC, ucp_S },
+  { 758, PT_SC, ucp_Samaritan },
+  { 768, PT_SC, ucp_Saurashtra },
+  { 779, PT_PC, ucp_Sc },
+  { 782, PT_SC, ucp_Shavian },
+  { 790, PT_SC, ucp_Sinhala },
+  { 798, PT_PC, ucp_Sk },
+  { 801, PT_PC, ucp_Sm },
+  { 804, PT_PC, ucp_So },
+  { 807, PT_SC, ucp_Sundanese },
+  { 817, PT_SC, ucp_Syloti_Nagri },
+  { 830, PT_SC, ucp_Syriac },
+  { 837, PT_SC, ucp_Tagalog },
+  { 845, PT_SC, ucp_Tagbanwa },
+  { 854, PT_SC, ucp_Tai_Le },
+  { 861, PT_SC, ucp_Tai_Tham },
+  { 870, PT_SC, ucp_Tai_Viet },
+  { 879, PT_SC, ucp_Tamil },
+  { 885, PT_SC, ucp_Telugu },
+  { 892, PT_SC, ucp_Thaana },
+  { 899, PT_SC, ucp_Thai },
+  { 904, PT_SC, ucp_Tibetan },
+  { 912, PT_SC, ucp_Tifinagh },
+  { 921, PT_SC, ucp_Ugaritic },
+  { 930, PT_SC, ucp_Vai },
+  { 934, PT_ALNUM, 0 },
+  { 938, PT_PXSPACE, 0 },
+  { 942, PT_SPACE, 0 },
+  { 946, PT_WORD, 0 },
+  { 950, PT_SC, ucp_Yi },
+  { 953, PT_GC, ucp_Z },
+  { 955, PT_PC, ucp_Zl },
+  { 958, PT_PC, ucp_Zp },
+  { 961, 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/src/3rdparty/pcre/pcre_ucd.c b/src/3rdparty/pcre/pcre_ucd.c
new file mode 100644 (file)
index 0000000..48fa486
--- /dev/null
@@ -0,0 +1,2981 @@
+#ifdef PCRE_HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+/* Unicode character database. */
+/* This file was autogenerated by the MultiStage2.py script. */
+/* Total size: 60384 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 }};
+const pcre_uint8 PRIV(ucd_stage1)[] = {0};
+const pcre_uint16 PRIV(ucd_stage2)[] = {0};
+#else
+
+/* When recompiling tables with a new Unicode version,
+please check types in the structure definition from pcre_internal.h:
+typedef struct {
+pcre_uint8 property_0;
+pcre_uint8 property_1;
+pcre_int32 property_2;
+} ucd_record; */
+
+
+const ucd_record PRIV(ucd_records)[] = { /* 4320 bytes, record size 8 */
+  {     9,      0,      0, }, /*   0 */
+  {     9,     29,      0, }, /*   1 */
+  {     9,     21,      0, }, /*   2 */
+  {     9,     23,      0, }, /*   3 */
+  {     9,     22,      0, }, /*   4 */
+  {     9,     18,      0, }, /*   5 */
+  {     9,     25,      0, }, /*   6 */
+  {     9,     17,      0, }, /*   7 */
+  {     9,     13,      0, }, /*   8 */
+  {    33,      9,     32, }, /*   9 */
+  {     9,     24,      0, }, /*  10 */
+  {     9,     16,      0, }, /*  11 */
+  {    33,      5,    -32, }, /*  12 */
+  {     9,     26,      0, }, /*  13 */
+  {    33,      5,      0, }, /*  14 */
+  {     9,     20,      0, }, /*  15 */
+  {     9,      1,      0, }, /*  16 */
+  {     9,     15,      0, }, /*  17 */
+  {     9,      5,    743, }, /*  18 */
+  {     9,     19,      0, }, /*  19 */
+  {    33,      5,    121, }, /*  20 */
+  {    33,      9,      1, }, /*  21 */
+  {    33,      5,     -1, }, /*  22 */
+  {    33,      9,   -199, }, /*  23 */
+  {    33,      5,   -232, }, /*  24 */
+  {    33,      9,   -121, }, /*  25 */
+  {    33,      5,   -300, }, /*  26 */
+  {    33,      5,    195, }, /*  27 */
+  {    33,      9,    210, }, /*  28 */
+  {    33,      9,    206, }, /*  29 */
+  {    33,      9,    205, }, /*  30 */
+  {    33,      9,     79, }, /*  31 */
+  {    33,      9,    202, }, /*  32 */
+  {    33,      9,    203, }, /*  33 */
+  {    33,      9,    207, }, /*  34 */
+  {    33,      5,     97, }, /*  35 */
+  {    33,      9,    211, }, /*  36 */
+  {    33,      9,    209, }, /*  37 */
+  {    33,      5,    163, }, /*  38 */
+  {    33,      9,    213, }, /*  39 */
+  {    33,      5,    130, }, /*  40 */
+  {    33,      9,    214, }, /*  41 */
+  {    33,      9,    218, }, /*  42 */
+  {    33,      9,    217, }, /*  43 */
+  {    33,      9,    219, }, /*  44 */
+  {    33,      7,      0, }, /*  45 */
+  {    33,      5,     56, }, /*  46 */
+  {    33,      9,      2, }, /*  47 */
+  {    33,      8,     -1, }, /*  48 */
+  {    33,      5,     -2, }, /*  49 */
+  {    33,      5,    -79, }, /*  50 */
+  {    33,      9,    -97, }, /*  51 */
+  {    33,      9,    -56, }, /*  52 */
+  {    33,      9,   -130, }, /*  53 */
+  {    33,      9,  10795, }, /*  54 */
+  {    33,      9,   -163, }, /*  55 */
+  {    33,      9,  10792, }, /*  56 */
+  {    33,      5,  10815, }, /*  57 */
+  {    33,      9,   -195, }, /*  58 */
+  {    33,      9,     69, }, /*  59 */
+  {    33,      9,     71, }, /*  60 */
+  {    33,      5,  10783, }, /*  61 */
+  {    33,      5,  10780, }, /*  62 */
+  {    33,      5,  10782, }, /*  63 */
+  {    33,      5,   -210, }, /*  64 */
+  {    33,      5,   -206, }, /*  65 */
+  {    33,      5,   -205, }, /*  66 */
+  {    33,      5,   -202, }, /*  67 */
+  {    33,      5,   -203, }, /*  68 */
+  {    33,      5,   -207, }, /*  69 */
+  {    33,      5,  42280, }, /*  70 */
+  {    33,      5,   -209, }, /*  71 */
+  {    33,      5,   -211, }, /*  72 */
+  {    33,      5,  10743, }, /*  73 */
+  {    33,      5,  10749, }, /*  74 */
+  {    33,      5,   -213, }, /*  75 */
+  {    33,      5,   -214, }, /*  76 */
+  {    33,      5,  10727, }, /*  77 */
+  {    33,      5,   -218, }, /*  78 */
+  {    33,      5,    -69, }, /*  79 */
+  {    33,      5,   -217, }, /*  80 */
+  {    33,      5,    -71, }, /*  81 */
+  {    33,      5,   -219, }, /*  82 */
+  {    33,      6,      0, }, /*  83 */
+  {     9,      6,      0, }, /*  84 */
+  {     3,     24,      0, }, /*  85 */
+  {    27,     12,      0, }, /*  86 */
+  {    27,     12,     84, }, /*  87 */
+  {    19,      9,      1, }, /*  88 */
+  {    19,      5,     -1, }, /*  89 */
+  {    19,     24,      0, }, /*  90 */
+  {     9,      2,      0, }, /*  91 */
+  {    19,      6,      0, }, /*  92 */
+  {    19,      5,    130, }, /*  93 */
+  {    19,      9,     38, }, /*  94 */
+  {    19,      9,     37, }, /*  95 */
+  {    19,      9,     64, }, /*  96 */
+  {    19,      9,     63, }, /*  97 */
+  {    19,      5,      0, }, /*  98 */
+  {    19,      9,     32, }, /*  99 */
+  {    19,      5,    -38, }, /* 100 */
+  {    19,      5,    -37, }, /* 101 */
+  {    19,      5,    -32, }, /* 102 */
+  {    19,      5,    -31, }, /* 103 */
+  {    19,      5,    -64, }, /* 104 */
+  {    19,      5,    -63, }, /* 105 */
+  {    19,      9,      8, }, /* 106 */
+  {    19,      5,    -62, }, /* 107 */
+  {    19,      5,    -57, }, /* 108 */
+  {    19,      9,      0, }, /* 109 */
+  {    19,      5,    -47, }, /* 110 */
+  {    19,      5,    -54, }, /* 111 */
+  {    19,      5,     -8, }, /* 112 */
+  {    10,      9,      1, }, /* 113 */
+  {    10,      5,     -1, }, /* 114 */
+  {    19,      5,    -86, }, /* 115 */
+  {    19,      5,    -80, }, /* 116 */
+  {    19,      5,      7, }, /* 117 */
+  {    19,      9,    -60, }, /* 118 */
+  {    19,      5,    -96, }, /* 119 */
+  {    19,     25,      0, }, /* 120 */
+  {    19,      9,     -7, }, /* 121 */
+  {    19,      9,   -130, }, /* 122 */
+  {    12,      9,     80, }, /* 123 */
+  {    12,      9,     32, }, /* 124 */
+  {    12,      5,    -32, }, /* 125 */
+  {    12,      5,    -80, }, /* 126 */
+  {    12,      9,      1, }, /* 127 */
+  {    12,      5,     -1, }, /* 128 */
+  {    12,     26,      0, }, /* 129 */
+  {    12,     12,      0, }, /* 130 */
+  {    12,     11,      0, }, /* 131 */
+  {    12,      9,     15, }, /* 132 */
+  {    12,      5,    -15, }, /* 133 */
+  {     1,      9,     48, }, /* 134 */
+  {     1,      6,      0, }, /* 135 */
+  {     1,     21,      0, }, /* 136 */
+  {     1,      5,    -48, }, /* 137 */
+  {     1,      5,      0, }, /* 138 */
+  {     1,     17,      0, }, /* 139 */
+  {    25,     12,      0, }, /* 140 */
+  {    25,     17,      0, }, /* 141 */
+  {    25,     21,      0, }, /* 142 */
+  {    25,      7,      0, }, /* 143 */
+  {     0,      1,      0, }, /* 144 */
+  {     0,     25,      0, }, /* 145 */
+  {     0,     21,      0, }, /* 146 */
+  {     0,     23,      0, }, /* 147 */
+  {     0,     26,      0, }, /* 148 */
+  {     0,     12,      0, }, /* 149 */
+  {     0,      7,      0, }, /* 150 */
+  {     0,      6,      0, }, /* 151 */
+  {     0,     13,      0, }, /* 152 */
+  {    49,     21,      0, }, /* 153 */
+  {    49,      1,      0, }, /* 154 */
+  {    49,      7,      0, }, /* 155 */
+  {    49,     12,      0, }, /* 156 */
+  {    55,      7,      0, }, /* 157 */
+  {    55,     12,      0, }, /* 158 */
+  {    63,     13,      0, }, /* 159 */
+  {    63,      7,      0, }, /* 160 */
+  {    63,     12,      0, }, /* 161 */
+  {    63,      6,      0, }, /* 162 */
+  {    63,     26,      0, }, /* 163 */
+  {    63,     21,      0, }, /* 164 */
+  {    89,      7,      0, }, /* 165 */
+  {    89,     12,      0, }, /* 166 */
+  {    89,      6,      0, }, /* 167 */
+  {    89,     21,      0, }, /* 168 */
+  {    94,      7,      0, }, /* 169 */
+  {    94,     12,      0, }, /* 170 */
+  {    94,     21,      0, }, /* 171 */
+  {    14,     12,      0, }, /* 172 */
+  {    14,     10,      0, }, /* 173 */
+  {    14,      7,      0, }, /* 174 */
+  {    14,     13,      0, }, /* 175 */
+  {    14,      6,      0, }, /* 176 */
+  {     2,     12,      0, }, /* 177 */
+  {     2,     10,      0, }, /* 178 */
+  {     2,      7,      0, }, /* 179 */
+  {     2,     13,      0, }, /* 180 */
+  {     2,     23,      0, }, /* 181 */
+  {     2,     15,      0, }, /* 182 */
+  {     2,     26,      0, }, /* 183 */
+  {    21,     12,      0, }, /* 184 */
+  {    21,     10,      0, }, /* 185 */
+  {    21,      7,      0, }, /* 186 */
+  {    21,     13,      0, }, /* 187 */
+  {    20,     12,      0, }, /* 188 */
+  {    20,     10,      0, }, /* 189 */
+  {    20,      7,      0, }, /* 190 */
+  {    20,     13,      0, }, /* 191 */
+  {    20,     23,      0, }, /* 192 */
+  {    43,     12,      0, }, /* 193 */
+  {    43,     10,      0, }, /* 194 */
+  {    43,      7,      0, }, /* 195 */
+  {    43,     13,      0, }, /* 196 */
+  {    43,     26,      0, }, /* 197 */
+  {    43,     15,      0, }, /* 198 */
+  {    53,     12,      0, }, /* 199 */
+  {    53,      7,      0, }, /* 200 */
+  {    53,     10,      0, }, /* 201 */
+  {    53,     13,      0, }, /* 202 */
+  {    53,     15,      0, }, /* 203 */
+  {    53,     26,      0, }, /* 204 */
+  {    53,     23,      0, }, /* 205 */
+  {    54,     10,      0, }, /* 206 */
+  {    54,      7,      0, }, /* 207 */
+  {    54,     12,      0, }, /* 208 */
+  {    54,     13,      0, }, /* 209 */
+  {    54,     15,      0, }, /* 210 */
+  {    54,     26,      0, }, /* 211 */
+  {    28,     10,      0, }, /* 212 */
+  {    28,      7,      0, }, /* 213 */
+  {    28,     12,      0, }, /* 214 */
+  {    28,     13,      0, }, /* 215 */
+  {    36,     10,      0, }, /* 216 */
+  {    36,      7,      0, }, /* 217 */
+  {    36,     12,      0, }, /* 218 */
+  {    36,     13,      0, }, /* 219 */
+  {    36,     15,      0, }, /* 220 */
+  {    36,     26,      0, }, /* 221 */
+  {    47,     10,      0, }, /* 222 */
+  {    47,      7,      0, }, /* 223 */
+  {    47,     12,      0, }, /* 224 */
+  {    47,     21,      0, }, /* 225 */
+  {    56,      7,      0, }, /* 226 */
+  {    56,     12,      0, }, /* 227 */
+  {    56,      6,      0, }, /* 228 */
+  {    56,     21,      0, }, /* 229 */
+  {    56,     13,      0, }, /* 230 */
+  {    32,      7,      0, }, /* 231 */
+  {    32,     12,      0, }, /* 232 */
+  {    32,      6,      0, }, /* 233 */
+  {    32,     13,      0, }, /* 234 */
+  {    57,      7,      0, }, /* 235 */
+  {    57,     26,      0, }, /* 236 */
+  {    57,     21,      0, }, /* 237 */
+  {    57,     12,      0, }, /* 238 */
+  {    57,     13,      0, }, /* 239 */
+  {    57,     15,      0, }, /* 240 */
+  {    57,     22,      0, }, /* 241 */
+  {    57,     18,      0, }, /* 242 */
+  {    57,     10,      0, }, /* 243 */
+  {    38,      7,      0, }, /* 244 */
+  {    38,     10,      0, }, /* 245 */
+  {    38,     12,      0, }, /* 246 */
+  {    38,     13,      0, }, /* 247 */
+  {    38,     21,      0, }, /* 248 */
+  {    38,     26,      0, }, /* 249 */
+  {    16,      9,   7264, }, /* 250 */
+  {    16,      7,      0, }, /* 251 */
+  {    16,      6,      0, }, /* 252 */
+  {    23,      7,      0, }, /* 253 */
+  {    15,      7,      0, }, /* 254 */
+  {    15,     12,      0, }, /* 255 */
+  {    15,     26,      0, }, /* 256 */
+  {    15,     21,      0, }, /* 257 */
+  {    15,     15,      0, }, /* 258 */
+  {     8,      7,      0, }, /* 259 */
+  {     7,     17,      0, }, /* 260 */
+  {     7,      7,      0, }, /* 261 */
+  {     7,     21,      0, }, /* 262 */
+  {    40,     29,      0, }, /* 263 */
+  {    40,      7,      0, }, /* 264 */
+  {    40,     22,      0, }, /* 265 */
+  {    40,     18,      0, }, /* 266 */
+  {    45,      7,      0, }, /* 267 */
+  {    45,     14,      0, }, /* 268 */
+  {    50,      7,      0, }, /* 269 */
+  {    50,     12,      0, }, /* 270 */
+  {    24,      7,      0, }, /* 271 */
+  {    24,     12,      0, }, /* 272 */
+  {     6,      7,      0, }, /* 273 */
+  {     6,     12,      0, }, /* 274 */
+  {    51,      7,      0, }, /* 275 */
+  {    51,     12,      0, }, /* 276 */
+  {    31,      7,      0, }, /* 277 */
+  {    31,      1,      0, }, /* 278 */
+  {    31,     10,      0, }, /* 279 */
+  {    31,     12,      0, }, /* 280 */
+  {    31,     21,      0, }, /* 281 */
+  {    31,      6,      0, }, /* 282 */
+  {    31,     23,      0, }, /* 283 */
+  {    31,     13,      0, }, /* 284 */
+  {    31,     15,      0, }, /* 285 */
+  {    37,     21,      0, }, /* 286 */
+  {    37,     17,      0, }, /* 287 */
+  {    37,     12,      0, }, /* 288 */
+  {    37,     29,      0, }, /* 289 */
+  {    37,     13,      0, }, /* 290 */
+  {    37,      7,      0, }, /* 291 */
+  {    37,      6,      0, }, /* 292 */
+  {    34,      7,      0, }, /* 293 */
+  {    34,     12,      0, }, /* 294 */
+  {    34,     10,      0, }, /* 295 */
+  {    34,     26,      0, }, /* 296 */
+  {    34,     21,      0, }, /* 297 */
+  {    34,     13,      0, }, /* 298 */
+  {    52,      7,      0, }, /* 299 */
+  {    39,      7,      0, }, /* 300 */
+  {    39,     10,      0, }, /* 301 */
+  {    39,     13,      0, }, /* 302 */
+  {    39,     15,      0, }, /* 303 */
+  {    39,     26,      0, }, /* 304 */
+  {    31,     26,      0, }, /* 305 */
+  {     5,      7,      0, }, /* 306 */
+  {     5,     12,      0, }, /* 307 */
+  {     5,     10,      0, }, /* 308 */
+  {     5,     21,      0, }, /* 309 */
+  {    90,      7,      0, }, /* 310 */
+  {    90,     10,      0, }, /* 311 */
+  {    90,     12,      0, }, /* 312 */
+  {    90,     13,      0, }, /* 313 */
+  {    90,     21,      0, }, /* 314 */
+  {    90,      6,      0, }, /* 315 */
+  {    61,     12,      0, }, /* 316 */
+  {    61,     10,      0, }, /* 317 */
+  {    61,      7,      0, }, /* 318 */
+  {    61,     13,      0, }, /* 319 */
+  {    61,     21,      0, }, /* 320 */
+  {    61,     26,      0, }, /* 321 */
+  {    75,     12,      0, }, /* 322 */
+  {    75,     10,      0, }, /* 323 */
+  {    75,      7,      0, }, /* 324 */
+  {    75,     13,      0, }, /* 325 */
+  {    92,      7,      0, }, /* 326 */
+  {    92,     12,      0, }, /* 327 */
+  {    92,     10,      0, }, /* 328 */
+  {    92,     21,      0, }, /* 329 */
+  {    69,      7,      0, }, /* 330 */
+  {    69,     10,      0, }, /* 331 */
+  {    69,     12,      0, }, /* 332 */
+  {    69,     21,      0, }, /* 333 */
+  {    69,     13,      0, }, /* 334 */
+  {    72,     13,      0, }, /* 335 */
+  {    72,      7,      0, }, /* 336 */
+  {    72,      6,      0, }, /* 337 */
+  {    72,     21,      0, }, /* 338 */
+  {     9,     10,      0, }, /* 339 */
+  {     9,      7,      0, }, /* 340 */
+  {    12,      5,      0, }, /* 341 */
+  {    12,      6,      0, }, /* 342 */
+  {    33,      5,  35332, }, /* 343 */
+  {    33,      5,   3814, }, /* 344 */
+  {    33,      5,    -59, }, /* 345 */
+  {    33,      9,  -7615, }, /* 346 */
+  {    19,      5,      8, }, /* 347 */
+  {    19,      9,     -8, }, /* 348 */
+  {    19,      5,     74, }, /* 349 */
+  {    19,      5,     86, }, /* 350 */
+  {    19,      5,    100, }, /* 351 */
+  {    19,      5,    128, }, /* 352 */
+  {    19,      5,    112, }, /* 353 */
+  {    19,      5,    126, }, /* 354 */
+  {    19,      8,     -8, }, /* 355 */
+  {    19,      5,      9, }, /* 356 */
+  {    19,      9,    -74, }, /* 357 */
+  {    19,      8,     -9, }, /* 358 */
+  {    19,      5,  -7205, }, /* 359 */
+  {    19,      9,    -86, }, /* 360 */
+  {    19,      9,   -100, }, /* 361 */
+  {    19,      9,   -112, }, /* 362 */
+  {    19,      9,   -128, }, /* 363 */
+  {    19,      9,   -126, }, /* 364 */
+  {    27,      1,      0, }, /* 365 */
+  {     9,     27,      0, }, /* 366 */
+  {     9,     28,      0, }, /* 367 */
+  {    27,     11,      0, }, /* 368 */
+  {     9,      9,      0, }, /* 369 */
+  {     9,      5,      0, }, /* 370 */
+  {    19,      9,  -7517, }, /* 371 */
+  {    33,      9,  -8383, }, /* 372 */
+  {    33,      9,  -8262, }, /* 373 */
+  {    33,      9,     28, }, /* 374 */
+  {    33,      5,    -28, }, /* 375 */
+  {    33,     14,     16, }, /* 376 */
+  {    33,     14,    -16, }, /* 377 */
+  {    33,     14,      0, }, /* 378 */
+  {     9,     26,     26, }, /* 379 */
+  {     9,     26,    -26, }, /* 380 */
+  {     4,     26,      0, }, /* 381 */
+  {    17,      9,     48, }, /* 382 */
+  {    17,      5,    -48, }, /* 383 */
+  {    33,      9, -10743, }, /* 384 */
+  {    33,      9,  -3814, }, /* 385 */
+  {    33,      9, -10727, }, /* 386 */
+  {    33,      5, -10795, }, /* 387 */
+  {    33,      5, -10792, }, /* 388 */
+  {    33,      9, -10780, }, /* 389 */
+  {    33,      9, -10749, }, /* 390 */
+  {    33,      9, -10783, }, /* 391 */
+  {    33,      9, -10782, }, /* 392 */
+  {    33,      9, -10815, }, /* 393 */
+  {    10,      5,      0, }, /* 394 */
+  {    10,     26,      0, }, /* 395 */
+  {    10,     12,      0, }, /* 396 */
+  {    10,     21,      0, }, /* 397 */
+  {    10,     15,      0, }, /* 398 */
+  {    16,      5,  -7264, }, /* 399 */
+  {    58,      7,      0, }, /* 400 */
+  {    58,      6,      0, }, /* 401 */
+  {    58,     21,      0, }, /* 402 */
+  {    58,     12,      0, }, /* 403 */
+  {    22,     26,      0, }, /* 404 */
+  {    22,      6,      0, }, /* 405 */
+  {    22,     14,      0, }, /* 406 */
+  {    23,     12,      0, }, /* 407 */
+  {    26,      7,      0, }, /* 408 */
+  {    26,      6,      0, }, /* 409 */
+  {    29,      7,      0, }, /* 410 */
+  {    29,      6,      0, }, /* 411 */
+  {     3,      7,      0, }, /* 412 */
+  {    23,     26,      0, }, /* 413 */
+  {    29,     26,      0, }, /* 414 */
+  {    22,      7,      0, }, /* 415 */
+  {    60,      7,      0, }, /* 416 */
+  {    60,      6,      0, }, /* 417 */
+  {    60,     26,      0, }, /* 418 */
+  {    85,      7,      0, }, /* 419 */
+  {    85,      6,      0, }, /* 420 */
+  {    85,     21,      0, }, /* 421 */
+  {    76,      7,      0, }, /* 422 */
+  {    76,      6,      0, }, /* 423 */
+  {    76,     21,      0, }, /* 424 */
+  {    76,     13,      0, }, /* 425 */
+  {    12,      7,      0, }, /* 426 */
+  {    12,     21,      0, }, /* 427 */
+  {    78,      7,      0, }, /* 428 */
+  {    78,     14,      0, }, /* 429 */
+  {    78,     12,      0, }, /* 430 */
+  {    78,     21,      0, }, /* 431 */
+  {    33,      9, -35332, }, /* 432 */
+  {    33,      9, -42280, }, /* 433 */
+  {    48,      7,      0, }, /* 434 */
+  {    48,     12,      0, }, /* 435 */
+  {    48,     10,      0, }, /* 436 */
+  {    48,     26,      0, }, /* 437 */
+  {    64,      7,      0, }, /* 438 */
+  {    64,     21,      0, }, /* 439 */
+  {    74,     10,      0, }, /* 440 */
+  {    74,      7,      0, }, /* 441 */
+  {    74,     12,      0, }, /* 442 */
+  {    74,     21,      0, }, /* 443 */
+  {    74,     13,      0, }, /* 444 */
+  {    14,     21,      0, }, /* 445 */
+  {    68,     13,      0, }, /* 446 */
+  {    68,      7,      0, }, /* 447 */
+  {    68,     12,      0, }, /* 448 */
+  {    68,     21,      0, }, /* 449 */
+  {    73,      7,      0, }, /* 450 */
+  {    73,     12,      0, }, /* 451 */
+  {    73,     10,      0, }, /* 452 */
+  {    73,     21,      0, }, /* 453 */
+  {    83,     12,      0, }, /* 454 */
+  {    83,     10,      0, }, /* 455 */
+  {    83,      7,      0, }, /* 456 */
+  {    83,     21,      0, }, /* 457 */
+  {    83,      6,      0, }, /* 458 */
+  {    83,     13,      0, }, /* 459 */
+  {    67,      7,      0, }, /* 460 */
+  {    67,     12,      0, }, /* 461 */
+  {    67,     10,      0, }, /* 462 */
+  {    67,     13,      0, }, /* 463 */
+  {    67,     21,      0, }, /* 464 */
+  {    38,      6,      0, }, /* 465 */
+  {    91,      7,      0, }, /* 466 */
+  {    91,     12,      0, }, /* 467 */
+  {    91,      6,      0, }, /* 468 */
+  {    91,     21,      0, }, /* 469 */
+  {    86,      7,      0, }, /* 470 */
+  {    86,     10,      0, }, /* 471 */
+  {    86,     12,      0, }, /* 472 */
+  {    86,     21,      0, }, /* 473 */
+  {    86,     13,      0, }, /* 474 */
+  {     9,      4,      0, }, /* 475 */
+  {     9,      3,      0, }, /* 476 */
+  {    25,     25,      0, }, /* 477 */
+  {     0,     24,      0, }, /* 478 */
+  {    35,      7,      0, }, /* 479 */
+  {    19,     14,      0, }, /* 480 */
+  {    19,     15,      0, }, /* 481 */
+  {    19,     26,      0, }, /* 482 */
+  {    70,      7,      0, }, /* 483 */
+  {    66,      7,      0, }, /* 484 */
+  {    41,      7,      0, }, /* 485 */
+  {    41,     15,      0, }, /* 486 */
+  {    18,      7,      0, }, /* 487 */
+  {    18,     14,      0, }, /* 488 */
+  {    59,      7,      0, }, /* 489 */
+  {    59,     21,      0, }, /* 490 */
+  {    42,      7,      0, }, /* 491 */
+  {    42,     21,      0, }, /* 492 */
+  {    42,     14,      0, }, /* 493 */
+  {    13,      9,     40, }, /* 494 */
+  {    13,      5,    -40, }, /* 495 */
+  {    46,      7,      0, }, /* 496 */
+  {    44,      7,      0, }, /* 497 */
+  {    44,     13,      0, }, /* 498 */
+  {    11,      7,      0, }, /* 499 */
+  {    80,      7,      0, }, /* 500 */
+  {    80,     21,      0, }, /* 501 */
+  {    80,     15,      0, }, /* 502 */
+  {    65,      7,      0, }, /* 503 */
+  {    65,     15,      0, }, /* 504 */
+  {    65,     21,      0, }, /* 505 */
+  {    71,      7,      0, }, /* 506 */
+  {    71,     21,      0, }, /* 507 */
+  {    30,      7,      0, }, /* 508 */
+  {    30,     12,      0, }, /* 509 */
+  {    30,     15,      0, }, /* 510 */
+  {    30,     21,      0, }, /* 511 */
+  {    87,      7,      0, }, /* 512 */
+  {    87,     15,      0, }, /* 513 */
+  {    87,     21,      0, }, /* 514 */
+  {    77,      7,      0, }, /* 515 */
+  {    77,     21,      0, }, /* 516 */
+  {    82,      7,      0, }, /* 517 */
+  {    82,     15,      0, }, /* 518 */
+  {    81,      7,      0, }, /* 519 */
+  {    81,     15,      0, }, /* 520 */
+  {    88,      7,      0, }, /* 521 */
+  {     0,     15,      0, }, /* 522 */
+  {    93,     10,      0, }, /* 523 */
+  {    93,     12,      0, }, /* 524 */
+  {    93,      7,      0, }, /* 525 */
+  {    93,     21,      0, }, /* 526 */
+  {    93,     15,      0, }, /* 527 */
+  {    93,     13,      0, }, /* 528 */
+  {    84,     12,      0, }, /* 529 */
+  {    84,     10,      0, }, /* 530 */
+  {    84,      7,      0, }, /* 531 */
+  {    84,     21,      0, }, /* 532 */
+  {    84,      1,      0, }, /* 533 */
+  {    62,      7,      0, }, /* 534 */
+  {    62,     14,      0, }, /* 535 */
+  {    62,     21,      0, }, /* 536 */
+  {    79,      7,      0, }, /* 537 */
+  {    19,     12,      0, }, /* 538 */
+  {    26,     26,      0, }, /* 539 */
+};
+
+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, 34, 35, 36, 37, 38, 39, 40, 40, 40, 41, 42, 43, 44, /* U+1000 */
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, /* U+1800 */
+ 61, 62, 63, 64, 65, 65, 66, 67, 68, 69, 70, 71, 72, 70, 73, 74, /* U+2000 */
+ 75, 75, 65, 76, 65, 65, 77, 17, 78, 79, 80, 81, 82, 83, 84, 85, /* U+2800 */
+ 86, 87, 88, 89, 90, 91, 92, 70, 93, 93, 93, 93, 93, 93, 93, 93, /* U+3000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+3800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+4000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 94, 93, 93, 93, 93, /* U+4800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+5000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+5800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+6000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+6800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+7000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+7800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+8000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+8800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+9000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 95, /* U+9800 */
+ 96, 97, 97, 97, 97, 97, 97, 97, 97, 98, 99, 99,100,101,102,103, /* U+A000 */
+104,105,106,107,108,109,110,111, 34, 34, 34, 34, 34, 34, 34, 34, /* U+A800 */
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, /* U+B000 */
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, /* U+B800 */
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, /* U+C000 */
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, /* U+C800 */
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,112, /* U+D000 */
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, /* U+D800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+E000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+E800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F000 */
+114,114, 93, 93,115,116,117,118,119,119,120,121,122,123,124,125, /* U+F800 */
+126,127,128,129, 17,130,131,132,133,134, 17, 17, 17, 17, 17, 17, /* U+10000 */
+135, 17,136, 17,137, 17,138, 17,139, 17, 17, 17,140, 17, 17, 17, /* U+10800 */
+141,142, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+11000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+11800 */
+143,143,143,143,143,143,144, 17,145, 17, 17, 17, 17, 17, 17, 17, /* U+12000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+12800 */
+146,146,146,146,146,146,146,146,147, 17, 17, 17, 17, 17, 17, 17, /* U+13000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+13800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+14000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+14800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+15000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+15800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+16000 */
+148,148,148,148,149, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+16800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+17000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+17800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+18000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+18800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+19000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+19800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1A000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1A800 */
+150, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1B000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1B800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1C000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1C800 */
+ 70,151,152,153,154, 17,155, 17,156,157,158,159,160,161,162,163, /* U+1D000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1D800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1E000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1E800 */
+164,165,166,167,168, 17,169,170,171,172,173,174,175,176,177, 17, /* U+1F000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1F800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+20000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+20800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+21000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+21800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+22000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+22800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+23000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+23800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+24000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+24800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+25000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+25800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+26000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+26800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+27000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+27800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+28000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+28800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+29000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+29800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,178, 93, 93, /* U+2A000 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+2A800 */
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,179, 93, /* U+2B000 */
+180, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2B800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2C000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2C800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2D000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2D800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2E000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2E800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2F000 */
+ 93, 93, 93, 93,180, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2F800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+30000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+30800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+31000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+31800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+32000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+32800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+33000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+33800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+34000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+34800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+35000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+35800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+36000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+36800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+37000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+37800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+38000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+38800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+39000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+39800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3A000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3A800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3B000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3B800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3C000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3C800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3D000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3D800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3E000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3E800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3F000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3F800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+40000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+40800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+41000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+41800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+42000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+42800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+43000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+43800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+44000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+44800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+45000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+45800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+46000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+46800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+47000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+47800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+48000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+48800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+49000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+49800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4A000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4A800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4B000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4B800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4C000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4C800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4D000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4D800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4E000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4E800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4F000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4F800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+50000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+50800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+51000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+51800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+52000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+52800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+53000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+53800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+54000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+54800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+55000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+55800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+56000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+56800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+57000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+57800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+58000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+58800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+59000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+59800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5A000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5A800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5B000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5B800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5C000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5C800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5D000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5D800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5E000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5E800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5F000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5F800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+60000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+60800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+61000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+61800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+62000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+62800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+63000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+63800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+64000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+64800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+65000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+65800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+66000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+66800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+67000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+67800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+68000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+68800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+69000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+69800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6A000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6A800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6B000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6B800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6C000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6C800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6D000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6D800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6E000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6E800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6F000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6F800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+70000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+70800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+71000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+71800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+72000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+72800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+73000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+73800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+74000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+74800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+75000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+75800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+76000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+76800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+77000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+77800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+78000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+78800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+79000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+79800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7A000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7A800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7B000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7B800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7C000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7C800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7D000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7D800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7E000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7E800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7F000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7F800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+80000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+80800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+81000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+81800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+82000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+82800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+83000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+83800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+84000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+84800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+85000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+85800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+86000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+86800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+87000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+87800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+88000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+88800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+89000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+89800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8A000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8A800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8B000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8B800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8C000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8C800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8D000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8D800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8E000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8E800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8F000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8F800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+90000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+90800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+91000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+91800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+92000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+92800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+93000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+93800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+94000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+94800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+95000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+95800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+96000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+96800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+97000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+97800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+98000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+98800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+99000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+99800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9A000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9A800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9B000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9B800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9C000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9C800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9D000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9D800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9E000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9E800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9F000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9F800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A0000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A0800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A1000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A1800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A2000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A2800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A3000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A3800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A4000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A4800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A5000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A5800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A6000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A6800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A7000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A7800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A8000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A8800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A9000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A9800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AA000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AA800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AB000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AB800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AC000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AC800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AD000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AD800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AE000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AE800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AF000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AF800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B0000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B0800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B1000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B1800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B2000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B2800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B3000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B3800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B4000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B4800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B5000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B5800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B6000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B6800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B7000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B7800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B8000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B8800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B9000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B9800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BA000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BA800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BB000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BB800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BC000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BC800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BD000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BD800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BE000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BE800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BF000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BF800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C0000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C0800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C1000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C1800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C2000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C2800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C3000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C3800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C4000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C4800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C5000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C5800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C6000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C6800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C7000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C7800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C8000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C8800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C9000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C9800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CA000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CA800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CB000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CB800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CC000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CC800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CD000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CD800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CE000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CE800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CF000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CF800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D0000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D0800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D1000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D1800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D2000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D2800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D3000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D3800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D4000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D4800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D5000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D5800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D6000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D6800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D7000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D7800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D8000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D8800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D9000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D9800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DA000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DA800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DB000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DB800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DC000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DC800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DD000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DD800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DE000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DE800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DF000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DF800 */
+181, 17,182,183, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E0000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E0800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E1000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E1800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E2000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E2800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E3000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E3800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E4000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E4800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E5000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E5800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E6000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E6800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E7000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E7800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E8000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E8800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E9000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E9800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EA000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EA800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EB000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EB800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EC000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EC800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+ED000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+ED800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EE000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EE800 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EF000 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EF800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F0000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F0800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F1000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F1800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F2000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F2800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F3000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F3800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F4000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F4800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F5000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F5800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F6000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F6800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F7000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F7800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F8000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F8800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F9000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F9800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FA000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FA800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FB000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FB800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FC000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FC800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FD000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FD800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FE000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FE800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FF000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,184, /* U+FF800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+100000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+100800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+101000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+101800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+102000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+102800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+103000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+103800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+104000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+104800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+105000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+105800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+106000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+106800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+107000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+107800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+108000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+108800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+109000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+109800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10A000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10A800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10B000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10B800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10C000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10C800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10D000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10D800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10E000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10E800 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10F000 */
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,184, /* U+10F800 */
+};
+
+const pcre_uint16 PRIV(ucd_stage2)[] = { /* 47360 bytes, block = 128 */
+/* block 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,  0,
+  1,  2,  2,  2,  3,  2,  2,  2,  4,  5,  2,  6,  2,  7,  2,  2,
+  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  2,  2,  6,  6,  6,  2,
+  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  4,  2,  5, 10, 11,
+ 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  4,  6,  5,  6,  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,
+  1,  2,  3,  3,  3,  3, 13, 13, 10, 13, 14, 15,  6, 16, 13, 10,
+ 13,  6, 17, 17, 10, 18, 13,  2, 10, 17, 14, 19, 17, 17, 17,  2,
+  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+  9,  9,  9,  9,  9,  9,  9,  6,  9,  9,  9,  9,  9,  9,  9, 14,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12,  6, 12, 12, 12, 12, 12, 12, 12, 20,
+
+/* block 2 */
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 23, 24, 21, 22, 21, 22, 21, 22, 14, 21, 22, 21, 22, 21, 22, 21,
+ 22, 21, 22, 21, 22, 21, 22, 21, 22, 14, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 25, 21, 22, 21, 22, 21, 22, 26,
+
+/* block 3 */
+ 27, 28, 21, 22, 21, 22, 29, 21, 22, 30, 30, 21, 22, 14, 31, 32,
+ 33, 21, 22, 30, 34, 35, 36, 37, 21, 22, 38, 14, 36, 39, 40, 41,
+ 21, 22, 21, 22, 21, 22, 42, 21, 22, 42, 14, 14, 21, 22, 42, 21,
+ 22, 43, 43, 21, 22, 21, 22, 44, 21, 22, 14, 45, 21, 22, 14, 46,
+ 45, 45, 45, 45, 47, 48, 49, 47, 48, 49, 47, 48, 49, 21, 22, 21,
+ 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 50, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 14, 47, 48, 49, 21, 22, 51, 52, 21, 22, 21, 22, 21, 22, 21, 22,
+
+/* block 4 */
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 53, 14, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 14, 14, 14, 14, 14, 14, 54, 21, 22, 55, 56, 57,
+ 57, 21, 22, 58, 59, 60, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 61, 62, 63, 64, 65, 14, 66, 66, 14, 67, 14, 68, 14, 14, 14, 14,
+ 66, 14, 14, 69, 14, 70, 14, 14, 71, 72, 14, 73, 14, 14, 14, 72,
+ 14, 74, 75, 14, 14, 76, 14, 14, 14, 14, 14, 14, 14, 77, 14, 14,
+
+/* block 5 */
+ 78, 14, 14, 78, 14, 14, 14, 14, 78, 79, 80, 80, 81, 14, 14, 14,
+ 14, 14, 82, 14, 45, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 83, 83, 83, 83, 83, 83, 83, 83, 83, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 10, 10, 10, 10, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 83, 83, 83, 83, 83, 10, 10, 10, 10, 10, 85, 85, 84, 10, 84, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+
+/* block 6 */
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 87, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 88, 89, 88, 89, 84, 90, 88, 89, 91, 91, 92, 93, 93, 93,  2, 91,
+
+/* block 7 */
+ 91, 91, 91, 91, 90, 10, 94,  2, 95, 95, 95, 91, 96, 91, 97, 97,
+ 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 91, 99, 99, 99, 99, 99, 99, 99, 99, 99,100,101,101,101,
+ 98,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,
+102,102,103,102,102,102,102,102,102,102,102,102,104,105,105,106,
+107,108,109,109,109,110,111,112, 88, 89, 88, 89, 88, 89, 88, 89,
+ 88, 89,113,114,113,114,113,114,113,114,113,114,113,114,113,114,
+115,116,117, 98,118,119,120, 88, 89,121, 88, 89, 98,122,122,122,
+
+/* block 8 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,
+124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
+124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,
+127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128,
+127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128,
+
+/* block 9 */
+127,128,129,130,130, 86, 86,130,131,131,127,128,127,128,127,128,
+127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128,
+127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128,
+127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128,
+132,127,128,127,128,127,128,127,128,127,128,127,128,127,128,133,
+127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128,
+127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128,
+127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128,
+
+/* block 10 */
+127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128,
+127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128,
+127,128,127,128,127,128,127,128, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,
+134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,
+134,134,134,134,134,134,134, 91, 91,135,136,136,136,136,136,136,
+ 91,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
+
+/* block 11 */
+137,137,137,137,137,137,137,138, 91,  2,139, 91, 91, 91, 91, 91,
+ 91,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
+140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
+140,140,140,140,140,140,140,140,140,140,140,140,140,140,141,140,
+142,140,140,142,140,140,142,140, 91, 91, 91, 91, 91, 91, 91, 91,
+143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
+143,143,143,143,143,143,143,143,143,143,143, 91, 91, 91, 91, 91,
+143,143,143,142,142, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 12 */
+144,144,144,144, 91, 91,145,145,145,146,146,147,  2,146,148,148,
+149,149,149,149,149,149,149,149,149,149,149,  2, 91, 91,146,  2,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+ 84,150,150,150,150,150,150,150,150,150,150, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86,149,149,149,149,149,149,149,149,149, 86,
+  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,146,146,146,146,150,150,
+ 86,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+
+/* block 13 */
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,146,150,149,149,149,149,149,149,149, 16,148,149,
+149,149,149,149,149,151,151,149,149,148,149,149,149,149,150,150,
+152,152,152,152,152,152,152,152,152,152,150,150,150,148,148,150,
+
+/* block 14 */
+153,153,153,153,153,153,153,153,153,153,153,153,153,153, 91,154,
+155,156,155,155,155,155,155,155,155,155,155,155,155,155,155,155,
+155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,
+156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
+156,156,156,156,156,156,156,156,156,156,156, 91, 91,155,155,155,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+
+/* block 15 */
+157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
+157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
+157,157,157,157,157,157,158,158,158,158,158,158,158,158,158,158,
+158,157, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+159,159,159,159,159,159,159,159,159,159,160,160,160,160,160,160,
+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
+160,160,160,160,160,160,160,160,160,160,160,161,161,161,161,161,
+161,161,161,161,162,162,163,164,164,164,162, 91, 91, 91, 91, 91,
+
+/* block 16 */
+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,167,166,166,166,166,166,
+166,166,166,166,167,166,166,166,167,166,166,166,166,166, 91, 91,
+168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, 91,
+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
+169,169,169,169,169,169,169,169,169,170,170,170, 91, 91,171, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 17 */
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 18 */
+172,172,172,173,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,174,174,174,174,174,174,
+174,174,174,174,174,174,174,174,174,174,172,173,172,174,173,173,
+173,172,172,172,172,172,172,172,172,173,173,173,173,172,173,173,
+174, 86, 86,172,172,172,172,172,174,174,174,174,174,174,174,174,
+174,174,172,172,  2,  2,175,175,175,175,175,175,175,175,175,175,
+  2,176,174,174,174,174,174,174, 91,174,174,174,174,174,174,174,
+
+/* block 19 */
+ 91,177,178,178, 91,179,179,179,179,179,179,179,179, 91, 91,179,
+179, 91, 91,179,179,179,179,179,179,179,179,179,179,179,179,179,
+179,179,179,179,179,179,179,179,179, 91,179,179,179,179,179,179,
+179, 91,179, 91, 91, 91,179,179,179,179, 91, 91,177,179,178,178,
+178,177,177,177,177, 91, 91,178,178, 91, 91,178,178,177,179, 91,
+ 91, 91, 91, 91, 91, 91, 91,178, 91, 91, 91, 91,179,179, 91,179,
+179,179,177,177, 91, 91,180,180,180,180,180,180,180,180,180,180,
+179,179,181,181,182,182,182,182,182,182,183,181, 91, 91, 91, 91,
+
+/* block 20 */
+ 91,184,184,185, 91,186,186,186,186,186,186, 91, 91, 91, 91,186,
+186, 91, 91,186,186,186,186,186,186,186,186,186,186,186,186,186,
+186,186,186,186,186,186,186,186,186, 91,186,186,186,186,186,186,
+186, 91,186,186, 91,186,186, 91,186,186, 91, 91,184, 91,185,185,
+185,184,184, 91, 91, 91, 91,184,184, 91, 91,184,184,184, 91, 91,
+ 91,184, 91, 91, 91, 91, 91, 91, 91,186,186,186,186, 91,186, 91,
+ 91, 91, 91, 91, 91, 91,187,187,187,187,187,187,187,187,187,187,
+184,184,186,186,186,184, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 21 */
+ 91,188,188,189, 91,190,190,190,190,190,190,190,190,190, 91,190,
+190,190, 91,190,190,190,190,190,190,190,190,190,190,190,190,190,
+190,190,190,190,190,190,190,190,190, 91,190,190,190,190,190,190,
+190, 91,190,190, 91,190,190,190,190,190, 91, 91,188,190,189,189,
+189,188,188,188,188,188, 91,188,188,189, 91,189,189,188, 91, 91,
+190, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+190,190,188,188, 91, 91,191,191,191,191,191,191,191,191,191,191,
+ 91,192, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 22 */
+ 91,193,194,194, 91,195,195,195,195,195,195,195,195, 91, 91,195,
+195, 91, 91,195,195,195,195,195,195,195,195,195,195,195,195,195,
+195,195,195,195,195,195,195,195,195, 91,195,195,195,195,195,195,
+195, 91,195,195, 91,195,195,195,195,195, 91, 91,193,195,194,193,
+194,193,193,193,193, 91, 91,194,194, 91, 91,194,194,193, 91, 91,
+ 91, 91, 91, 91, 91, 91,193,194, 91, 91, 91, 91,195,195, 91,195,
+195,195,193,193, 91, 91,196,196,196,196,196,196,196,196,196,196,
+197,195,198,198,198,198,198,198, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 23 */
+ 91, 91,199,200, 91,200,200,200,200,200,200, 91, 91, 91,200,200,
+200, 91,200,200,200,200, 91, 91, 91,200,200, 91,200, 91,200,200,
+ 91, 91, 91,200,200, 91, 91, 91,200,200,200, 91, 91, 91,200,200,
+200,200,200,200,200,200,200,200,200,200, 91, 91, 91, 91,201,201,
+199,201,201, 91, 91, 91,201,201,201, 91,201,201,201,199, 91, 91,
+200, 91, 91, 91, 91, 91, 91,201, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91,202,202,202,202,202,202,202,202,202,202,
+203,203,203,204,204,204,204,204,204,205,204, 91, 91, 91, 91, 91,
+
+/* block 24 */
+ 91,206,206,206, 91,207,207,207,207,207,207,207,207, 91,207,207,
+207, 91,207,207,207,207,207,207,207,207,207,207,207,207,207,207,
+207,207,207,207,207,207,207,207,207, 91,207,207,207,207,207,207,
+207,207,207,207, 91,207,207,207,207,207, 91, 91, 91,207,208,208,
+208,206,206,206,206, 91,208,208,208, 91,208,208,208,208, 91, 91,
+ 91, 91, 91, 91, 91,208,208, 91,207,207, 91, 91, 91, 91, 91, 91,
+207,207,208,208, 91, 91,209,209,209,209,209,209,209,209,209,209,
+ 91, 91, 91, 91, 91, 91, 91, 91,210,210,210,210,210,210,210,211,
+
+/* block 25 */
+ 91, 91,212,212, 91,213,213,213,213,213,213,213,213, 91,213,213,
+213, 91,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
+213,213,213,213,213,213,213,213,213, 91,213,213,213,213,213,213,
+213,213,213,213, 91,213,213,213,213,213, 91, 91,214,213,212,214,
+212,212,212,212,212, 91,214,212,212, 91,212,212,214,214, 91, 91,
+ 91, 91, 91, 91, 91,212,212, 91, 91, 91, 91, 91, 91, 91,213, 91,
+213,213,214,214, 91, 91,215,215,215,215,215,215,215,215,215,215,
+ 91,213,213, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 26 */
+ 91, 91,216,216, 91,217,217,217,217,217,217,217,217, 91,217,217,
+217, 91,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217, 91, 91,217,216,216,
+216,218,218,218,218, 91,216,216,216, 91,216,216,216,218,217, 91,
+ 91, 91, 91, 91, 91, 91, 91,216, 91, 91, 91, 91, 91, 91, 91, 91,
+217,217,218,218, 91, 91,219,219,219,219,219,219,219,219,219,219,
+220,220,220,220,220,220, 91, 91, 91,221,217,217,217,217,217,217,
+
+/* block 27 */
+ 91, 91,222,222, 91,223,223,223,223,223,223,223,223,223,223,223,
+223,223,223,223,223,223,223, 91, 91, 91,223,223,223,223,223,223,
+223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
+223,223, 91,223,223,223,223,223,223,223,223,223, 91,223, 91, 91,
+223,223,223,223,223,223,223, 91, 91, 91,224, 91, 91, 91, 91,222,
+222,222,224,224,224, 91,224, 91,222,222,222,222,222,222,222,222,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91,222,222,225, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 28 */
+ 91,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,
+226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,
+226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,
+226,227,226,226,227,227,227,227,227,227,227, 91, 91, 91, 91,  3,
+226,226,226,226,226,226,228,227,227,227,227,227,227,227,227,229,
+230,230,230,230,230,230,230,230,230,230,229,229, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 29 */
+ 91,231,231, 91,231, 91, 91,231,231, 91,231, 91, 91,231, 91, 91,
+ 91, 91, 91, 91,231,231,231,231, 91,231,231,231,231,231,231,231,
+ 91,231,231,231, 91,231, 91,231, 91, 91,231,231, 91,231,231,231,
+231,232,231,231,232,232,232,232,232,232, 91,232,232,231, 91, 91,
+231,231,231,231,231, 91,233, 91,232,232,232,232,232,232, 91, 91,
+234,234,234,234,234,234,234,234,234,234, 91, 91,231,231, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 30 */
+235,236,236,236,237,237,237,237,237,237,237,237,237,237,237,237,
+237,237,237,236,236,236,236,236,238,238,236,236,236,236,236,236,
+239,239,239,239,239,239,239,239,239,239,240,240,240,240,240,240,
+240,240,240,240,236,238,236,238,236,238,241,242,241,242,243,243,
+235,235,235,235,235,235,235,235, 91,235,235,235,235,235,235,235,
+235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+235,235,235,235,235,235,235,235,235,235,235,235,235, 91, 91, 91,
+ 91,238,238,238,238,238,238,238,238,238,238,238,238,238,238,243,
+
+/* block 31 */
+238,238,238,238,238,237,238,238,235,235,235,235,235,238,238,238,
+238,238,238,238,238,238,238,238, 91,238,238,238,238,238,238,238,
+238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,
+238,238,238,238,238,238,238,238,238,238,238,238,238, 91,236,236,
+236,236,236,236,236,236,238,236,236,236,236,236,236, 91,236,236,
+237,237,237,237,237, 13, 13, 13, 13,237,237, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 32 */
+244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
+244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
+244,244,244,244,244,244,244,244,244,244,244,245,245,246,246,246,
+246,245,246,246,246,246,246,246,245,246,246,245,245,246,246,244,
+247,247,247,247,247,247,247,247,247,247,248,248,248,248,248,248,
+244,244,244,244,244,244,245,245,246,246,244,244,244,244,246,246,
+246,244,245,245,245,244,244,245,245,245,245,245,245,245,244,244,
+244,246,246,246,246,244,244,244,244,244,244,244,244,244,244,244,
+
+/* block 33 */
+244,244,246,245,245,246,246,245,245,245,245,245,245,246,244,245,
+247,247,247,247,247,247,247,247,247,247,245,245,245,246,249,249,
+250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
+250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
+250,250,250,250,250,250, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,
+251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,
+251,251,251,251,251,251,251,251,251,251,251,  2,252, 91, 91, 91,
+
+/* block 34 */
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+
+/* block 35 */
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254, 91,254,254,254,254, 91, 91,
+254,254,254,254,254,254,254, 91,254, 91,254,254,254,254, 91, 91,
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+
+/* block 36 */
+254,254,254,254,254,254,254,254,254, 91,254,254,254,254, 91, 91,
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+254, 91,254,254,254,254, 91, 91,254,254,254,254,254,254,254, 91,
+254, 91,254,254,254,254, 91, 91,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254, 91,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+
+/* block 37 */
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+254, 91,254,254,254,254, 91, 91,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254,254,254, 91, 91,255,255,255,
+256,257,257,257,257,257,257,257,257,258,258,258,258,258,258,258,
+258,258,258,258,258,258,258,258,258,258,258,258,258, 91, 91, 91,
+
+/* block 38 */
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+256,256,256,256,256,256,256,256,256,256, 91, 91, 91, 91, 91, 91,
+259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,
+259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,
+259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,
+259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,
+259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,
+259,259,259,259,259, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 39 */
+260,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+
+/* block 40 */
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+
+/* block 41 */
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,262,262,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+
+/* block 42 */
+263,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,265,266, 91, 91, 91,
+267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,
+267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,
+267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,
+267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,
+267,267,267,267,267,267,267,267,267,267,267,  2,  2,  2,268,268,
+268, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 43 */
+269,269,269,269,269,269,269,269,269,269,269,269,269, 91,269,269,
+269,269,270,270,270, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,
+271,271,272,272,272,  2,  2, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,
+273,273,274,274, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+275,275,275,275,275,275,275,275,275,275,275,275,275, 91,275,275,
+275, 91,276,276, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 44 */
+277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,
+277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,
+277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,
+277,277,277,277,278,278,279,280,280,280,280,280,280,280,279,279,
+279,279,279,279,279,279,280,279,279,280,280,280,280,280,280,280,
+280,280,280,280,281,281,281,282,281,281,281,283,277,280, 91, 91,
+284,284,284,284,284,284,284,284,284,284, 91, 91, 91, 91, 91, 91,
+285,285,285,285,285,285,285,285,285,285, 91, 91, 91, 91, 91, 91,
+
+/* block 45 */
+286,286,  2,  2,286,  2,287,286,286,286,286,288,288,288,289, 91,
+290,290,290,290,290,290,290,290,290,290, 91, 91, 91, 91, 91, 91,
+291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,
+291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,
+291,291,291,292,291,291,291,291,291,291,291,291,291,291,291,291,
+291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,
+291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,
+291,291,291,291,291,291,291,291, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 46 */
+291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,
+291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,
+291,291,291,291,291,291,291,291,291,288,291, 91, 91, 91, 91, 91,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,261,261, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 47 */
+293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,
+293,293,293,293,293,293,293,293,293,293,293,293,293, 91, 91, 91,
+294,294,294,295,295,295,295,294,294,295,295,295, 91, 91, 91, 91,
+295,295,294,295,295,295,295,295,295,294,294,294, 91, 91, 91, 91,
+296, 91, 91, 91,297,297,298,298,298,298,298,298,298,298,298,298,
+299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,
+299,299,299,299,299,299,299,299,299,299,299,299,299,299, 91, 91,
+299,299,299,299,299, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 48 */
+300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,
+300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,
+300,300,300,300,300,300,300,300,300,300,300,300, 91, 91, 91, 91,
+301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,
+301,300,300,300,300,300,300,300,301,301, 91, 91, 91, 91, 91, 91,
+302,302,302,302,302,302,302,302,302,302,303, 91, 91, 91,304,304,
+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,
+
+/* block 49 */
+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,308,308,308, 91, 91,309,309,
+310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,
+310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,
+310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,
+310,310,310,310,310,311,312,311,312,312,312,312,312,312,312, 91,
+312,311,312,311,311,312,312,312,312,312,312,312,312,311,311,311,
+311,311,311,312,312,312,312,312,312,312,312,312,312, 91, 91,312,
+
+/* block 50 */
+313,313,313,313,313,313,313,313,313,313, 91, 91, 91, 91, 91, 91,
+313,313,313,313,313,313,313,313,313,313, 91, 91, 91, 91, 91, 91,
+314,314,314,314,314,314,314,315,314,314,314,314,314,314, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 51 */
+316,316,316,316,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,318,
+318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,
+318,318,318,318,316,317,316,316,316,316,316,317,316,317,317,317,
+317,317,316,317,317,318,318,318,318,318,318,318, 91, 91, 91, 91,
+319,319,319,319,319,319,319,319,319,319,320,320,320,320,320,320,
+320,321,321,321,321,321,321,321,321,321,321,316,316,316,316,316,
+316,316,316,316,321,321,321,321,321,321,321,321,321, 91, 91, 91,
+
+/* block 52 */
+322,322,323,324,324,324,324,324,324,324,324,324,324,324,324,324,
+324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
+324,323,322,322,322,322,323,323,322,322,323, 91, 91, 91,324,324,
+325,325,325,325,325,325,325,325,325,325, 91, 91, 91, 91, 91, 91,
+326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,
+326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,
+326,326,326,326,326,326,327,328,327,327,328,328,328,327,328,327,
+327,327,328,328, 91, 91, 91, 91, 91, 91, 91, 91,329,329,329,329,
+
+/* block 53 */
+330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,
+330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,
+330,330,330,330,331,331,331,331,331,331,331,331,332,332,332,332,
+332,332,332,332,331,331,332,332, 91, 91, 91,333,333,333,333,333,
+334,334,334,334,334,334,334,334,334,334, 91, 91, 91,330,330,330,
+335,335,335,335,335,335,335,335,335,335,336,336,336,336,336,336,
+336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
+336,336,336,336,336,336,336,336,337,337,337,337,337,337,338,338,
+
+/* block 54 */
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 86, 86, 86,  2, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86,339, 86, 86, 86, 86, 86, 86, 86,340,340,340,340, 86,340,340,
+340,340,339, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 55 */
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 98, 98, 98, 98, 98,341, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 92, 92, 92,
+ 92, 92, 14, 14, 14, 14, 98, 98, 98, 98, 98, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,342,343, 14, 14, 14,344, 14, 14,
+
+/* block 56 */
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 92,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 86, 86, 86, 86,
+
+/* block 57 */
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+
+/* block 58 */
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 14, 14, 14, 14, 14,345, 14, 14,346, 14,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+
+/* block 59 */
+347,347,347,347,347,347,347,347,348,348,348,348,348,348,348,348,
+347,347,347,347,347,347, 91, 91,348,348,348,348,348,348, 91, 91,
+347,347,347,347,347,347,347,347,348,348,348,348,348,348,348,348,
+347,347,347,347,347,347,347,347,348,348,348,348,348,348,348,348,
+347,347,347,347,347,347, 91, 91,348,348,348,348,348,348, 91, 91,
+ 98,347, 98,347, 98,347, 98,347, 91,348, 91,348, 91,348, 91,348,
+347,347,347,347,347,347,347,347,348,348,348,348,348,348,348,348,
+349,349,350,350,350,350,351,351,352,352,353,353,354,354, 91, 91,
+
+/* block 60 */
+347,347,347,347,347,347,347,347,355,355,355,355,355,355,355,355,
+347,347,347,347,347,347,347,347,355,355,355,355,355,355,355,355,
+347,347,347,347,347,347,347,347,355,355,355,355,355,355,355,355,
+347,347, 98,356, 98, 91, 98, 98,348,348,357,357,358, 90,359, 90,
+ 90, 90, 98,356, 98, 91, 98, 98,360,360,360,360,358, 90, 90, 90,
+347,347, 98, 98, 91, 91, 98, 98,348,348,361,361, 91, 90, 90, 90,
+347,347, 98, 98, 98,117, 98, 98,348,348,362,362,121, 90, 90, 90,
+ 91, 91, 98,356, 98, 91, 98, 98,363,363,364,364,358, 90, 90, 91,
+
+/* block 61 */
+  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 16,365,365, 16, 16,
+  7,  7,  7,  7,  7,  7,  2,  2, 15, 19,  4, 15, 15, 19,  4, 15,
+  2,  2,  2,  2,  2,  2,  2,  2,366,367, 16, 16, 16, 16, 16,  1,
+  2,  2,  2,  2,  2,  2,  2,  2,  2, 15, 19,  2,  2,  2,  2, 11,
+ 11,  2,  2,  2,  6,  4,  5,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+  2,  2,  6,  2, 11,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  1,
+ 16, 16, 16, 16, 16, 91, 91, 91, 91, 91, 16, 16, 16, 16, 16, 16,
+ 17, 83, 91, 91, 17, 17, 17, 17, 17, 17,  6,  6,  6,  4,  5, 83,
+
+/* block 62 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,  6,  6,  6,  4,  5, 91,
+ 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 91, 91, 91,
+  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,368,368,368,
+368, 86,368,368,368, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 63 */
+ 13, 13,369, 13, 13, 13, 13,369, 13, 13,370,369,369,369,370,370,
+369,369,369,370, 13,369, 13, 13,  6,369,369,369,369,369, 13, 13,
+ 13, 13, 13, 13,369, 13,371, 13,369, 13,372,373,369,369, 13,370,
+369,369,374,369,370,340,340,340,340,370, 13, 13,370,370,369,369,
+  6,  6,  6,  6,  6,369,370,370,370,370, 13,  6, 13, 13,375, 13,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,
+377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,
+
+/* block 64 */
+378,378,378, 21, 22,378,378,378,378, 17, 91, 91, 91, 91, 91, 91,
+  6,  6,  6,  6,  6, 13, 13, 13, 13, 13,  6,  6, 13, 13, 13, 13,
+  6, 13, 13,  6, 13, 13,  6, 13, 13, 13, 13, 13, 13, 13,  6, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  6,  6,
+ 13, 13,  6, 13,  6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+
+/* block 65 */
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+
+/* block 66 */
+ 13, 13, 13, 13, 13, 13, 13, 13,  6,  6,  6,  6, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+  6,  6, 13, 13, 13, 13, 13, 13, 13,  4,  5, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  6, 13, 13, 13,
+
+/* block 67 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  6,  6,  6,  6,  6,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+  6,  6,  6,  6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  6,  6,  6,  6,
+  6,  6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 68 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+
+/* block 69 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13,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,
+380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,
+380,380,380,380,380,380,380,380,380,380, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+
+/* block 70 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+
+/* block 71 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13,  6, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13,  6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,  6,  6,  6,  6,  6,  6,  6,  6,
+
+/* block 72 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  6,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+
+/* block 73 */
+ 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,  4,  5,  4,  5,  4,  5,  4,  5,
+  4,  5,  4,  5,  4,  5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+
+/* block 74 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+  6,  6,  6,  6,  6,  4,  5,  6,  6,  6,  6, 91,  6, 91,  6,  6,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+  6,  6,  6,  6,  6,  6,  4,  5,  4,  5,  4,  5,  4,  5,  4,  5,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+
+/* block 75 */
+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,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,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,381,381,381,381,381,381,381,381,381,381,381,381,381,381,
+
+/* block 76 */
+  6,  6,  6,  4,  5,  4,  5,  4,  5,  4,  5,  4,  5,  4,  5,  4,
+  5,  4,  5,  4,  5,  4,  5,  4,  5,  6,  6,  6,  6,  6,  6,  6,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+  6,  6,  6,  6,  6,  6,  6,  6,  4,  5,  4,  5,  6,  6,  6,  6,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  4,  5,  6,  6,
+
+/* block 77 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+  6,  6,  6,  6,  6, 13, 13,  6,  6,  6,  6,  6,  6, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 78 */
+382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,
+382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,
+382,382,382,382,382,382,382,382,382,382,382,382,382,382,382, 91,
+383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,
+383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,
+383,383,383,383,383,383,383,383,383,383,383,383,383,383,383, 91,
+ 21, 22,384,385,386,387,388, 21, 22, 21, 22, 21, 22,389,390,391,
+392, 14, 21, 22, 14, 21, 22, 14, 14, 14, 14, 14, 14, 83,393,393,
+
+/* block 79 */
+113,114,113,114,113,114,113,114,113,114,113,114,113,114,113,114,
+113,114,113,114,113,114,113,114,113,114,113,114,113,114,113,114,
+113,114,113,114,113,114,113,114,113,114,113,114,113,114,113,114,
+113,114,113,114,113,114,113,114,113,114,113,114,113,114,113,114,
+113,114,113,114,113,114,113,114,113,114,113,114,113,114,113,114,
+113,114,113,114,113,114,113,114,113,114,113,114,113,114,113,114,
+113,114,113,114,394,395,395,395,395,395,395,113,114,113,114,396,
+396,396, 91, 91, 91, 91, 91, 91, 91,397,397,397,397,398,397,397,
+
+/* block 80 */
+399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,
+399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,
+399,399,399,399,399,399, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,
+400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,
+400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,
+400,400,400,400,400,400, 91, 91, 91, 91, 91, 91, 91, 91, 91,401,
+402, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,403,
+
+/* block 81 */
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+254,254,254,254,254,254,254, 91,254,254,254,254,254,254,254, 91,
+254,254,254,254,254,254,254, 91,254,254,254,254,254,254,254, 91,
+254,254,254,254,254,254,254, 91,254,254,254,254,254,254,254, 91,
+254,254,254,254,254,254,254, 91,254,254,254,254,254,254,254, 91,
+130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,
+130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,
+
+/* block 82 */
+  2,  2, 15, 19, 15, 19,  2,  2,  2, 15, 19,  2, 15, 19,  2,  2,
+  2,  2,  2,  2,  2,  2,  2,  7,  2,  2,  7,  2, 15, 19,  2,  2,
+ 15, 19,  4,  5,  4,  5,  4,  5,  4,  5,  2,  2,  2,  2,  2, 84,
+  2,  2, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 83 */
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404, 91,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 84 */
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+
+/* block 85 */
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,404,404,404,404,404, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91,
+
+/* block 86 */
+  1,  2,  2,  2, 13,405,340,406,  4,  5,  4,  5,  4,  5,  4,  5,
+  4,  5, 13, 13,  4,  5,  4,  5,  4,  5,  4,  5,  7,  4,  5,  5,
+ 13,406,406,406,406,406,406,406,406,406, 86, 86, 86, 86,407,407,
+  7, 84, 84, 84, 84, 84, 13, 13,406,406,406,405,340,  2, 13, 13,
+ 91,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
+408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
+408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
+408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
+
+/* block 87 */
+408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,
+408,408,408,408,408,408,408, 91, 91, 86, 86, 10, 10,409,409,408,
+  7,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,
+410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,
+410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,
+410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,
+410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,
+410,410,410,410,410,410,410,410,410,410,410,  2, 84,411,411,410,
+
+/* block 88 */
+ 91, 91, 91, 91, 91,412,412,412,412,412,412,412,412,412,412,412,
+412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,
+412,412,412,412,412,412,412,412,412,412,412,412,412,412, 91, 91,
+ 91,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+
+/* block 89 */
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, 91,
+ 13, 13, 17, 17, 17, 17, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,
+412,412,412,412,412,412,412,412,412,412,412, 91, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,
+
+/* block 90 */
+413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,
+413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, 91,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,
+413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, 13,
+
+/* block 91 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
+414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
+414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, 91,
+
+/* block 92 */
+414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
+414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
+414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
+414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
+414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
+414,414,414,414,414,414,414,414, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+
+/* block 93 */
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+
+/* block 94 */
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+
+/* block 95 */
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 96 */
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
+416,416,416,416,416,417,416,416,416,416,416,416,416,416,416,416,
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
+
+/* block 97 */
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
+
+/* block 98 */
+416,416,416,416,416,416,416,416,416,416,416,416,416, 91, 91, 91,
+418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,
+418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,
+418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,
+418,418,418,418,418,418,418, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
+419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
+419,419,419,419,419,419,419,419,420,420,420,420,420,420,421,421,
+
+/* block 99 */
+422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
+422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
+422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
+422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
+422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
+422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
+422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
+422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
+
+/* block 100 */
+422,422,422,422,422,422,422,422,422,422,422,422,423,424,424,424,
+422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
+425,425,425,425,425,425,425,425,425,425,422,422, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128,
+127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128,
+127,128,127,128,127,128,127,128,127,128,127,128,127,128,426,130,
+131,131,131,427, 91, 91, 91, 91, 91, 91, 91, 91,130,130,427,342,
+
+/* block 101 */
+127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128,
+127,128,127,128,127,128,127,128, 91, 91, 91, 91, 91, 91, 91, 91,
+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,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,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,
+430,430,431,431,431,431,431,431, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 102 */
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+ 10, 10, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 14, 14, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22,
+ 83, 14, 14, 14, 14, 14, 14, 14, 14, 21, 22, 21, 22,432, 21, 22,
+
+/* block 103 */
+ 21, 22, 21, 22, 21, 22, 21, 22, 84, 10, 10, 21, 22,433, 14, 91,
+ 21, 22, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 14, 45, 45, 45, 45, 45,
+
+/* block 104 */
+434,434,435,434,434,434,435,434,434,434,434,435,434,434,434,434,
+434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,
+434,434,434,436,436,435,435,436,437,437,437,437, 91, 91, 91, 91,
+ 17, 17, 17, 17, 17, 17, 13, 13,  3, 13, 91, 91, 91, 91, 91, 91,
+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,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, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 105 */
+440,440,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,441,441,441,440,440,440,440,440,440,440,440,440,440,440,440,
+440,440,440,440,442, 91, 91, 91, 91, 91, 91, 91, 91, 91,443,443,
+444,444,444,444,444,444,444,444,444,444, 91, 91, 91, 91, 91, 91,
+172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
+172,172,174,174,174,174,174,174,445,445,445,174, 91, 91, 91, 91,
+
+/* block 106 */
+446,446,446,446,446,446,446,446,446,446,447,447,447,447,447,447,
+447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,
+447,447,447,447,447,447,448,448,448,448,448,448,448,448,449,449,
+450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,
+450,450,450,450,450,450,450,451,451,451,451,451,451,451,451,451,
+451,451,452,452, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,453,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253, 91, 91, 91,
+
+/* block 107 */
+454,454,454,455,456,456,456,456,456,456,456,456,456,456,456,456,
+456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,
+456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,
+456,456,456,454,455,455,454,454,454,454,455,455,454,455,455,455,
+455,457,457,457,457,457,457,457,457,457,457,457,457,457, 91,458,
+459,459,459,459,459,459,459,459,459,459, 91, 91, 91, 91,457,457,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 108 */
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,461,461,461,461,461,461,462,
+462,461,461,462,462,461,461, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+460,460,460,461,460,460,460,460,460,460,460,460,461,462, 91, 91,
+463,463,463,463,463,463,463,463,463,463, 91, 91,464,464,464,464,
+244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
+465,244,244,244,244,244,244,249,249,249,244,245, 91, 91, 91, 91,
+
+/* block 109 */
+466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
+466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
+466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
+467,466,467,467,467,466,466,467,467,466,466,466,466,466,467,467,
+466,467,466, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,466,466,468,469,469,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 110 */
+ 91,254,254,254,254,254,254, 91, 91,254,254,254,254,254,254, 91,
+ 91,254,254,254,254,254,254, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+254,254,254,254,254,254,254, 91,254,254,254,254,254,254,254, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 111 */
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,
+470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,
+470,470,470,471,471,472,471,471,472,471,471,473,471,472, 91, 91,
+474,474,474,474,474,474,474,474,474,474, 91, 91, 91, 91, 91, 91,
+
+/* block 112 */
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253, 91, 91, 91, 91,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253, 91, 91, 91, 91,
+
+/* block 113 */
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,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 114 */
+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 115 */
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415, 91, 91,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415, 91, 91,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+
+/* block 116 */
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 117 */
+ 14, 14, 14, 14, 14, 14, 14, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91,138,138,138,138,138, 91, 91, 91, 91, 91,143,140,143,
+143,143,143,143,143,143,143,143,143,477,143,143,143,143,143,143,
+143,143,143,143,143,143,143, 91,143,143,143,143,143, 91,143, 91,
+143,143, 91,143,143, 91,143,143,143,143,143,143,143,143,143,143,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+
+/* block 118 */
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
+478,478, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+
+/* block 119 */
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+
+/* block 120 */
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,  4,  5,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+
+/* block 121 */
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+ 91, 91,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+150,150,150,150,150,150,150,150,150,150,150,150,147, 13, 91, 91,
+
+/* block 122 */
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+  2,  2,  2,  2,  2,  2,  2,  4,  5,  2, 91, 91, 91, 91, 91, 91,
+ 86, 86, 86, 86, 86, 86, 86, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+  2,  7,  7, 11, 11,  4,  5,  4,  5,  4,  5,  4,  5,  4,  5,  4,
+  5,  4,  5,  4,  5,  2,  2,  4,  5,  2,  2,  2,  2, 11, 11, 11,
+  2,  2,  2, 91,  2,  2,  2,  2,  7,  4,  5,  4,  5,  4,  5,  2,
+  2,  2,  6,  7,  6,  6,  6, 91,  2,  3,  2,  2, 91, 91, 91, 91,
+150,150,150,150,150, 91,150,150,150,150,150,150,150,150,150,150,
+
+/* block 123 */
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,150,150,150,150,150,150,150,150, 91, 91, 16,
+
+/* block 124 */
+ 91,  2,  2,  2,  3,  2,  2,  2,  4,  5,  2,  6,  2,  7,  2,  2,
+  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  2,  2,  6,  6,  6,  2,
+  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  4,  2,  5, 10, 11,
+ 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  4,  6,  5,  6,  4,
+  5,  2,  4,  5,  2,  2,410,410,410,410,410,410,410,410,410,410,
+ 84,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,
+
+/* block 125 */
+410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,
+410,410,410,410,410,410,410,410,410,410,410,410,410,410, 84, 84,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, 91,
+ 91, 91,253,253,253,253,253,253, 91, 91,253,253,253,253,253,253,
+ 91, 91,253,253,253,253,253,253, 91, 91,253,253,253, 91, 91, 91,
+  3,  3,  6, 10, 13,  3,  3, 91, 13,  6,  6,  6,  6, 13, 13, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 16, 16, 16, 13, 13, 91, 91,
+
+/* block 126 */
+479,479,479,479,479,479,479,479,479,479,479,479, 91,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, 91,479,479,479,479,479,479,479,479,
+479,479,479,479,479,479,479,479,479,479,479, 91,479,479, 91,479,
+479,479,479,479,479,479,479,479,479,479,479,479,479,479, 91, 91,
+479,479,479,479,479,479,479,479,479,479,479,479,479,479, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 127 */
+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,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,
+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,479,479,479, 91, 91, 91, 91, 91,
+
+/* block 128 */
+  2,  2, 13, 91, 91, 91, 91, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 91, 91, 91, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
+480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
+480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
+480,480,480,480,480,481,481,481,481,482,482,482,482,482,482,482,
+
+/* block 129 */
+482,482,482,482,482,482,482,482,482,482,481, 91, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 86, 91, 91,
+
+/* block 130 */
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,483,483,483,483,483,483, 91, 91, 91,
+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,
+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,
+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,
+484, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 131 */
+485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,
+485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, 91,
+486,486,486,486, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
+487,488,487,487,487,487,487,487,487,487,488, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 132 */
+489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,
+489,489,489,489,489,489,489,489,489,489,489,489,489,489, 91,490,
+491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,
+491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,
+491,491,491,491, 91, 91, 91, 91,491,491,491,491,491,491,491,491,
+492,493,493,493,493,493, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 133 */
+494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,
+494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,
+494,494,494,494,494,494,494,494,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,
+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,
+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,
+
+/* block 134 */
+497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,
+497,497,497,497,497,497,497,497,497,497,497,497,497,497, 91, 91,
+498,498,498,498,498,498,498,498,498,498, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 135 */
+499,499,499,499,499,499, 91, 91,499, 91,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, 91,499,499, 91, 91, 91,499, 91, 91,499,
+500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,
+500,500,500,500,500,500, 91,501,502,502,502,502,502,502,502,502,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 136 */
+503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
+503,503,503,503,503,503,504,504,504,504,504,504, 91, 91, 91,505,
+506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,
+506,506,506,506,506,506,506,506,506,506, 91, 91, 91, 91, 91,507,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 137 */
+508,509,509,509, 91,509,509, 91, 91, 91, 91, 91,509,509,509,509,
+508,508,508,508, 91,508,508,508, 91,508,508,508,508,508,508,508,
+508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,
+508,508,508,508, 91, 91, 91, 91,509,509,509, 91, 91, 91, 91,509,
+510,510,510,510,510,510,510,510, 91, 91, 91, 91, 91, 91, 91, 91,
+511,511,511,511,511,511,511,511,511, 91, 91, 91, 91, 91, 91, 91,
+512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,
+512,512,512,512,512,512,512,512,512,512,512,512,512,513,513,514,
+
+/* block 138 */
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515, 91, 91, 91,516,516,516,516,516,516,516,
+517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,
+517,517,517,517,517,517, 91, 91,518,518,518,518,518,518,518,518,
+519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
+519,519,519, 91, 91, 91, 91, 91,520,520,520,520,520,520,520,520,
+
+/* block 139 */
+521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,
+521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,
+521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,
+521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,
+521,521,521,521,521,521,521,521,521, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 140 */
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
+522,522,522,522,522,522,522,522,522,522,522,522,522,522,522, 91,
+
+/* block 141 */
+523,524,523,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,525,525,525,525,525,524,524,524,524,524,524,524,524,
+524,524,524,524,524,524,524,526,526,526,526,526,526,526, 91, 91,
+ 91, 91,527,527,527,527,527,527,527,527,527,527,527,527,527,527,
+527,527,527,527,527,527,528,528,528,528,528,528,528,528,528,528,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 142 */
+529,529,530,531,531,531,531,531,531,531,531,531,531,531,531,531,
+531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,
+531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,
+530,530,530,529,529,529,529,530,530,529,529,532,532,533,532,532,
+532,532, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 143 */
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+
+/* block 144 */
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 145 */
+535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,
+535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,
+535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,
+535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,
+535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,
+535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,
+535,535,535, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+536,536,536,536, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 146 */
+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 147 */
+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, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 148 */
+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,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,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,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,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 149 */
+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,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,428,428,428,428,428, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 150 */
+410,408, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 151 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 152 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 91, 91, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13,339,339, 86, 86, 86, 13, 13, 13,339,339,339,
+339,339,339, 16, 16, 16, 16, 16, 16, 16, 16, 86, 86, 86, 86, 86,
+
+/* block 153 */
+ 86, 86, 86, 13, 13, 86, 86, 86, 86, 86, 86, 86, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 86, 86, 86, 86, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 154 */
+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,538,538,538,482, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 155 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 156 */
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,370,370,370,370,370,370,
+370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+370,370,370,370,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,370,370,
+370,370,370,370,370, 91,370,370,370,370,370,370,370,370,370,370,
+370,370,370,370,370,370,370,370,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+
+/* block 157 */
+369,369,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+370,370,370,370,370,370,370,370,370,370,370,370,369, 91,369,369,
+ 91, 91,369, 91, 91,369,369, 91, 91,369,369,369,369, 91,369,369,
+369,369,369,369,369,369,370,370,370,370, 91,370, 91,370,370,370,
+370,370,370,370, 91,370,370,370,370,370,370,370,370,370,370,370,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,370,370,370,370,370,370,
+370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+
+/* block 158 */
+370,370,370,370,369,369, 91,369,369,369,369, 91, 91,369,369,369,
+369,369,369,369,369, 91,369,369,369,369,369,369,369, 91,370,370,
+370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+370,370,370,370,370,370,370,370,369,369, 91,369,369,369,369, 91,
+369,369,369,369,369, 91,369, 91, 91, 91,369,369,369,369,369,369,
+369, 91,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+370,370,370,370,370,370,370,370,370,370,370,370,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+
+/* block 159 */
+369,369,369,369,369,369,370,370,370,370,370,370,370,370,370,370,
+370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,370,370,370,370,370,370,
+370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+370,370,370,370,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,370,370,
+370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+
+/* block 160 */
+370,370,370,370,370,370,370,370,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+370,370,370,370,370,370,370,370,370,370,370,370,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,370,370,370,370,370,370,370,370,370,370,
+370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+
+/* block 161 */
+369,369,369,369,369,369,369,369,369,369,370,370,370,370,370,370,
+370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+370,370,370,370,370,370, 91, 91,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,  6,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+370,370,370,370,370,370,370,370,370,370,370,  6,370,370,370,370,
+370,370,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,  6,370,370,370,370,
+
+/* block 162 */
+370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+370,370,370,370,370,  6,370,370,370,370,370,370,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,  6,370,370,370,370,370,370,370,370,370,370,
+370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,  6,
+370,370,370,370,370,370,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,  6,
+370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+
+/* block 163 */
+370,370,370,370,370,370,370,370,370,  6,370,370,370,370,370,370,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,  6,370,370,370,370,370,370,
+370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+370,370,370,  6,370,370,370,370,370,370,369,370, 91, 91,  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 164 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+
+/* block 165 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91,
+ 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91,
+ 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 166 */
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 91, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+
+/* block 167 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+
+/* block 168 */
+539, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91,
+ 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 169 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 91, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91,
+
+/* block 170 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 91, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 171 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91,
+ 13, 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+
+/* block 172 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 91, 13, 13, 13, 13, 91, 91, 91,
+
+/* block 173 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 174 */
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 13, 13, 13, 13, 13,
+
+/* block 175 */
+ 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 91, 13, 13, 13, 91, 13, 91, 13, 91, 13, 91, 13, 13, 13, 91,
+ 13, 13, 13, 13, 13, 13, 91, 91, 13, 13, 13, 13, 91, 13, 91, 91,
+ 13, 13, 13, 13, 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 91, 91, 91, 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 176 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 177 */
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 178 */
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 179 */
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+
+/* block 180 */
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 181 */
+ 91, 16, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 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, 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, 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, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+
+/* block 182 */
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+
+/* block 183 */
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+
+/* block 184 */
+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, 91, 91,
+
+};
+
+#if UCD_BLOCK_SIZE != 128
+#error Please correct UCD_BLOCK_SIZE in pcre_internal.h
+#endif
+#endif  /* SUPPORT_UCP */
diff --git a/src/3rdparty/pcre/pcre_valid_utf8.c b/src/3rdparty/pcre/pcre_valid_utf8.c
new file mode 100644 (file)
index 0000000..b2dc5c9
--- /dev/null
@@ -0,0 +1,299 @@
+/*************************************************
+*      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 an internal function for validating UTF-8 character
+strings. */
+
+
+#ifdef PCRE_HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre_internal.h"
+
+
+/*************************************************
+*         Validate a UTF-8 string                *
+*************************************************/
+
+/* This function is called (optionally) at the start of compile or match, to
+check that a supposed UTF-8 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.
+
+Originally, this function checked according to RFC 2279, allowing for values in
+the range 0 to 0x7fffffff, up to 6 bytes long, but ensuring that they were in
+the canonical format. Once somebody had pointed out RFC 3629 to me (it
+obsoletes 2279), additional restrictions were applied. The values are now
+limited to be between 0 and 0x0010ffff, no more than 4 bytes long, and the
+subrange 0xd000 to 0xdfff is excluded. However, the format of 5-byte and 6-byte
+characters is still checked.
+
+From release 8.13 more information about the details of the error are passed
+back in the returned value:
+
+PCRE_UTF8_ERR0   No error
+PCRE_UTF8_ERR1   Missing 1 byte at the end of the string
+PCRE_UTF8_ERR2   Missing 2 bytes at the end of the string
+PCRE_UTF8_ERR3   Missing 3 bytes at the end of the string
+PCRE_UTF8_ERR4   Missing 4 bytes at the end of the string
+PCRE_UTF8_ERR5   Missing 5 bytes at the end of the string
+PCRE_UTF8_ERR6   2nd-byte's two top bits are not 0x80
+PCRE_UTF8_ERR7   3rd-byte's two top bits are not 0x80
+PCRE_UTF8_ERR8   4th-byte's two top bits are not 0x80
+PCRE_UTF8_ERR9   5th-byte's two top bits are not 0x80
+PCRE_UTF8_ERR10  6th-byte's two top bits are not 0x80
+PCRE_UTF8_ERR11  5-byte character is not permitted by RFC 3629
+PCRE_UTF8_ERR12  6-byte character is not permitted by RFC 3629
+PCRE_UTF8_ERR13  4-byte character with value > 0x10ffff is not permitted
+PCRE_UTF8_ERR14  3-byte character with value 0xd000-0xdfff is not permitted
+PCRE_UTF8_ERR15  Overlong 2-byte sequence
+PCRE_UTF8_ERR16  Overlong 3-byte sequence
+PCRE_UTF8_ERR17  Overlong 4-byte sequence
+PCRE_UTF8_ERR18  Overlong 5-byte sequence (won't ever occur)
+PCRE_UTF8_ERR19  Overlong 6-byte sequence (won't ever occur)
+PCRE_UTF8_ERR20  Isolated 0x80 byte (not within UTF-8 character)
+PCRE_UTF8_ERR21  Byte with the illegal value 0xfe or 0xff
+
+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-8 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;
+
+if (length < 0)
+  {
+  for (p = string; *p != 0; p++);
+  length = (int)(p - string);
+  }
+
+for (p = string; length-- > 0; p++)
+  {
+  register int ab, c, d;
+
+  c = *p;
+  if (c < 128) continue;                /* ASCII character */
+
+  if (c < 0xc0)                         /* Isolated 10xx xxxx byte */
+    {
+    *erroroffset = (int)(p - string);
+    return PCRE_UTF8_ERR20;
+    }
+
+  if (c >= 0xfe)                        /* Invalid 0xfe or 0xff bytes */
+    {
+    *erroroffset = (int)(p - string);
+    return PCRE_UTF8_ERR21;
+    }
+
+  ab = PRIV(utf8_table4)[c & 0x3f];     /* Number of additional bytes */
+  if (length < ab)
+    {
+    *erroroffset = (int)(p - string);          /* Missing bytes */
+    return ab - length;                 /* Codes ERR1 to ERR5 */
+    }
+  length -= ab;                         /* Length remaining */
+
+  /* Check top bits in the second byte */
+
+  if (((d = *(++p)) & 0xc0) != 0x80)
+    {
+    *erroroffset = (int)(p - string) - 1;
+    return PCRE_UTF8_ERR6;
+    }
+
+  /* For each length, check that the remaining bytes start with the 0x80 bit
+  set and not the 0x40 bit. Then check for an overlong sequence, and for the
+  excluded range 0xd800 to 0xdfff. */
+
+  switch (ab)
+    {
+    /* 2-byte character. No further bytes to check for 0x80. Check first byte
+    for for xx00 000x (overlong sequence). */
+
+    case 1: if ((c & 0x3e) == 0)
+      {
+      *erroroffset = (int)(p - string) - 1;
+      return PCRE_UTF8_ERR15;
+      }
+    break;
+
+    /* 3-byte character. Check third byte for 0x80. Then check first 2 bytes
+      for 1110 0000, xx0x xxxx (overlong sequence) or
+          1110 1101, 1010 xxxx (0xd800 - 0xdfff) */
+
+    case 2:
+    if ((*(++p) & 0xc0) != 0x80)     /* Third byte */
+      {
+      *erroroffset = (int)(p - string) - 2;
+      return PCRE_UTF8_ERR7;
+      }
+    if (c == 0xe0 && (d & 0x20) == 0)
+      {
+      *erroroffset = (int)(p - string) - 2;
+      return PCRE_UTF8_ERR16;
+      }
+    if (c == 0xed && d >= 0xa0)
+      {
+      *erroroffset = (int)(p - string) - 2;
+      return PCRE_UTF8_ERR14;
+      }
+    break;
+
+    /* 4-byte character. Check 3rd and 4th bytes for 0x80. Then check first 2
+       bytes for for 1111 0000, xx00 xxxx (overlong sequence), then check for a
+       character greater than 0x0010ffff (f4 8f bf bf) */
+
+    case 3:
+    if ((*(++p) & 0xc0) != 0x80)     /* Third byte */
+      {
+      *erroroffset = (int)(p - string) - 2;
+      return PCRE_UTF8_ERR7;
+      }
+    if ((*(++p) & 0xc0) != 0x80)     /* Fourth byte */
+      {
+      *erroroffset = (int)(p - string) - 3;
+      return PCRE_UTF8_ERR8;
+      }
+    if (c == 0xf0 && (d & 0x30) == 0)
+      {
+      *erroroffset = (int)(p - string) - 3;
+      return PCRE_UTF8_ERR17;
+      }
+    if (c > 0xf4 || (c == 0xf4 && d > 0x8f))
+      {
+      *erroroffset = (int)(p - string) - 3;
+      return PCRE_UTF8_ERR13;
+      }
+    break;
+
+    /* 5-byte and 6-byte characters are not allowed by RFC 3629, and will be
+    rejected by the length test below. However, we do the appropriate tests
+    here so that overlong sequences get diagnosed, and also in case there is
+    ever an option for handling these larger code points. */
+
+    /* 5-byte character. Check 3rd, 4th, and 5th bytes for 0x80. Then check for
+    1111 1000, xx00 0xxx */
+
+    case 4:
+    if ((*(++p) & 0xc0) != 0x80)     /* Third byte */
+      {
+      *erroroffset = (int)(p - string) - 2;
+      return PCRE_UTF8_ERR7;
+      }
+    if ((*(++p) & 0xc0) != 0x80)     /* Fourth byte */
+      {
+      *erroroffset = (int)(p - string) - 3;
+      return PCRE_UTF8_ERR8;
+      }
+    if ((*(++p) & 0xc0) != 0x80)     /* Fifth byte */
+      {
+      *erroroffset = (int)(p - string) - 4;
+      return PCRE_UTF8_ERR9;
+      }
+    if (c == 0xf8 && (d & 0x38) == 0)
+      {
+      *erroroffset = (int)(p - string) - 4;
+      return PCRE_UTF8_ERR18;
+      }
+    break;
+
+    /* 6-byte character. Check 3rd-6th bytes for 0x80. Then check for
+    1111 1100, xx00 00xx. */
+
+    case 5:
+    if ((*(++p) & 0xc0) != 0x80)     /* Third byte */
+      {
+      *erroroffset = (int)(p - string) - 2;
+      return PCRE_UTF8_ERR7;
+      }
+    if ((*(++p) & 0xc0) != 0x80)     /* Fourth byte */
+      {
+      *erroroffset = (int)(p - string) - 3;
+      return PCRE_UTF8_ERR8;
+      }
+    if ((*(++p) & 0xc0) != 0x80)     /* Fifth byte */
+      {
+      *erroroffset = (int)(p - string) - 4;
+      return PCRE_UTF8_ERR9;
+      }
+    if ((*(++p) & 0xc0) != 0x80)     /* Sixth byte */
+      {
+      *erroroffset = (int)(p - string) - 5;
+      return PCRE_UTF8_ERR10;
+      }
+    if (c == 0xfc && (d & 0x3c) == 0)
+      {
+      *erroroffset = (int)(p - string) - 5;
+      return PCRE_UTF8_ERR19;
+      }
+    break;
+    }
+
+  /* Character is valid under RFC 2279, but 4-byte and 5-byte characters are
+  excluded by RFC 3629. The pointer p is currently at the last byte of the
+  character. */
+
+  if (ab > 3)
+    {
+    *erroroffset = (int)(p - string) - ab;
+    return (ab == 4)? PCRE_UTF8_ERR11 : PCRE_UTF8_ERR12;
+    }
+  }
+
+#else  /* SUPPORT_UTF */
+(void)(string);  /* Keep picky compilers happy */
+(void)(length);
+#endif
+
+return PCRE_UTF8_ERR0;   /* This indicates success */
+}
+
+/* End of pcre_valid_utf8.c */
diff --git a/src/3rdparty/pcre/pcre_version.c b/src/3rdparty/pcre/pcre_version.c
new file mode 100644 (file)
index 0000000..915ae87
--- /dev/null
@@ -0,0 +1,95 @@
+/*************************************************
+*      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 PCRE_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. */
+
+#ifdef COMPILE_PCRE8
+PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
+pcre_version(void)
+#else
+PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
+pcre16_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/src/3rdparty/pcre/pcre_xclass.c b/src/3rdparty/pcre/pcre_xclass.c
new file mode 100644 (file)
index 0000000..45f1c5b
--- /dev/null
@@ -0,0 +1,198 @@
+/*************************************************
+*      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 an internal function that is used to match an extended
+class. It is used by both pcre_exec() and pcre_def_exec(). */
+
+
+#ifdef PCRE_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)(int c, const pcre_uchar *data, BOOL utf)
+{
+int 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_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)
+  {
+  int 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);
+
+    switch(*data)
+      {
+      case PT_ANY:
+      if (t == XCL_PROP) return !negated;
+      break;
+
+      case PT_LAMP:
+      if ((prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
+           prop->chartype == ucp_Lt) == (t == XCL_PROP)) return !negated;
+      break;
+
+      case PT_GC:
+      if ((data[1] == PRIV(ucp_gentype)[prop->chartype]) == (t == XCL_PROP))
+        return !negated;
+      break;
+
+      case PT_PC:
+      if ((data[1] == prop->chartype) == (t == XCL_PROP)) return !negated;
+      break;
+
+      case PT_SC:
+      if ((data[1] == prop->script) == (t == XCL_PROP)) return !negated;
+      break;
+
+      case PT_ALNUM:
+      if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+           PRIV(ucp_gentype)[prop->chartype] == ucp_N) == (t == XCL_PROP))
+        return !negated;
+      break;
+
+      case PT_SPACE:    /* Perl space */
+      if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
+           c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR)
+             == (t == XCL_PROP))
+        return !negated;
+      break;
+
+      case PT_PXSPACE:  /* POSIX space */
+      if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
+           c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
+           c == CHAR_FF || c == CHAR_CR) == (t == XCL_PROP))
+        return !negated;
+      break;
+
+      case PT_WORD:
+      if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+           PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE)
+             == (t == XCL_PROP))
+        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/src/3rdparty/pcre/sljit/sljitConfig.h b/src/3rdparty/pcre/sljit/sljitConfig.h
new file mode 100644 (file)
index 0000000..c832dfe
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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 _SLJIT_CONFIG_H_
+#define _SLJIT_CONFIG_H_
+
+/* --------------------------------------------------------------------- */
+/*  Architecture                                                         */
+/* --------------------------------------------------------------------- */
+
+/* Architecture selection */
+/* #define SLJIT_CONFIG_X86_32 1 */
+/* #define SLJIT_CONFIG_X86_64 1 */
+/* #define SLJIT_CONFIG_ARM_V5 1 */
+/* #define SLJIT_CONFIG_ARM_V7 1 */
+/* #define SLJIT_CONFIG_ARM_THUMB2 1 */
+/* #define SLJIT_CONFIG_PPC_32 1 */
+/* #define SLJIT_CONFIG_PPC_64 1 */
+/* #define SLJIT_CONFIG_MIPS_32 1 */
+
+/* #define SLJIT_CONFIG_AUTO 1 */
+/* #define SLJIT_CONFIG_UNSUPPORTED 1 */
+
+/* --------------------------------------------------------------------- */
+/*  Utilities                                                            */
+/* --------------------------------------------------------------------- */
+
+/* Useful for thread-safe compiling of global functions. */
+#ifndef SLJIT_UTIL_GLOBAL_LOCK
+/* Enabled by default */
+#define SLJIT_UTIL_GLOBAL_LOCK 1
+#endif
+
+/* Implements a stack like data structure (by using mmap / VirtualAlloc). */
+#ifndef SLJIT_UTIL_STACK
+/* Enabled by default */
+#define SLJIT_UTIL_STACK 1
+#endif
+
+/* --------------------------------------------------------------------- */
+/*  Configuration                                                        */
+/* --------------------------------------------------------------------- */
+
+/* If SLJIT_STD_MACROS_DEFINED is not defined, the application should
+   define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMMOVE, and NULL. */
+#ifndef SLJIT_STD_MACROS_DEFINED
+/* Disabled by default. */
+#define SLJIT_STD_MACROS_DEFINED 0
+#endif
+
+/* Executable code allocation:
+   If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should
+   define both SLJIT_MALLOC_EXEC and SLJIT_FREE_EXEC. */
+#ifndef SLJIT_EXECUTABLE_ALLOCATOR
+/* Enabled by default. */
+#define SLJIT_EXECUTABLE_ALLOCATOR 1
+#endif
+
+/* Debug checks (assertions, etc.). */
+#ifndef SLJIT_DEBUG
+/* Enabled by default */
+#define SLJIT_DEBUG 1
+#endif
+
+/* Verbose operations */
+#ifndef SLJIT_VERBOSE
+/* Enabled by default */
+#define SLJIT_VERBOSE 1
+#endif
+
+/* See the beginning of sljitConfigInternal.h */
+
+#endif
diff --git a/src/3rdparty/pcre/sljit/sljitConfigInternal.h b/src/3rdparty/pcre/sljit/sljitConfigInternal.h
new file mode 100644 (file)
index 0000000..de6e9f0
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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 _SLJIT_CONFIG_INTERNAL_H_
+#define _SLJIT_CONFIG_INTERNAL_H_
+
+/*
+   SLJIT defines the following macros depending on the target architecture:
+
+   Feature detection (boolean) macros:
+   SLJIT_32BIT_ARCHITECTURE : 32 bit architecture
+   SLJIT_64BIT_ARCHITECTURE : 64 bit architecture
+   SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_w/sljit_uw array by index
+   SLJIT_FLOAT_SHIFT : the shift required to apply when accessing a double array by index
+   SLJIT_LITTLE_ENDIAN : little endian architecture
+   SLJIT_BIG_ENDIAN : big endian architecture
+   SLJIT_UNALIGNED : allows unaligned memory accesses for non-fpu operations (only!)
+   SLJIT_INDIRECT_CALL : see SLJIT_FUNC_OFFSET() for more information
+
+   Types and useful macros:
+   sljit_b, sljit_ub : signed and unsigned 8 bit byte
+   sljit_h, sljit_uh : signed and unsigned 16 bit half-word (short) type
+   sljit_i, sljit_ui : signed and unsigned 32 bit integer type
+   sljit_w, sljit_uw : signed and unsigned machine word, enough to store a pointer (same as intptr_t)
+   SLJIT_CALL : C calling convention define for both calling JIT form C and C callbacks for JIT
+   SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (compiler independent helper)
+*/
+
+#if !((defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
+       || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
+       || (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \
+       || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
+       || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
+       || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
+       || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
+       || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
+       || (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
+       || (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED))
+#error "An architecture must be selected"
+#endif
+
+/* Sanity check. */
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
+       + (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
+       + (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \
+       + (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
+       + (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
+       + (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
+       + (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
+       + (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
+       + (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
+       + (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2
+#error "Multiple architectures are selected"
+#endif
+
+/* Auto select option (requires compiler support) */
+#if (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)
+
+#ifndef _WIN32
+
+#if defined(__i386__) || defined(__i386)
+#define SLJIT_CONFIG_X86_32 1
+#elif defined(__x86_64__)
+#define SLJIT_CONFIG_X86_64 1
+#elif defined(__arm__) || defined(__ARM__)
+#ifdef __thumb2__
+#define SLJIT_CONFIG_ARM_THUMB2 1
+#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__)
+#define SLJIT_CONFIG_ARM_V7 1
+#else
+#define SLJIT_CONFIG_ARM_V5 1
+#endif
+#elif defined(__ppc64__) || defined(__powerpc64__)
+#define SLJIT_CONFIG_PPC_64 1
+#elif defined(__ppc__) || defined(__powerpc__)
+#define SLJIT_CONFIG_PPC_32 1
+#elif defined(__mips__)
+#define SLJIT_CONFIG_MIPS_32 1
+#else
+/* Unsupported architecture */
+#define SLJIT_CONFIG_UNSUPPORTED 1
+#endif
+
+#else /* !_WIN32 */
+
+#if defined(_M_X64) || defined(__x86_64__)
+#define SLJIT_CONFIG_X86_64 1
+#elif defined(_ARM_)
+#define SLJIT_CONFIG_ARM_V5 1
+#else
+#define SLJIT_CONFIG_X86_32 1
+#endif
+
+#endif /* !WIN32 */
+#endif /* SLJIT_CONFIG_AUTO */
+
+#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
+#undef SLJIT_EXECUTABLE_ALLOCATOR
+#endif
+
+#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED)
+
+/* These libraries are needed for the macros below. */
+#include <stdlib.h>
+#include <string.h>
+
+#endif /* STD_MACROS_DEFINED */
+
+/* General macros:
+   Note: SLJIT is designed to be independent from them as possible.
+
+   In release mode (SLJIT_DEBUG is not defined) only the following macros are needed:
+*/
+
+#ifndef SLJIT_MALLOC
+#define SLJIT_MALLOC(size) malloc(size)
+#endif
+
+#ifndef SLJIT_FREE
+#define SLJIT_FREE(ptr) free(ptr)
+#endif
+
+#ifndef SLJIT_MEMMOVE
+#define SLJIT_MEMMOVE(dest, src, len) memmove(dest, src, len)
+#endif
+
+#ifndef SLJIT_ZEROMEM
+#define SLJIT_ZEROMEM(dest, len) memset(dest, 0, len)
+#endif
+
+#if !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY)
+
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+#define SLJIT_LIKELY(x)                __builtin_expect((x), 1)
+#define SLJIT_UNLIKELY(x)      __builtin_expect((x), 0)
+#else
+#define SLJIT_LIKELY(x)                (x)
+#define SLJIT_UNLIKELY(x)      (x)
+#endif
+
+#endif /* !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY) */
+
+#ifndef SLJIT_INLINE
+/* Inline functions. */
+#define SLJIT_INLINE __inline
+#endif
+
+#ifndef SLJIT_CONST
+/* Const variables. */
+#define SLJIT_CONST const
+#endif
+
+#ifndef SLJIT_UNUSED_ARG
+/* Unused arguments. */
+#define SLJIT_UNUSED_ARG(arg) (void)arg
+#endif
+
+#if (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC)
+/* Static ABI functions. For all-in-one programs. */
+
+#if defined(__GNUC__)
+/* Disable unused warnings in gcc. */
+#define SLJIT_API_FUNC_ATTRIBUTE static __attribute__((unused))
+#else
+#define SLJIT_API_FUNC_ATTRIBUTE static
+#endif
+
+#else
+#define SLJIT_API_FUNC_ATTRIBUTE
+#endif /* (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) */
+
+#ifndef SLJIT_CACHE_FLUSH
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+
+/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */
+#define SLJIT_CACHE_FLUSH(from, to) \
+       ppc_cache_flush((from), (to))
+
+#elif (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+
+/* Not required to implement on archs with unified caches. */
+#define SLJIT_CACHE_FLUSH(from, to)
+
+#else
+
+/* Calls __ARM_NR_cacheflush on ARM-Linux. */
+#define SLJIT_CACHE_FLUSH(from, to) \
+       __clear_cache((char*)(from), (char*)(to))
+
+#endif
+
+#endif /* !SLJIT_CACHE_FLUSH */
+
+/* 8 bit byte type. */
+typedef unsigned char sljit_ub;
+typedef signed char sljit_b;
+
+/* 16 bit half-word type. */
+typedef unsigned short int sljit_uh;
+typedef signed short int sljit_h;
+
+/* 32 bit integer type. */
+typedef unsigned int sljit_ui;
+typedef signed int sljit_i;
+
+/* Machine word type. Can encapsulate a pointer.
+     32 bit for 32 bit machines.
+     64 bit for 64 bit machines. */
+#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
+/* Just to have something. */
+#define SLJIT_WORD_SHIFT 0
+typedef unsigned long int sljit_uw;
+typedef long int sljit_w;
+#elif !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#define SLJIT_32BIT_ARCHITECTURE 1
+#define SLJIT_WORD_SHIFT 2
+typedef unsigned int sljit_uw;
+typedef int sljit_w;
+#else
+#define SLJIT_64BIT_ARCHITECTURE 1
+#define SLJIT_WORD_SHIFT 3
+#ifdef _WIN32
+typedef unsigned __int64 sljit_uw;
+typedef __int64 sljit_w;
+#else
+typedef unsigned long int sljit_uw;
+typedef long int sljit_w;
+#endif
+#endif
+
+/* Double precision. */
+#define SLJIT_FLOAT_SHIFT 3
+
+#ifndef SLJIT_W
+
+/* Defining long constants. */
+#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
+#define SLJIT_W(w)     (w##ll)
+#else
+#define SLJIT_W(w)     (w)
+#endif
+
+#endif /* !SLJIT_W */
+
+#ifndef SLJIT_CALL
+
+/* ABI (Application Binary Interface) types. */
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+
+#if defined(__GNUC__)
+
+#define SLJIT_CALL __attribute__ ((fastcall))
+#define SLJIT_X86_32_FASTCALL 1
+
+#elif defined(_WIN32)
+
+#ifdef __BORLANDC__
+#define SLJIT_CALL __msfastcall
+#else /* __BORLANDC__ */
+#define SLJIT_CALL __fastcall
+#endif /* __BORLANDC__ */
+#define SLJIT_X86_32_FASTCALL 1
+
+#else /* defined(_WIN32) */
+#define SLJIT_CALL __stdcall
+#endif
+
+#else /* Other architectures. */
+
+#define SLJIT_CALL
+
+#endif /* SLJIT_CONFIG_X86_32 */
+
+#endif /* !SLJIT_CALL */
+
+#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)
+
+/* These macros are useful for the application. */
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#define SLJIT_BIG_ENDIAN 1
+
+#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+
+#ifdef __MIPSEL__
+#define SLJIT_LITTLE_ENDIAN 1
+#else
+#define SLJIT_BIG_ENDIAN 1
+#endif
+
+#else
+#define SLJIT_LITTLE_ENDIAN 1
+#endif
+
+#endif /* !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN) */
+
+/* Sanity check. */
+#if (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
+#error "Exactly one endianness must be selected"
+#endif
+
+#if !(defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && !(defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
+#error "Exactly one endianness must be selected"
+#endif
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+/* It seems ppc64 compilers use an indirect addressing for functions.
+   It makes things really complicated. */
+#define SLJIT_INDIRECT_CALL 1
+#endif
+
+#ifndef SLJIT_SSE2
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+/* Turn on SSE2 support on x86 (operating on doubles).
+   (Better performance than legacy fpu instructions). */
+#define SLJIT_SSE2 1
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+/* Auto detect SSE2 support using CPUID.
+   On 64 bit x86 cpus, sse2 must be present. */
+#define SLJIT_SSE2_AUTO 1
+#endif
+
+#endif /* (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) */
+
+#endif /* !SLJIT_SSE2 */
+
+#ifndef SLJIT_UNALIGNED
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
+       || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
+       || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
+       || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
+       || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
+       || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#define SLJIT_UNALIGNED 1
+#endif
+
+#endif /* !SLJIT_UNALIGNED */
+
+#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size);
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);
+#define SLJIT_MALLOC_EXEC(size) sljit_malloc_exec(size)
+#define SLJIT_FREE_EXEC(ptr) sljit_free_exec(ptr)
+#endif
+
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG) || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+#include <stdio.h>
+#endif
+
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+
+/* Feel free to redefine these two macros. */
+#ifndef SLJIT_ASSERT
+
+#define SLJIT_HALT_PROCESS() \
+       *((int*)0) = 0
+
+#define SLJIT_ASSERT(x) \
+       do { \
+               if (SLJIT_UNLIKELY(!(x))) { \
+                       printf("Assertion failed at " __FILE__ ":%d\n", __LINE__); \
+                       SLJIT_HALT_PROCESS(); \
+               } \
+       } while (0)
+
+#endif /* !SLJIT_ASSERT */
+
+#ifndef SLJIT_ASSERT_STOP
+
+#define SLJIT_ASSERT_STOP() \
+       do { \
+               printf("Should never been reached " __FILE__ ":%d\n", __LINE__); \
+               SLJIT_HALT_PROCESS(); \
+       } while (0)
+
+#endif /* !SLJIT_ASSERT_STOP */
+
+#else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
+
+#undef SLJIT_ASSERT
+#undef SLJIT_ASSERT_STOP
+
+#define SLJIT_ASSERT(x) \
+       do { } while (0)
+#define SLJIT_ASSERT_STOP() \
+       do { } while (0)
+
+#endif /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
+
+#ifndef SLJIT_COMPILE_ASSERT
+
+/* Should be improved eventually. */
+#define SLJIT_COMPILE_ASSERT(x, description) \
+       SLJIT_ASSERT(x)
+
+#endif /* !SLJIT_COMPILE_ASSERT */
+
+#endif
diff --git a/src/3rdparty/pcre/sljit/sljitExecAllocator.c b/src/3rdparty/pcre/sljit/sljitExecAllocator.c
new file mode 100644 (file)
index 0000000..f66744d
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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 simple executable memory allocator
+
+   It is assumed, that executable code blocks are usually medium (or sometimes
+   large) memory blocks, and the allocator is not too frequently called (less
+   optimized than other allocators). Thus, using it as a generic allocator is
+   not suggested.
+
+   How does it work:
+     Memory is allocated in continuous memory areas called chunks by alloc_chunk()
+     Chunk format:
+     [ block ][ block ] ... [ block ][ block terminator ]
+
+   All blocks and the block terminator is started with block_header. The block
+   header contains the size of the previous and the next block. These sizes
+   can also contain special values.
+     Block size:
+       0 - The block is a free_block, with a different size member.
+       1 - The block is a block terminator.
+       n - The block is used at the moment, and the value contains its size.
+     Previous block size:
+       0 - This is the first block of the memory chunk.
+       n - The size of the previous block.
+
+   Using these size values we can go forward or backward on the block chain.
+   The unused blocks are stored in a chain list pointed by free_blocks. This
+   list is useful if we need to find a suitable memory area when the allocator
+   is called.
+   When a block is freed, the new free block is connected to its adjacent free
+   blocks if possible.
+
+     [ free block ][ used block ][ free block ]
+   and "used block" is freed, the three blocks are connected together:
+     [           one big free block           ]
+*/
+
+/* --------------------------------------------------------------------- */
+/*  System (OS) functions                                                */
+/* --------------------------------------------------------------------- */
+
+/* 64 KByte. */
+#define CHUNK_SIZE     0x10000
+
+/*
+   alloc_chunk / free_chunk :
+     * allocate executable system memory chunks
+     * the size is always divisible by CHUNK_SIZE
+   allocator_grab_lock / allocator_release_lock :
+     * make the allocator thread safe
+     * can be empty if the OS (or the application) does not support threading
+     * only the allocator requires this lock, sljit is fully thread safe
+       as it only uses local variables
+*/
+
+#ifdef _WIN32
+
+static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
+{
+       return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+}
+
+static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
+{
+       SLJIT_UNUSED_ARG(size);
+       VirtualFree(chunk, 0, MEM_RELEASE);
+}
+
+#else
+
+#include <sys/mman.h>
+
+static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
+{
+       void* retval = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
+       return (retval != MAP_FAILED) ? retval : NULL;
+}
+
+static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
+{
+       munmap(chunk, size);
+}
+
+#endif
+
+/* --------------------------------------------------------------------- */
+/*  Common functions                                                     */
+/* --------------------------------------------------------------------- */
+
+#define CHUNK_MASK     (~(CHUNK_SIZE - 1))
+
+struct block_header {
+       sljit_uw size;
+       sljit_uw prev_size;
+};
+
+struct free_block {
+       struct block_header header;
+       struct free_block *next;
+       struct free_block *prev;
+       sljit_uw size;
+};
+
+#define AS_BLOCK_HEADER(base, offset) \
+       ((struct block_header*)(((sljit_ub*)base) + offset))
+#define AS_FREE_BLOCK(base, offset) \
+       ((struct free_block*)(((sljit_ub*)base) + offset))
+#define MEM_START(base)                ((void*)(((sljit_ub*)base) + sizeof(struct block_header)))
+#define ALIGN_SIZE(size)       (((size) + sizeof(struct block_header) + 7) & ~7)
+
+static struct free_block* free_blocks;
+static sljit_uw allocated_size;
+static sljit_uw total_size;
+
+static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size)
+{
+       free_block->header.size = 0;
+       free_block->size = size;
+
+       free_block->next = free_blocks;
+       free_block->prev = 0;
+       if (free_blocks)
+               free_blocks->prev = free_block;
+       free_blocks = free_block;
+}
+
+static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block)
+{
+       if (free_block->next)
+               free_block->next->prev = free_block->prev;
+
+       if (free_block->prev)
+               free_block->prev->next = free_block->next;
+       else {
+               SLJIT_ASSERT(free_blocks == free_block);
+               free_blocks = free_block->next;
+       }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
+{
+       struct block_header *header;
+       struct block_header *next_header;
+       struct free_block *free_block;
+       sljit_uw chunk_size;
+
+       allocator_grab_lock();
+       if (size < sizeof(struct free_block))
+               size = sizeof(struct free_block);
+       size = ALIGN_SIZE(size);
+
+       free_block = free_blocks;
+       while (free_block) {
+               if (free_block->size >= size) {
+                       chunk_size = free_block->size;
+                       if (chunk_size > size + 64) {
+                               /* We just cut a block from the end of the free block. */
+                               chunk_size -= size;
+                               free_block->size = chunk_size;
+                               header = AS_BLOCK_HEADER(free_block, chunk_size);
+                               header->prev_size = chunk_size;
+                               AS_BLOCK_HEADER(header, size)->prev_size = size;
+                       }
+                       else {
+                               sljit_remove_free_block(free_block);
+                               header = (struct block_header*)free_block;
+                               size = chunk_size;
+                       }
+                       allocated_size += size;
+                       header->size = size;
+                       allocator_release_lock();
+                       return MEM_START(header);
+               }
+               free_block = free_block->next;
+       }
+
+       chunk_size = (size + sizeof(struct block_header) + CHUNK_SIZE - 1) & CHUNK_MASK;
+       header = (struct block_header*)alloc_chunk(chunk_size);
+       PTR_FAIL_IF(!header);
+
+       chunk_size -= sizeof(struct block_header);
+       total_size += chunk_size;
+
+       header->prev_size = 0;
+       if (chunk_size > size + 64) {
+               /* Cut the allocated space into a free and a used block. */
+               allocated_size += size;
+               header->size = size;
+               chunk_size -= size;
+
+               free_block = AS_FREE_BLOCK(header, size);
+               free_block->header.prev_size = size;
+               sljit_insert_free_block(free_block, chunk_size);
+               next_header = AS_BLOCK_HEADER(free_block, chunk_size);
+       }
+       else {
+               /* All space belongs to this allocation. */
+               allocated_size += chunk_size;
+               header->size = chunk_size;
+               next_header = AS_BLOCK_HEADER(header, chunk_size);
+       }
+       next_header->size = 1;
+       next_header->prev_size = chunk_size;
+       allocator_release_lock();
+       return MEM_START(header);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
+{
+       struct block_header *header;
+       struct free_block* free_block;
+
+       allocator_grab_lock();
+       header = AS_BLOCK_HEADER(ptr, -(sljit_w)sizeof(struct block_header));
+       allocated_size -= header->size;
+
+       /* Connecting free blocks together if possible. */
+
+       /* If header->prev_size == 0, free_block will equal to header.
+          In this case, free_block->header.size will be > 0. */
+       free_block = AS_FREE_BLOCK(header, -(sljit_w)header->prev_size);
+       if (SLJIT_UNLIKELY(!free_block->header.size)) {
+               free_block->size += header->size;
+               header = AS_BLOCK_HEADER(free_block, free_block->size);
+               header->prev_size = free_block->size;
+       }
+       else {
+               free_block = (struct free_block*)header;
+               sljit_insert_free_block(free_block, header->size);
+       }
+
+       header = AS_BLOCK_HEADER(free_block, free_block->size);
+       if (SLJIT_UNLIKELY(!header->size)) {
+               free_block->size += ((struct free_block*)header)->size;
+               sljit_remove_free_block((struct free_block*)header);
+               header = AS_BLOCK_HEADER(free_block, free_block->size);
+               header->prev_size = free_block->size;
+       }
+
+       /* The whole chunk is free. */
+       if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) {
+               /* If this block is freed, we still have (allocated_size / 2) free space. */
+               if (total_size - free_block->size > (allocated_size * 3 / 2)) {
+                       total_size -= free_block->size;
+                       sljit_remove_free_block(free_block);
+                       free_chunk(free_block, free_block->size + sizeof(struct block_header));
+               }
+       }
+
+       allocator_release_lock();
+}
diff --git a/src/3rdparty/pcre/sljit/sljitLir.c b/src/3rdparty/pcre/sljit/sljitLir.c
new file mode 100644 (file)
index 0000000..c1fa5e4
--- /dev/null
@@ -0,0 +1,1594 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+#include "sljitLir.h"
+
+#define CHECK_ERROR() \
+       do { \
+               if (SLJIT_UNLIKELY(compiler->error)) \
+                       return compiler->error; \
+       } while (0)
+
+#define CHECK_ERROR_PTR() \
+       do { \
+               if (SLJIT_UNLIKELY(compiler->error)) \
+                       return NULL; \
+       } while (0)
+
+#define CHECK_ERROR_VOID() \
+       do { \
+               if (SLJIT_UNLIKELY(compiler->error)) \
+                       return; \
+       } while (0)
+
+#define FAIL_IF(expr) \
+       do { \
+               if (SLJIT_UNLIKELY(expr)) \
+                       return compiler->error; \
+       } while (0)
+
+#define PTR_FAIL_IF(expr) \
+       do { \
+               if (SLJIT_UNLIKELY(expr)) \
+                       return NULL; \
+       } while (0)
+
+#define FAIL_IF_NULL(ptr) \
+       do { \
+               if (SLJIT_UNLIKELY(!(ptr))) { \
+                       compiler->error = SLJIT_ERR_ALLOC_FAILED; \
+                       return SLJIT_ERR_ALLOC_FAILED; \
+               } \
+       } while (0)
+
+#define PTR_FAIL_IF_NULL(ptr) \
+       do { \
+               if (SLJIT_UNLIKELY(!(ptr))) { \
+                       compiler->error = SLJIT_ERR_ALLOC_FAILED; \
+                       return NULL; \
+               } \
+       } while (0)
+
+#define PTR_FAIL_WITH_EXEC_IF(ptr) \
+       do { \
+               if (SLJIT_UNLIKELY(!(ptr))) { \
+                       compiler->error = SLJIT_ERR_EX_ALLOC_FAILED; \
+                       return NULL; \
+               } \
+       } while (0)
+
+#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
+
+#define GET_OPCODE(op) \
+       ((op) & ~(SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
+
+#define GET_FLAGS(op) \
+       ((op) & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C))
+
+#define GET_ALL_FLAGS(op) \
+       ((op) & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
+
+#define BUF_SIZE       4096
+
+#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)
+#define ABUF_SIZE      2048
+#else
+#define ABUF_SIZE      4096
+#endif
+
+/* Jump flags. */
+#define JUMP_LABEL     0x1
+#define JUMP_ADDR      0x2
+/* SLJIT_REWRITABLE_JUMP is 0x1000. */
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       #define PATCH_MB        0x4
+       #define PATCH_MW        0x8
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       #define PATCH_MD        0x10
+#endif
+#endif
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+       #define IS_BL           0x4
+       #define PATCH_B         0x8
+#endif
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       #define CPOOL_SIZE      512
+#endif
+
+#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
+       #define IS_CONDITIONAL  0x04
+       #define IS_BL           0x08
+       /* cannot be encoded as branch */
+       #define B_TYPE0         0x00
+       /* conditional + imm8 */
+       #define B_TYPE1         0x10
+       /* conditional + imm20 */
+       #define B_TYPE2         0x20
+       /* IT + imm24 */
+       #define B_TYPE3         0x30
+       /* imm11 */
+       #define B_TYPE4         0x40
+       /* imm24 */
+       #define B_TYPE5         0x50
+       /* BL + imm24 */
+       #define BL_TYPE6        0x60
+       /* 0xf00 cc code for branches */
+#endif
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+       #define UNCOND_B        0x04
+       #define PATCH_B         0x08
+       #define ABSOLUTE_B      0x10
+#endif
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+       #define IS_MOVABLE      0x04
+       #define IS_JAL          0x08
+       #define IS_BIT26_COND   0x10
+       #define IS_BIT16_COND   0x20
+
+       #define IS_COND         (IS_BIT26_COND | IS_BIT16_COND)
+
+       #define PATCH_B         0x40
+       #define PATCH_J         0x80
+
+       /* instruction types */
+       #define UNMOVABLE_INS   0
+       /* 1 - 31 last destination register */
+       #define FCSR_FCC        32
+       /* no destination (i.e: store) */
+       #define MOVABLE_INS     33
+#endif
+
+#endif /* !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) */
+
+/* Utils can still be used even if SLJIT_CONFIG_UNSUPPORTED is set. */
+#include "sljitUtils.c"
+
+#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
+
+#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
+#include "sljitExecAllocator.c"
+#endif
+
+#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) && !(defined SLJIT_SSE2 && SLJIT_SSE2)
+#error SLJIT_SSE2_AUTO cannot be enabled without SLJIT_SSE2
+#endif
+
+/* --------------------------------------------------------------------- */
+/*  Public functions                                                     */
+/* --------------------------------------------------------------------- */
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || ((defined SLJIT_SSE2 && SLJIT_SSE2) && ((defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)))
+#define SLJIT_NEEDS_COMPILER_INIT 1
+static int compiler_initialized = 0;
+/* A thread safe initialization. */
+static void init_compiler(void);
+#endif
+
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void)
+{
+       struct sljit_compiler *compiler = (struct sljit_compiler*)SLJIT_MALLOC(sizeof(struct sljit_compiler));
+       if (!compiler)
+               return NULL;
+       SLJIT_ZEROMEM(compiler, sizeof(struct sljit_compiler));
+
+       SLJIT_COMPILE_ASSERT(
+               sizeof(sljit_b) == 1 && sizeof(sljit_ub) == 1
+               && sizeof(sljit_h) == 2 && sizeof(sljit_uh) == 2
+               && sizeof(sljit_i) == 4 && sizeof(sljit_ui) == 4
+               && ((sizeof(sljit_w) == 4 && sizeof(sljit_uw) == 4) || (sizeof(sljit_w) == 8 && sizeof(sljit_uw) == 8)),
+               invalid_integer_types);
+
+       /* Only the non-zero members must be set. */
+       compiler->error = SLJIT_SUCCESS;
+
+       compiler->buf = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE);
+       compiler->abuf = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE);
+
+       if (!compiler->buf || !compiler->abuf) {
+               if (compiler->buf)
+                       SLJIT_FREE(compiler->buf);
+               if (compiler->abuf)
+                       SLJIT_FREE(compiler->abuf);
+               SLJIT_FREE(compiler);
+               return NULL;
+       }
+
+       compiler->buf->next = NULL;
+       compiler->buf->used_size = 0;
+       compiler->abuf->next = NULL;
+       compiler->abuf->used_size = 0;
+
+       compiler->temporaries = -1;
+       compiler->saveds = -1;
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       compiler->args = -1;
+#endif
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       compiler->cpool = (sljit_uw*)SLJIT_MALLOC(CPOOL_SIZE * sizeof(sljit_uw) + CPOOL_SIZE * sizeof(sljit_ub));
+       if (!compiler->cpool) {
+               SLJIT_FREE(compiler->buf);
+               SLJIT_FREE(compiler->abuf);
+               SLJIT_FREE(compiler);
+               return NULL;
+       }
+       compiler->cpool_unique = (sljit_ub*)(compiler->cpool + CPOOL_SIZE);
+       compiler->cpool_diff = 0xffffffff;
+#endif
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+       compiler->delay_slot = UNMOVABLE_INS;
+#endif
+
+#if (defined SLJIT_NEEDS_COMPILER_INIT && SLJIT_NEEDS_COMPILER_INIT)
+       if (!compiler_initialized) {
+               init_compiler();
+               compiler_initialized = 1;
+       }
+#endif
+
+       return compiler;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler)
+{
+       struct sljit_memory_fragment *buf;
+       struct sljit_memory_fragment *curr;
+
+       buf = compiler->buf;
+       while (buf) {
+               curr = buf;
+               buf = buf->next;
+               SLJIT_FREE(curr);
+       }
+
+       buf = compiler->abuf;
+       while (buf) {
+               curr = buf;
+               buf = buf->next;
+               SLJIT_FREE(curr);
+       }
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       SLJIT_FREE(compiler->cpool);
+#endif
+       SLJIT_FREE(compiler);
+}
+
+#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
+{
+       /* Remove thumb mode flag. */
+       SLJIT_FREE_EXEC((void*)((sljit_uw)code & ~0x1));
+}
+#elif (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
+{
+       /* Resolve indirection. */
+       code = (void*)(*(sljit_uw*)code);
+       SLJIT_FREE_EXEC(code);
+}
+#else
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
+{
+       SLJIT_FREE_EXEC(code);
+}
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label)
+{
+       if (SLJIT_LIKELY(!!jump) && SLJIT_LIKELY(!!label)) {
+               jump->flags &= ~JUMP_ADDR;
+               jump->flags |= JUMP_LABEL;
+               jump->u.label = label;
+       }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target)
+{
+       if (SLJIT_LIKELY(!!jump)) {
+               SLJIT_ASSERT(jump->flags & SLJIT_REWRITABLE_JUMP);
+
+               jump->flags &= ~JUMP_LABEL;
+               jump->flags |= JUMP_ADDR;
+               jump->u.target = target;
+       }
+}
+
+/* --------------------------------------------------------------------- */
+/*  Private functions                                                    */
+/* --------------------------------------------------------------------- */
+
+static void* ensure_buf(struct sljit_compiler *compiler, int size)
+{
+       sljit_ub *ret;
+       struct sljit_memory_fragment *new_frag;
+
+       if (compiler->buf->used_size + size <= (int)(BUF_SIZE - sizeof(sljit_uw) - sizeof(void*))) {
+               ret = compiler->buf->memory + compiler->buf->used_size;
+               compiler->buf->used_size += size;
+               return ret;
+       }
+       new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE);
+       PTR_FAIL_IF_NULL(new_frag);
+       new_frag->next = compiler->buf;
+       compiler->buf = new_frag;
+       new_frag->used_size = size;
+       return new_frag->memory;
+}
+
+static void* ensure_abuf(struct sljit_compiler *compiler, int size)
+{
+       sljit_ub *ret;
+       struct sljit_memory_fragment *new_frag;
+
+       if (compiler->abuf->used_size + size <= (int)(ABUF_SIZE - sizeof(sljit_uw) - sizeof(void*))) {
+               ret = compiler->abuf->memory + compiler->abuf->used_size;
+               compiler->abuf->used_size += size;
+               return ret;
+       }
+       new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE);
+       PTR_FAIL_IF_NULL(new_frag);
+       new_frag->next = compiler->abuf;
+       compiler->abuf = new_frag;
+       new_frag->used_size = size;
+       return new_frag->memory;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, int size)
+{
+       CHECK_ERROR_PTR();
+
+#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
+       if (size <= 0 || size > 128)
+               return NULL;
+       size = (size + 7) & ~7;
+#else
+       if (size <= 0 || size > 64)
+               return NULL;
+       size = (size + 3) & ~3;
+#endif
+       return ensure_abuf(compiler, size);
+}
+
+static SLJIT_INLINE void reverse_buf(struct sljit_compiler *compiler)
+{
+       struct sljit_memory_fragment *buf = compiler->buf;
+       struct sljit_memory_fragment *prev = NULL;
+       struct sljit_memory_fragment *tmp;
+
+       do {
+               tmp = buf->next;
+               buf->next = prev;
+               prev = buf;
+               buf = tmp;
+       } while (buf != NULL);
+
+       compiler->buf = prev;
+}
+
+static SLJIT_INLINE void set_label(struct sljit_label *label, struct sljit_compiler *compiler)
+{
+       label->next = NULL;
+       label->size = compiler->size;
+       if (compiler->last_label)
+               compiler->last_label->next = label;
+       else
+               compiler->labels = label;
+       compiler->last_label = label;
+}
+
+static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, int flags)
+{
+       jump->next = NULL;
+       jump->flags = flags;
+       if (compiler->last_jump)
+               compiler->last_jump->next = jump;
+       else
+               compiler->jumps = jump;
+       compiler->last_jump = jump;
+}
+
+static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_compiler *compiler)
+{
+       const_->next = NULL;
+       const_->addr = compiler->size;
+       if (compiler->last_const)
+               compiler->last_const->next = const_;
+       else
+               compiler->consts = const_;
+       compiler->last_const = const_;
+}
+
+#define ADDRESSING_DEPENDS_ON(exp, reg) \
+       (((exp) & SLJIT_MEM) && (((exp) & 0xf) == reg || (((exp) >> 4) & 0xf) == reg))
+
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+#define FUNCTION_CHECK_OP() \
+       SLJIT_ASSERT(!GET_FLAGS(op) || !(op & SLJIT_KEEP_FLAGS)); \
+       switch (GET_OPCODE(op)) { \
+       case SLJIT_NOT: \
+       case SLJIT_CLZ: \
+       case SLJIT_AND: \
+       case SLJIT_OR: \
+       case SLJIT_XOR: \
+       case SLJIT_SHL: \
+       case SLJIT_LSHR: \
+       case SLJIT_ASHR: \
+               SLJIT_ASSERT(!(op & (SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C))); \
+               break; \
+       case SLJIT_NEG: \
+               SLJIT_ASSERT(!(op & (SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_C))); \
+               break; \
+       case SLJIT_MUL: \
+               SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_C))); \
+               break; \
+       case SLJIT_FCMP: \
+               SLJIT_ASSERT(!(op & (SLJIT_INT_OP | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
+               SLJIT_ASSERT((op & (SLJIT_SET_E | SLJIT_SET_S))); \
+               break; \
+       case SLJIT_ADD: \
+               SLJIT_ASSERT(!(op & (SLJIT_SET_S | SLJIT_SET_U))); \
+               break; \
+       case SLJIT_SUB: \
+               break; \
+       case SLJIT_ADDC: \
+       case SLJIT_SUBC: \
+               SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O))); \
+               break; \
+       default: \
+               /* Nothing allowed */ \
+               SLJIT_ASSERT(!(op & (SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
+               break; \
+       }
+
+#define FUNCTION_CHECK_IS_REG(r) \
+       ((r) == SLJIT_UNUSED || (r) == SLJIT_LOCALS_REG || \
+       ((r) >= SLJIT_TEMPORARY_REG1 && (r) <= SLJIT_TEMPORARY_REG3 && (r) <= SLJIT_TEMPORARY_REG1 - 1 + compiler->temporaries) || \
+       ((r) >= SLJIT_SAVED_REG1 && (r) <= SLJIT_SAVED_REG3 && (r) <= SLJIT_SAVED_REG1 - 1 + compiler->saveds)) \
+
+#define FUNCTION_CHECK_SRC(p, i) \
+       SLJIT_ASSERT(compiler->temporaries != -1 && compiler->saveds != -1); \
+       if (((p) >= SLJIT_TEMPORARY_REG1 && (p) <= SLJIT_TEMPORARY_REG1 - 1 + compiler->temporaries) || \
+                       ((p) >= SLJIT_SAVED_REG1 && (p) <= SLJIT_SAVED_REG1 - 1 + compiler->saveds) || \
+                       (p) == SLJIT_LOCALS_REG) \
+               SLJIT_ASSERT(i == 0); \
+       else if ((p) == SLJIT_IMM) \
+               ; \
+       else if ((p) & SLJIT_MEM) { \
+               SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & 0xf)); \
+               if ((p) & 0xf0) { \
+                       SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(((p) >> 4) & 0xf)); \
+                       SLJIT_ASSERT(((p) & 0xf0) != (SLJIT_LOCALS_REG << 4) && !(i & ~0x3)); \
+               } else \
+                       SLJIT_ASSERT((((p) >> 4) & 0xf) == 0); \
+               SLJIT_ASSERT(((p) >> 9) == 0); \
+       } \
+       else \
+               SLJIT_ASSERT_STOP();
+
+#define FUNCTION_CHECK_DST(p, i) \
+       SLJIT_ASSERT(compiler->temporaries != -1 && compiler->saveds != -1); \
+       if (((p) >= SLJIT_TEMPORARY_REG1 && (p) <= SLJIT_TEMPORARY_REG1 - 1 + compiler->temporaries) || \
+                       ((p) >= SLJIT_SAVED_REG1 && (p) <= SLJIT_SAVED_REG1 - 1 + compiler->saveds) || \
+                       (p) == SLJIT_UNUSED) \
+               SLJIT_ASSERT(i == 0); \
+       else if ((p) & SLJIT_MEM) { \
+               SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & 0xf)); \
+               if ((p) & 0xf0) { \
+                       SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(((p) >> 4) & 0xf)); \
+                       SLJIT_ASSERT(((p) & 0xf0) != (SLJIT_LOCALS_REG << 4) && !(i & ~0x3)); \
+               } else \
+                       SLJIT_ASSERT((((p) >> 4) & 0xf) == 0); \
+               SLJIT_ASSERT(((p) >> 9) == 0); \
+       } \
+       else \
+               SLJIT_ASSERT_STOP();
+
+#define FUNCTION_FCHECK(p, i) \
+       if ((p) >= SLJIT_FLOAT_REG1 && (p) <= SLJIT_FLOAT_REG4) \
+               SLJIT_ASSERT(i == 0); \
+       else if ((p) & SLJIT_MEM) { \
+               SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & 0xf)); \
+               if ((p) & 0xf0) { \
+                       SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(((p) >> 4) & 0xf)); \
+                       SLJIT_ASSERT(((p) & 0xf0) != (SLJIT_LOCALS_REG << 4) && !(i & ~0x3)); \
+               } else \
+                       SLJIT_ASSERT((((p) >> 4) & 0xf) == 0); \
+               SLJIT_ASSERT(((p) >> 9) == 0); \
+       } \
+       else \
+               SLJIT_ASSERT_STOP();
+
+#define FUNCTION_CHECK_OP1() \
+       if (GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI) { \
+               SLJIT_ASSERT(!GET_ALL_FLAGS(op)); \
+       } \
+        if (GET_OPCODE(op) >= SLJIT_MOVU && GET_OPCODE(op) <= SLJIT_MOVU_SI) { \
+               SLJIT_ASSERT(!(src & SLJIT_MEM) || (src & 0xf) != SLJIT_LOCALS_REG); \
+               SLJIT_ASSERT(!(dst & SLJIT_MEM) || (dst & 0xf) != SLJIT_LOCALS_REG); \
+               if ((src & SLJIT_MEM) && (src & 0xf)) \
+                       SLJIT_ASSERT((dst & 0xf) != (src & 0xf) && ((dst >> 4) & 0xf) != (src & 0xf)); \
+       }
+
+#endif
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose)
+{
+       compiler->verbose = verbose;
+}
+
+static char* reg_names[] = {
+       (char*)"<noreg>", (char*)"t1", (char*)"t2", (char*)"t3",
+       (char*)"te1", (char*)"te2", (char*)"s1", (char*)"s2",
+       (char*)"s3", (char*)"se1", (char*)"se2", (char*)"lcr"
+};
+
+static char* freg_names[] = {
+       (char*)"<noreg>", (char*)"float_r1", (char*)"float_r2", (char*)"float_r3", (char*)"float_r4"
+};
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#ifdef _WIN64
+       #define SLJIT_PRINT_D   "I64"
+#else
+       #define SLJIT_PRINT_D   "l"
+#endif
+#else
+       #define SLJIT_PRINT_D   ""
+#endif
+
+#define sljit_verbose_param(p, i) \
+       if ((p) & SLJIT_IMM) \
+               fprintf(compiler->verbose, "#%"SLJIT_PRINT_D"d", (i)); \
+       else if ((p) & SLJIT_MEM) { \
+               if ((p) & 0xf) { \
+                       if (i) { \
+                               if (((p) >> 4) & 0xf) \
+                                       fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF], 1 << (i)); \
+                               else \
+                                       fprintf(compiler->verbose, "[%s + #%"SLJIT_PRINT_D"d]", reg_names[(p) & 0xF], (i)); \
+                       } \
+                       else { \
+                               if (((p) >> 4) & 0xf) \
+                                       fprintf(compiler->verbose, "[%s + %s]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF]); \
+                               else \
+                                       fprintf(compiler->verbose, "[%s]", reg_names[(p) & 0xF]); \
+                       } \
+               } \
+               else \
+                       fprintf(compiler->verbose, "[#%"SLJIT_PRINT_D"d]", (i)); \
+       } else \
+               fprintf(compiler->verbose, "%s", reg_names[p]);
+#define sljit_verbose_fparam(p, i) \
+       if ((p) & SLJIT_MEM) { \
+               if ((p) & 0xf) { \
+                       if (i) { \
+                               if (((p) >> 4) & 0xf) \
+                                       fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF], 1 << (i)); \
+                               else \
+                                       fprintf(compiler->verbose, "[%s + #%"SLJIT_PRINT_D"d]", reg_names[(p) & 0xF], (i)); \
+                       } \
+                       else { \
+                               if (((p) >> 4) & 0xF) \
+                                       fprintf(compiler->verbose, "[%s + %s]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF]); \
+                               else \
+                                       fprintf(compiler->verbose, "[%s]", reg_names[(p) & 0xF]); \
+                       } \
+               } \
+               else \
+                       fprintf(compiler->verbose, "[#%"SLJIT_PRINT_D"d]", (i)); \
+       } else \
+               fprintf(compiler->verbose, "%s", freg_names[p]);
+
+static SLJIT_CONST char* op_names[] = {
+       /* op0 */
+       (char*)"breakpoint", (char*)"nop",
+       (char*)"umul", (char*)"smul", (char*)"udiv", (char*)"sdiv",
+       /* op1 */
+       (char*)"mov", (char*)"mov.ub", (char*)"mov.sb", (char*)"mov.uh",
+       (char*)"mov.sh", (char*)"mov.ui", (char*)"mov.si", (char*)"movu",
+       (char*)"movu.ub", (char*)"movu.sb", (char*)"movu.uh", (char*)"movu.sh",
+       (char*)"movu.ui", (char*)"movu.si", (char*)"not", (char*)"neg",
+       (char*)"clz",
+       /* op2 */
+       (char*)"add", (char*)"addc", (char*)"sub", (char*)"subc",
+       (char*)"mul", (char*)"and", (char*)"or", (char*)"xor",
+       (char*)"shl", (char*)"lshr", (char*)"ashr",
+       /* fop1 */
+       (char*)"fcmp", (char*)"fmov", (char*)"fneg", (char*)"fabs",
+       /* fop2 */
+       (char*)"fadd", (char*)"fsub", (char*)"fmul", (char*)"fdiv"
+};
+
+static char* jump_names[] = {
+       (char*)"c_equal", (char*)"c_not_equal",
+       (char*)"c_less", (char*)"c_greater_equal",
+       (char*)"c_greater", (char*)"c_less_equal",
+       (char*)"c_sig_less", (char*)"c_sig_greater_equal",
+       (char*)"c_sig_greater", (char*)"c_sig_less_equal",
+       (char*)"c_overflow", (char*)"c_not_overflow",
+       (char*)"c_mul_overflow", (char*)"c_mul_not_overflow",
+       (char*)"c_float_equal", (char*)"c_float_not_equal",
+       (char*)"c_float_less", (char*)"c_float_greater_equal",
+       (char*)"c_float_greater", (char*)"c_float_less_equal",
+       (char*)"c_float_nan", (char*)"c_float_not_nan",
+       (char*)"jump", (char*)"fast_call",
+       (char*)"call0", (char*)"call1", (char*)"call2", (char*)"call3"
+};
+
+#endif
+
+/* --------------------------------------------------------------------- */
+/*  Arch dependent                                                       */
+/* --------------------------------------------------------------------- */
+
+static SLJIT_INLINE void check_sljit_generate_code(struct sljit_compiler *compiler)
+{
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       struct sljit_jump *jump;
+#endif
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+
+       SLJIT_ASSERT(compiler->size > 0);
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       jump = compiler->jumps;
+       while (jump) {
+               /* All jumps have target. */
+               SLJIT_ASSERT(jump->flags & (JUMP_LABEL | JUMP_ADDR));
+               jump = jump->next;
+       }
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(args);
+       SLJIT_UNUSED_ARG(temporaries);
+       SLJIT_UNUSED_ARG(saveds);
+       SLJIT_UNUSED_ARG(local_size);
+
+       SLJIT_ASSERT(args >= 0 && args <= 3);
+       SLJIT_ASSERT(temporaries >= 0 && temporaries <= SLJIT_NO_TMP_REGISTERS);
+       SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NO_GEN_REGISTERS);
+       SLJIT_ASSERT(args <= saveds);
+       SLJIT_ASSERT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose))
+               fprintf(compiler->verbose, "  enter args=%d temporaries=%d saveds=%d local_size=%d\n", args, temporaries, saveds, local_size);
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(args);
+       SLJIT_UNUSED_ARG(temporaries);
+       SLJIT_UNUSED_ARG(saveds);
+       SLJIT_UNUSED_ARG(local_size);
+
+       SLJIT_ASSERT(args >= 0 && args <= 3);
+       SLJIT_ASSERT(temporaries >= 0 && temporaries <= SLJIT_NO_TMP_REGISTERS);
+       SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NO_GEN_REGISTERS);
+       SLJIT_ASSERT(args <= saveds);
+       SLJIT_ASSERT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose))
+               fprintf(compiler->verbose, "  fake_enter args=%d temporaries=%d saveds=%d local_size=%d\n", args, temporaries, saveds, local_size);
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+{
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(op);
+       SLJIT_UNUSED_ARG(src);
+       SLJIT_UNUSED_ARG(srcw);
+
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       if (op != SLJIT_UNUSED) {
+               SLJIT_ASSERT(op >= SLJIT_MOV && op <= SLJIT_MOV_SI);
+               FUNCTION_CHECK_SRC(src, srcw);
+       }
+       else
+               SLJIT_ASSERT(src == 0 && srcw == 0);
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+               if (op == SLJIT_UNUSED)
+                       fprintf(compiler->verbose, "  return\n");
+               else {
+                       fprintf(compiler->verbose, "  return %s ", op_names[op]);
+                       sljit_verbose_param(src, srcw);
+                       fprintf(compiler->verbose, "\n");
+               }
+       }
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
+{
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(dst);
+       SLJIT_UNUSED_ARG(dstw);
+       SLJIT_UNUSED_ARG(args);
+       SLJIT_UNUSED_ARG(temporaries);
+       SLJIT_UNUSED_ARG(saveds);
+       SLJIT_UNUSED_ARG(local_size);
+
+       SLJIT_ASSERT(args >= 0 && args <= 3);
+       SLJIT_ASSERT(temporaries >= 0 && temporaries <= SLJIT_NO_TMP_REGISTERS);
+       SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NO_GEN_REGISTERS);
+       SLJIT_ASSERT(args <= saveds);
+       SLJIT_ASSERT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+       FUNCTION_CHECK_DST(dst, dstw);
+       compiler->temporaries = -1;
+       compiler->saveds = -1;
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+               fprintf(compiler->verbose, "  fast_enter ");
+               sljit_verbose_param(dst, dstw);
+               fprintf(compiler->verbose, " args=%d temporaries=%d saveds=%d local_size=%d\n", args, temporaries, saveds, local_size);
+       }
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+{
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(src);
+       SLJIT_UNUSED_ARG(srcw);
+
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       FUNCTION_CHECK_SRC(src, srcw);
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+               fprintf(compiler->verbose, "  fast_return ");
+               sljit_verbose_param(src, srcw);
+               fprintf(compiler->verbose, "\n");
+       }
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_op0(struct sljit_compiler *compiler, int op)
+{
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(op);
+
+       SLJIT_ASSERT((op >= SLJIT_BREAKPOINT && op <= SLJIT_SMUL)
+               || ((op & ~SLJIT_INT_OP) >= SLJIT_UDIV && (op & ~SLJIT_INT_OP) <= SLJIT_SDIV));
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose))
+               fprintf(compiler->verbose, "  %s%s\n", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)]);
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_op1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(op);
+       SLJIT_UNUSED_ARG(dst);
+       SLJIT_UNUSED_ARG(dstw);
+       SLJIT_UNUSED_ARG(src);
+       SLJIT_UNUSED_ARG(srcw);
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+               compiler->skip_checks = 0;
+               return;
+       }
+#endif
+
+       SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_CLZ);
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       FUNCTION_CHECK_OP();
+       FUNCTION_CHECK_SRC(src, srcw);
+       FUNCTION_CHECK_DST(dst, dstw);
+       FUNCTION_CHECK_OP1();
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+               fprintf(compiler->verbose, "  %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)],
+                       !(op & SLJIT_SET_E) ? "" : "E", !(op & SLJIT_SET_S) ? "" : "S", !(op & SLJIT_SET_U) ? "" : "U", !(op & SLJIT_SET_O) ? "" : "O", !(op & SLJIT_SET_C) ? "" : "C", !(op & SLJIT_KEEP_FLAGS) ? "" : "K");
+               sljit_verbose_param(dst, dstw);
+               fprintf(compiler->verbose, ", ");
+               sljit_verbose_param(src, srcw);
+               fprintf(compiler->verbose, "\n");
+       }
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_op2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(op);
+       SLJIT_UNUSED_ARG(dst);
+       SLJIT_UNUSED_ARG(dstw);
+       SLJIT_UNUSED_ARG(src1);
+       SLJIT_UNUSED_ARG(src1w);
+       SLJIT_UNUSED_ARG(src2);
+       SLJIT_UNUSED_ARG(src2w);
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+               compiler->skip_checks = 0;
+               return;
+       }
+#endif
+
+       SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_ADD && GET_OPCODE(op) <= SLJIT_ASHR);
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       FUNCTION_CHECK_OP();
+       FUNCTION_CHECK_SRC(src1, src1w);
+       FUNCTION_CHECK_SRC(src2, src2w);
+       FUNCTION_CHECK_DST(dst, dstw);
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+               fprintf(compiler->verbose, "  %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)],
+                       !(op & SLJIT_SET_E) ? "" : "E", !(op & SLJIT_SET_S) ? "" : "S", !(op & SLJIT_SET_U) ? "" : "U", !(op & SLJIT_SET_O) ? "" : "O", !(op & SLJIT_SET_C) ? "" : "C", !(op & SLJIT_KEEP_FLAGS) ? "" : "K");
+               sljit_verbose_param(dst, dstw);
+               fprintf(compiler->verbose, ", ");
+               sljit_verbose_param(src1, src1w);
+               fprintf(compiler->verbose, ", ");
+               sljit_verbose_param(src2, src2w);
+               fprintf(compiler->verbose, "\n");
+       }
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_get_register_index(int reg)
+{
+       SLJIT_UNUSED_ARG(reg);
+       SLJIT_ASSERT(reg > 0 && reg <= SLJIT_NO_REGISTERS);
+}
+
+static SLJIT_INLINE void check_sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, int size)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(instruction);
+       SLJIT_UNUSED_ARG(size);
+       SLJIT_ASSERT(instruction);
+}
+
+static SLJIT_INLINE void check_sljit_emit_fop1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(op);
+       SLJIT_UNUSED_ARG(dst);
+       SLJIT_UNUSED_ARG(dstw);
+       SLJIT_UNUSED_ARG(src);
+       SLJIT_UNUSED_ARG(srcw);
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+               compiler->skip_checks = 0;
+               return;
+       }
+#endif
+
+       SLJIT_ASSERT(sljit_is_fpu_available());
+       SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_FCMP && GET_OPCODE(op) <= SLJIT_FABS);
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       FUNCTION_CHECK_OP();
+       FUNCTION_FCHECK(src, srcw);
+       FUNCTION_FCHECK(dst, dstw);
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+               fprintf(compiler->verbose, "  %s%s%s ", op_names[GET_OPCODE(op)],
+                       !(op & SLJIT_SET_E) ? "" : "E", !(op & SLJIT_SET_S) ? "" : "S");
+               sljit_verbose_fparam(dst, dstw);
+               fprintf(compiler->verbose, ", ");
+               sljit_verbose_fparam(src, srcw);
+               fprintf(compiler->verbose, "\n");
+       }
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_fop2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(op);
+       SLJIT_UNUSED_ARG(dst);
+       SLJIT_UNUSED_ARG(dstw);
+       SLJIT_UNUSED_ARG(src1);
+       SLJIT_UNUSED_ARG(src1w);
+       SLJIT_UNUSED_ARG(src2);
+       SLJIT_UNUSED_ARG(src2w);
+
+       SLJIT_ASSERT(sljit_is_fpu_available());
+       SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_FADD && GET_OPCODE(op) <= SLJIT_FDIV);
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       FUNCTION_CHECK_OP();
+       FUNCTION_FCHECK(src1, src1w);
+       FUNCTION_FCHECK(src2, src2w);
+       FUNCTION_FCHECK(dst, dstw);
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+               fprintf(compiler->verbose, "  %s ", op_names[GET_OPCODE(op)]);
+               sljit_verbose_fparam(dst, dstw);
+               fprintf(compiler->verbose, ", ");
+               sljit_verbose_fparam(src1, src1w);
+               fprintf(compiler->verbose, ", ");
+               sljit_verbose_fparam(src2, src2w);
+               fprintf(compiler->verbose, "\n");
+       }
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_label(struct sljit_compiler *compiler)
+{
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose))
+               fprintf(compiler->verbose, "label:\n");
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_jump(struct sljit_compiler *compiler, int type)
+{
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(type);
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+               compiler->skip_checks = 0;
+               return;
+       }
+#endif
+
+       SLJIT_ASSERT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP)));
+       SLJIT_ASSERT((type & 0xff) >= SLJIT_C_EQUAL && (type & 0xff) <= SLJIT_CALL3);
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose))
+               fprintf(compiler->verbose, "  jump%s <%s>\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : "R", jump_names[type & 0xff]);
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_cmp(struct sljit_compiler *compiler, int type,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(type);
+       SLJIT_UNUSED_ARG(src1);
+       SLJIT_UNUSED_ARG(src1w);
+       SLJIT_UNUSED_ARG(src2);
+       SLJIT_UNUSED_ARG(src2w);
+
+       SLJIT_ASSERT(!(type & ~(0xff | SLJIT_INT_OP | SLJIT_REWRITABLE_JUMP)));
+       SLJIT_ASSERT((type & 0xff) >= SLJIT_C_EQUAL && (type & 0xff) <= SLJIT_C_SIG_LESS_EQUAL);
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       FUNCTION_CHECK_SRC(src1, src1w);
+       FUNCTION_CHECK_SRC(src2, src2w);
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+               fprintf(compiler->verbose, "  %scmp%s <%s> ", !(type & SLJIT_INT_OP) ? "" : "i", !(type & SLJIT_REWRITABLE_JUMP) ? "" : "R", jump_names[type & 0xff]);
+               sljit_verbose_param(src1, src1w);
+               fprintf(compiler->verbose, ", ");
+               sljit_verbose_param(src2, src2w);
+               fprintf(compiler->verbose, "\n");
+       }
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(type);
+       SLJIT_UNUSED_ARG(src1);
+       SLJIT_UNUSED_ARG(src1w);
+       SLJIT_UNUSED_ARG(src2);
+       SLJIT_UNUSED_ARG(src2w);
+
+       SLJIT_ASSERT(sljit_is_fpu_available());
+       SLJIT_ASSERT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP)));
+       SLJIT_ASSERT((type & 0xff) >= SLJIT_C_FLOAT_EQUAL && (type & 0xff) <= SLJIT_C_FLOAT_NOT_NAN);
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       FUNCTION_FCHECK(src1, src1w);
+       FUNCTION_FCHECK(src2, src2w);
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+               fprintf(compiler->verbose, "  fcmp%s <%s> ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : "R", jump_names[type & 0xff]);
+               sljit_verbose_fparam(src1, src1w);
+               fprintf(compiler->verbose, ", ");
+               sljit_verbose_fparam(src2, src2w);
+               fprintf(compiler->verbose, "\n");
+       }
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
+{
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(type);
+       SLJIT_UNUSED_ARG(src);
+       SLJIT_UNUSED_ARG(srcw);
+
+       SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL3);
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       FUNCTION_CHECK_SRC(src, srcw);
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+               fprintf(compiler->verbose, "  ijump <%s> ", jump_names[type]);
+               sljit_verbose_param(src, srcw);
+               fprintf(compiler->verbose, "\n");
+       }
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type)
+{
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(op);
+       SLJIT_UNUSED_ARG(dst);
+       SLJIT_UNUSED_ARG(dstw);
+       SLJIT_UNUSED_ARG(type);
+
+       SLJIT_ASSERT(type >= SLJIT_C_EQUAL && type < SLJIT_JUMP);
+       SLJIT_ASSERT(op == SLJIT_MOV || GET_OPCODE(op) == SLJIT_OR);
+       SLJIT_ASSERT(GET_ALL_FLAGS(op) == 0 || GET_ALL_FLAGS(op) == SLJIT_SET_E || GET_ALL_FLAGS(op) == SLJIT_KEEP_FLAGS);
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       FUNCTION_CHECK_DST(dst, dstw);
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+               fprintf(compiler->verbose, "  cond_set%s%s <%s> ", !(op & SLJIT_SET_E) ? "" : "E",
+                       !(op & SLJIT_KEEP_FLAGS) ? "" : "K", op_names[GET_OPCODE(op)]);
+               sljit_verbose_param(dst, dstw);
+               fprintf(compiler->verbose, ", <%s>\n", jump_names[type]);
+       }
+#endif
+}
+
+static SLJIT_INLINE void check_sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value)
+{
+       /* If debug and verbose are disabled, all arguments are unused. */
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(dst);
+       SLJIT_UNUSED_ARG(dstw);
+       SLJIT_UNUSED_ARG(init_value);
+
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       FUNCTION_CHECK_DST(dst, dstw);
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+               fprintf(compiler->verbose, "  const ");
+               sljit_verbose_param(dst, dstw);
+               fprintf(compiler->verbose, ", #%"SLJIT_PRINT_D"d\n", init_value);
+       }
+#endif
+}
+
+static SLJIT_INLINE int emit_mov_before_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+{
+       /* Return if don't need to do anything. */
+       if (op == SLJIT_UNUSED)
+               return SLJIT_SUCCESS;
+
+#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
+       if (src == SLJIT_RETURN_REG && op == SLJIT_MOV)
+               return SLJIT_SUCCESS;
+#else
+       if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_UI || op == SLJIT_MOV_SI))
+               return SLJIT_SUCCESS;
+#endif
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       compiler->skip_checks = 1;
+#endif
+       return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw);
+}
+
+/* CPU description section */
+
+#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)
+#define SLJIT_CPUINFO_PART1 " 32bit ("
+#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
+#define SLJIT_CPUINFO_PART1 " 64bit ("
+#else
+#error "Internal error: CPU type info missing"
+#endif
+
+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
+#define SLJIT_CPUINFO_PART2 "little endian + "
+#elif (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN)
+#define SLJIT_CPUINFO_PART2 "big endian + "
+#else
+#error "Internal error: CPU type info missing"
+#endif
+
+#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED)
+#define SLJIT_CPUINFO_PART3 "unaligned)"
+#else
+#define SLJIT_CPUINFO_PART3 "aligned)"
+#endif
+
+#define SLJIT_CPUINFO SLJIT_CPUINFO_PART1 SLJIT_CPUINFO_PART2 SLJIT_CPUINFO_PART3
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       #include "sljitNativeX86_common.c"
+#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       #include "sljitNativeX86_common.c"
+#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       #include "sljitNativeARM_v5.c"
+#elif (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+       #include "sljitNativeARM_v5.c"
+#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
+       #include "sljitNativeARM_Thumb2.c"
+#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+       #include "sljitNativePPC_common.c"
+#elif (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+       #include "sljitNativePPC_common.c"
+#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+       #include "sljitNativeMIPS_common.c"
+#endif
+
+#if !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, int type,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       /* Default compare for most architectures. */
+       int flags, tmp_src, condition;
+       sljit_w tmp_srcw;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w);
+
+       condition = type & 0xff;
+       if (SLJIT_UNLIKELY((src1 & SLJIT_IMM) && !(src2 & SLJIT_IMM))) {
+               /* Immediate is prefered as second argument by most architectures. */
+               switch (condition) {
+               case SLJIT_C_LESS:
+                       condition = SLJIT_C_GREATER;
+                       break;
+               case SLJIT_C_GREATER_EQUAL:
+                       condition = SLJIT_C_LESS_EQUAL;
+                       break;
+               case SLJIT_C_GREATER:
+                       condition = SLJIT_C_LESS;
+                       break;
+               case SLJIT_C_LESS_EQUAL:
+                       condition = SLJIT_C_GREATER_EQUAL;
+                       break;
+               case SLJIT_C_SIG_LESS:
+                       condition = SLJIT_C_SIG_GREATER;
+                       break;
+               case SLJIT_C_SIG_GREATER_EQUAL:
+                       condition = SLJIT_C_SIG_LESS_EQUAL;
+                       break;
+               case SLJIT_C_SIG_GREATER:
+                       condition = SLJIT_C_SIG_LESS;
+                       break;
+               case SLJIT_C_SIG_LESS_EQUAL:
+                       condition = SLJIT_C_SIG_GREATER_EQUAL;
+                       break;
+               }
+               type = condition | (type & (SLJIT_INT_OP | SLJIT_REWRITABLE_JUMP));
+               tmp_src = src1;
+               src1 = src2;
+               src2 = tmp_src;
+               tmp_srcw = src1w;
+               src1w = src2w;
+               src2w = tmp_srcw;
+       }
+
+       if (condition <= SLJIT_C_NOT_ZERO)
+               flags = SLJIT_SET_E;
+       else if (condition <= SLJIT_C_LESS_EQUAL)
+               flags = SLJIT_SET_U;
+       else
+               flags = SLJIT_SET_S;
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       compiler->skip_checks = 1;
+#endif
+       PTR_FAIL_IF(sljit_emit_op2(compiler, SLJIT_SUB | flags | (type & SLJIT_INT_OP),
+               SLJIT_UNUSED, 0, src1, src1w, src2, src2w));
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       compiler->skip_checks = 1;
+#endif
+       return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       int flags, condition;
+
+       check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w);
+
+       condition = type & 0xff;
+       if (condition <= SLJIT_C_FLOAT_NOT_EQUAL)
+               flags = SLJIT_SET_E;
+       else
+               flags = SLJIT_SET_S;
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       compiler->skip_checks = 1;
+#endif
+       sljit_emit_fop1(compiler, SLJIT_FCMP | flags, src1, src1w, src2, src2w);
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       compiler->skip_checks = 1;
+#endif
+       return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP));
+}
+
+#endif
+
+#else /* SLJIT_CONFIG_UNSUPPORTED */
+
+/* Empty function bodies for those machines, which are not (yet) supported. */
+
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
+{
+       return "unsupported";
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void)
+{
+       SLJIT_ASSERT_STOP();
+       return NULL;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_ASSERT_STOP();
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, int size)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(size);
+       SLJIT_ASSERT_STOP();
+       return NULL;
+}
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(verbose);
+       SLJIT_ASSERT_STOP();
+}
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_ASSERT_STOP();
+       return NULL;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
+{
+       SLJIT_UNUSED_ARG(code);
+       SLJIT_ASSERT_STOP();
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(args);
+       SLJIT_UNUSED_ARG(temporaries);
+       SLJIT_UNUSED_ARG(saveds);
+       SLJIT_UNUSED_ARG(local_size);
+       SLJIT_ASSERT_STOP();
+       return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(args);
+       SLJIT_UNUSED_ARG(temporaries);
+       SLJIT_UNUSED_ARG(saveds);
+       SLJIT_UNUSED_ARG(local_size);
+       SLJIT_ASSERT_STOP();
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(op);
+       SLJIT_UNUSED_ARG(src);
+       SLJIT_UNUSED_ARG(srcw);
+       SLJIT_ASSERT_STOP();
+       return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(dst);
+       SLJIT_UNUSED_ARG(dstw);
+       SLJIT_UNUSED_ARG(args);
+       SLJIT_UNUSED_ARG(temporaries);
+       SLJIT_UNUSED_ARG(saveds);
+       SLJIT_UNUSED_ARG(local_size);
+       SLJIT_ASSERT_STOP();
+       return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(src);
+       SLJIT_UNUSED_ARG(srcw);
+       SLJIT_ASSERT_STOP();
+       return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(op);
+       SLJIT_ASSERT_STOP();
+       return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(op);
+       SLJIT_UNUSED_ARG(dst);
+       SLJIT_UNUSED_ARG(dstw);
+       SLJIT_UNUSED_ARG(src);
+       SLJIT_UNUSED_ARG(srcw);
+       SLJIT_ASSERT_STOP();
+       return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(op);
+       SLJIT_UNUSED_ARG(dst);
+       SLJIT_UNUSED_ARG(dstw);
+       SLJIT_UNUSED_ARG(src1);
+       SLJIT_UNUSED_ARG(src1w);
+       SLJIT_UNUSED_ARG(src2);
+       SLJIT_UNUSED_ARG(src2w);
+       SLJIT_ASSERT_STOP();
+       return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
+{
+       SLJIT_ASSERT_STOP();
+       return reg;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, int size)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(instruction);
+       SLJIT_UNUSED_ARG(size);
+       SLJIT_ASSERT_STOP();
+       return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
+{
+       SLJIT_ASSERT_STOP();
+       return 0;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(op);
+       SLJIT_UNUSED_ARG(dst);
+       SLJIT_UNUSED_ARG(dstw);
+       SLJIT_UNUSED_ARG(src);
+       SLJIT_UNUSED_ARG(srcw);
+       SLJIT_ASSERT_STOP();
+       return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(op);
+       SLJIT_UNUSED_ARG(dst);
+       SLJIT_UNUSED_ARG(dstw);
+       SLJIT_UNUSED_ARG(src1);
+       SLJIT_UNUSED_ARG(src1w);
+       SLJIT_UNUSED_ARG(src2);
+       SLJIT_UNUSED_ARG(src2w);
+       SLJIT_ASSERT_STOP();
+       return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_ASSERT_STOP();
+       return NULL;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(type);
+       SLJIT_ASSERT_STOP();
+       return NULL;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, int type,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(type);
+       SLJIT_UNUSED_ARG(src1);
+       SLJIT_UNUSED_ARG(src1w);
+       SLJIT_UNUSED_ARG(src2);
+       SLJIT_UNUSED_ARG(src2w);
+       SLJIT_ASSERT_STOP();
+       return NULL;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(type);
+       SLJIT_UNUSED_ARG(src1);
+       SLJIT_UNUSED_ARG(src1w);
+       SLJIT_UNUSED_ARG(src2);
+       SLJIT_UNUSED_ARG(src2w);
+       SLJIT_ASSERT_STOP();
+       return NULL;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label)
+{
+       SLJIT_UNUSED_ARG(jump);
+       SLJIT_UNUSED_ARG(label);
+       SLJIT_ASSERT_STOP();
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target)
+{
+       SLJIT_UNUSED_ARG(jump);
+       SLJIT_UNUSED_ARG(target);
+       SLJIT_ASSERT_STOP();
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(type);
+       SLJIT_UNUSED_ARG(src);
+       SLJIT_UNUSED_ARG(srcw);
+       SLJIT_ASSERT_STOP();
+       return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(op);
+       SLJIT_UNUSED_ARG(dst);
+       SLJIT_UNUSED_ARG(dstw);
+       SLJIT_UNUSED_ARG(type);
+       SLJIT_ASSERT_STOP();
+       return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w initval)
+{
+       SLJIT_UNUSED_ARG(compiler);
+       SLJIT_UNUSED_ARG(dst);
+       SLJIT_UNUSED_ARG(dstw);
+       SLJIT_UNUSED_ARG(initval);
+       SLJIT_ASSERT_STOP();
+       return NULL;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+{
+       SLJIT_UNUSED_ARG(addr);
+       SLJIT_UNUSED_ARG(new_addr);
+       SLJIT_ASSERT_STOP();
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
+{
+       SLJIT_UNUSED_ARG(addr);
+       SLJIT_UNUSED_ARG(new_constant);
+       SLJIT_ASSERT_STOP();
+}
+
+#endif
diff --git a/src/3rdparty/pcre/sljit/sljitLir.h b/src/3rdparty/pcre/sljit/sljitLir.h
new file mode 100644 (file)
index 0000000..0cb1c1e
--- /dev/null
@@ -0,0 +1,853 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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 _SLJIT_LIR_H_
+#define _SLJIT_LIR_H_
+
+/*
+   ------------------------------------------------------------------------
+    Stack-Less JIT compiler for multiple architectures (x86, ARM, PowerPC)
+   ------------------------------------------------------------------------
+
+   Short description
+    Advantages:
+      - The execution can be continued from any LIR instruction
+        In other words, jump into and out of the code is safe
+      - Both target of (conditional) jump and call instructions
+        and constants can be dynamically modified during runtime
+        - although it is not suggested to do it frequently
+        - very effective to cache an important value once
+      - A fixed stack space can be allocated for local variables
+      - The compiler is thread-safe
+    Disadvantages:
+      - Limited number of registers (only 6+4 integer registers, max 3+2
+        temporary, max 3+2 saved and 4 floating point registers)
+    In practice:
+      - This approach is very effective for interpreters
+        - One of the saved registers typically points to a stack interface
+        - It can jump to any exception handler anytime (even for another
+          function. It is safe for SLJIT.)
+        - Fast paths can be modified during runtime reflecting the changes
+          of the fastest execution path of the dynamic language
+        - SLJIT supports complex memory addressing modes
+        - mainly position independent code
+      - Optimizations (perhaps later)
+        - Only for basic blocks (when no labels inserted between LIR instructions)
+
+    For valgrind users:
+      - pass --smc-check=all argument to valgrind, since JIT is a "self-modifying code"
+*/
+
+#if !(defined SLJIT_NO_DEFAULT_CONFIG && SLJIT_NO_DEFAULT_CONFIG)
+#include "sljitConfig.h"
+#endif
+
+/* The following header file defines useful macros for fine tuning
+sljit based code generators. They are listed in the begining
+of sljitConfigInternal.h */
+
+#include "sljitConfigInternal.h"
+
+/* --------------------------------------------------------------------- */
+/*  Error codes                                                          */
+/* --------------------------------------------------------------------- */
+
+/* Indicates no error. */
+#define SLJIT_SUCCESS                  0
+/* After the call of sljit_generate_code(), the error code of the compiler
+   is set to this value to avoid future sljit calls (in debug mode at least).
+   The complier should be freed after sljit_generate_code(). */
+#define SLJIT_ERR_COMPILED             1
+/* Cannot allocate non executable memory. */
+#define SLJIT_ERR_ALLOC_FAILED         2
+/* Cannot allocate executable memory.
+   Only for sljit_generate_code() */
+#define SLJIT_ERR_EX_ALLOC_FAILED      3
+/* return value for SLJIT_CONFIG_UNSUPPORTED empty architecture. */
+#define SLJIT_ERR_UNSUPPORTED          4
+
+/* --------------------------------------------------------------------- */
+/*  Registers                                                            */
+/* --------------------------------------------------------------------- */
+
+#define SLJIT_UNUSED           0
+
+/* Temporary (scratch) registers may not preserve their values across function calls. */
+#define SLJIT_TEMPORARY_REG1   1
+#define SLJIT_TEMPORARY_REG2   2
+#define SLJIT_TEMPORARY_REG3   3
+/* Note: Extra Registers cannot be used for memory addressing. */
+/* Note: on x86-32, these registers are emulated (using stack loads & stores). */
+#define SLJIT_TEMPORARY_EREG1  4
+#define SLJIT_TEMPORARY_EREG2  5
+
+/* Saved registers whose preserve their values across function calls. */
+#define SLJIT_SAVED_REG1       6
+#define SLJIT_SAVED_REG2       7
+#define SLJIT_SAVED_REG3       8
+/* Note: Extra Registers cannot be used for memory addressing. */
+/* Note: on x86-32, these registers are emulated (using stack loads & stores). */
+#define SLJIT_SAVED_EREG1      9
+#define SLJIT_SAVED_EREG2      10
+
+/* Read-only register (cannot be the destination of an operation). */
+/* Note: SLJIT_MEM2( ... , SLJIT_LOCALS_REG) is not supported (x86 limitation). */
+/* Note: SLJIT_LOCALS_REG is not necessary the real stack pointer. See sljit_emit_enter. */
+#define SLJIT_LOCALS_REG       11
+
+/* Number of registers. */
+#define SLJIT_NO_TMP_REGISTERS 5
+#define SLJIT_NO_GEN_REGISTERS 5
+#define SLJIT_NO_REGISTERS     11
+
+/* Return with machine word. */
+
+#define SLJIT_RETURN_REG       SLJIT_TEMPORARY_REG1
+
+/* x86 prefers specific registers for special purposes. In case of shift
+   by register it supports only SLJIT_TEMPORARY_REG3 for shift argument
+   (which is the src2 argument of sljit_emit_op2). If another register is
+   used, sljit must exchange data between registers which cause a minor
+   slowdown. Other architectures has no such limitation. */
+
+#define SLJIT_PREF_SHIFT_REG   SLJIT_TEMPORARY_REG3
+
+/* --------------------------------------------------------------------- */
+/*  Floating point registers                                             */
+/* --------------------------------------------------------------------- */
+
+/* Note: SLJIT_UNUSED as destination is not valid for floating point
+     operations, since they cannot be used for setting flags. */
+
+/* Floating point operations are performed on double precision values. */
+
+#define SLJIT_FLOAT_REG1       1
+#define SLJIT_FLOAT_REG2       2
+#define SLJIT_FLOAT_REG3       3
+#define SLJIT_FLOAT_REG4       4
+
+/* --------------------------------------------------------------------- */
+/*  Main structures and functions                                        */
+/* --------------------------------------------------------------------- */
+
+struct sljit_memory_fragment {
+       struct sljit_memory_fragment *next;
+       sljit_uw used_size;
+       sljit_ub memory[1];
+};
+
+struct sljit_label {
+       struct sljit_label *next;
+       sljit_uw addr;
+       /* The maximum size difference. */
+       sljit_uw size;
+};
+
+struct sljit_jump {
+       struct sljit_jump *next;
+       sljit_uw addr;
+       sljit_w flags;
+       union {
+               sljit_uw target;
+               struct sljit_label* label;
+       } u;
+};
+
+struct sljit_const {
+       struct sljit_const *next;
+       sljit_uw addr;
+};
+
+struct sljit_compiler {
+       int error;
+
+       struct sljit_label *labels;
+       struct sljit_jump *jumps;
+       struct sljit_const *consts;
+       struct sljit_label *last_label;
+       struct sljit_jump *last_jump;
+       struct sljit_const *last_const;
+
+       struct sljit_memory_fragment *buf;
+       struct sljit_memory_fragment *abuf;
+
+       /* Used local registers. */
+       int temporaries;
+       /* Used saved registers. */
+       int saveds;
+       /* Local stack size. */
+       int local_size;
+       /* Code size. */
+       sljit_uw size;
+       /* For statistical purposes. */
+       sljit_uw executable_size;
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       int args;
+       int temporaries_start;
+       int saveds_start;
+#endif
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       int mode32;
+#ifdef _WIN64
+       int has_locals;
+#endif
+#endif
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       int flags_saved;
+#endif
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       /* Constant pool handling. */
+       sljit_uw *cpool;
+       sljit_ub *cpool_unique;
+       sljit_uw cpool_diff;
+       sljit_uw cpool_fill;
+       /* Other members. */
+       /* Contains pointer, "ldr pc, [...]" pairs. */
+       sljit_uw patches;
+#endif
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+       /* Temporary fields. */
+       sljit_uw shift_imm;
+       int cache_arg;
+       sljit_w cache_argw;
+#endif
+
+#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
+       int cache_arg;
+       sljit_w cache_argw;
+#endif
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+       int has_locals;
+       sljit_w imm;
+       int cache_arg;
+       sljit_w cache_argw;
+#endif
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+       int has_locals;
+       int delay_slot;
+       int cache_arg;
+       sljit_w cache_argw;
+#endif
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+       FILE* verbose;
+#endif
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+       int skip_checks;
+#endif
+};
+
+/* --------------------------------------------------------------------- */
+/*  Main functions                                                       */
+/* --------------------------------------------------------------------- */
+
+/* Creates an sljit compiler.
+   Returns NULL if failed. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void);
+/* Free everything except the codes. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler);
+
+static SLJIT_INLINE int sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; }
+
+/*
+   Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit,
+   and <= 128 bytes on 64 bit architectures. The memory area is owned by the compiler,
+   and freed by sljit_free_compiler. The returned pointer is sizeof(sljit_w) aligned.
+   Excellent for allocating small blocks during the compiling, and no need to worry
+   about freeing them. The size is enough to contain at most 16 pointers.
+   If the size is outside of the range, the function will return with NULL,
+   but this return value does not indicate that there is no more memory (does
+   not set the compiler to out-of-memory status).
+*/
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, int size);
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+/* Passing NULL disables verbose. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose);
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler);
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code);
+
+/*
+   After the code generation we can retrieve the allocated executable memory size,
+   although this area may not be fully filled with instructions depending on some
+   optimizations. This function is useful only for statistical purposes.
+
+   Before a successful code generation, this function returns with 0.
+*/
+static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; }
+
+/* Instruction generation. Returns with error code. */
+
+/*
+   The executable code is basically a function call from the viewpoint of
+   the C language. The function calls must obey to the ABI (Application
+   Binary Interface) of the platform, which specify the purpose of machine
+   registers and stack handling among other things. The sljit_emit_enter
+   function emits the necessary instructions for setting up a new context
+   for the executable code and moves function arguments to the saved
+   registers. The number of arguments are specified in the "args"
+   parameter and the first argument goes to SLJIT_SAVED_REG1, the second
+   goes to SLJIT_SAVED_REG2 and so on. The number of temporary and
+   saved registers are passed in "temporaries" and "saveds" arguments
+   respectively. Since the saved registers contains the arguments,
+   "args" must be less or equal than "saveds". The sljit_emit_enter
+   is also capable of allocating a stack space for local variables. The
+   "local_size" argument contains the size in bytes of this local area
+   and its staring address is stored in SLJIT_LOCALS_REG. However
+   the SLJIT_LOCALS_REG is not necessary the machine stack pointer.
+   The memory bytes between SLJIT_LOCALS_REG (inclusive) and
+   SLJIT_LOCALS_REG + local_size (exclusive) can be modified freely
+   until the function returns. The stack space is uninitialized.
+
+   Note: every call of sljit_emit_enter and sljit_set_context overwrites
+         the previous context. */
+
+#define SLJIT_MAX_LOCAL_SIZE   65536
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler,
+       int args, int temporaries, int saveds, int local_size);
+
+/* The machine code has a context (which contains the local stack space size,
+   number of used registers, etc.) which initialized by sljit_emit_enter. Several
+   functions (like sljit_emit_return) requres this context to be able to generate
+   the appropriate code. However, some code fragments (like inline cache) may have
+   no normal entry point so their context is unknown for the compiler. Using the
+   function below we can specify thir context.
+
+   Note: every call of sljit_emit_enter and sljit_set_context overwrites
+         the previous context. */
+
+/* Note: multiple calls of this function overwrites the previous call. */
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
+       int args, int temporaries, int saveds, int local_size);
+
+/* Return from machine code.  The op argument can be SLJIT_UNUSED which means the
+   function does not return with anything or any opcode between SLJIT_MOV and
+   SLJIT_MOV_SI (see sljit_emit_op1). As for src and srcw they must be 0 if op
+   is SLJIT_UNUSED, otherwise see below the description about source and
+   destination arguments. */
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op,
+       int src, sljit_w srcw);
+
+/* Really fast calling method for utility functions inside sljit (see SLJIT_FAST_CALL).
+   All registers and even the stack frame is passed to the callee. The return address is
+   preserved in dst/dstw by sljit_emit_fast_enter, and sljit_emit_fast_return can
+   use this as a return value later. */
+
+/* Note: only for sljit specific, non ABI compilant calls. Fast, since only a few machine instructions
+   are needed. Excellent for small uility functions, where saving registers and setting up
+   a new stack frame would cost too much performance. However, it is still possible to return
+   to the address of the caller (or anywhere else). */
+
+/* Note: flags are not changed (unlike sljit_emit_enter / sljit_emit_return). */
+
+/* Note: although sljit_emit_fast_return could be replaced by an ijump, it is not suggested,
+   since many architectures do clever branch prediction on call / return instruction pairs. */
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size);
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw);
+
+/*
+   Source and destination values for arithmetical instructions
+    imm              - a simple immediate value (cannot be used as a destination)
+    reg              - any of the registers (immediate argument must be 0)
+    [imm]            - absolute immediate memory address
+    [reg+imm]        - indirect memory address
+    [reg+(reg<<imm)] - indirect indexed memory address (shift must be between 0 and 3)
+                       useful for (byte, half, int, sljit_w) array access
+                       (fully supported by both x86 and ARM architectures, and cheap operation on others)
+*/
+
+/*
+   IMPORATNT NOTE: memory access MUST be naturally aligned except
+                   SLJIT_UNALIGNED macro is defined and its value is 1.
+
+     length | alignment
+   ---------+-----------
+     byte   | 1 byte (not aligned)
+     half   | 2 byte (real_address & 0x1 == 0)
+     int    | 4 byte (real_address & 0x3 == 0)
+    sljit_w | 4 byte if SLJIT_32BIT_ARCHITECTURE is defined and its value is 1
+            | 8 byte if SLJIT_64BIT_ARCHITECTURE is defined and its value is 1
+
+   Note: different architectures have different addressing limitations
+         Thus sljit may generate several instructions for other addressing modes
+   x86:  all addressing modes supported, but write-back is not supported
+         (requires an extra instruction). On x86-64 only 32 bit signed
+         integers are supported by the architecture.
+   arm:  [reg+imm] supported for small immediates (-4095 <= imm <= 4095
+         or -255 <= imm <= 255 for loading signed bytes, any halfs or doubles)
+         [reg+(reg<<imm)] are supported or requires only two instructions
+         Write back is limited to small immediates on thumb2
+   ppc:  [reg+imm], -65535 <= imm <= 65535. 64 bit moves requires immediates
+         divisible by 4. [reg+reg] supported, write-back supported
+         [reg+(reg<<imm)] (imm != 0) is cheap (requires two instructions)
+*/
+
+/* Register output: simply the name of the register.
+   For destination, you can use SLJIT_UNUSED as well. */
+#define SLJIT_MEM              0x100
+#define SLJIT_MEM0()           (SLJIT_MEM)
+#define SLJIT_MEM1(r1)         (SLJIT_MEM | (r1))
+#define SLJIT_MEM2(r1, r2)     (SLJIT_MEM | (r1) | ((r2) << 4))
+#define SLJIT_IMM              0x200
+
+/* Set 32 bit operation mode (I) on 64 bit CPUs. The flag is totally ignored on
+   32 bit CPUs. The arithmetic instruction uses only the lower 32 bit of the
+   input register(s), and set the flags according to the 32 bit result. If the
+   destination is a register, the higher 32 bit of the result is undefined.
+   The addressing modes (SLJIT_MEM1/SLJIT_MEM2 macros) are unaffected by this flag. */
+#define SLJIT_INT_OP           0x100
+
+/* Common CPU status flags for all architectures (x86, ARM, PPC)
+    - carry flag
+    - overflow flag
+    - zero flag
+    - negative/positive flag (depends on arc)
+   On mips, these flags are emulated by software. */
+
+/* By default, the instructions may, or may not set the CPU status flags.
+   Forcing to set or keep status flags can be done with the following flags: */
+
+/* Note: sljit tries to emit the minimum number of instructions. Using these
+   flags can increase them, so use them wisely to avoid unnecessary code generation. */
+
+/* Set Equal (Zero) status flag (E). */
+#define SLJIT_SET_E                    0x0200
+/* Set signed status flag (S). */
+#define SLJIT_SET_S                    0x0400
+/* Set unsgined status flag (U). */
+#define SLJIT_SET_U                    0x0800
+/* Set signed overflow flag (O). */
+#define SLJIT_SET_O                    0x1000
+/* Set carry flag (C).
+   Note: Kinda unsigned overflow, but behaves differently on various cpus. */
+#define SLJIT_SET_C                    0x2000
+/* Do not modify the flags (K).
+   Note: This flag cannot be combined with any other SLJIT_SET_* flag. */
+#define SLJIT_KEEP_FLAGS               0x4000
+
+/* Notes:
+     - you cannot postpone conditional jump instructions except if noted that
+       the instruction does not set flags (See: SLJIT_KEEP_FLAGS).
+     - flag combinations: '|' means 'logical or'. */
+
+/* Flags: - (never set any flags)
+   Note: breakpoint instruction is not supported by all architectures (namely ppc)
+         It falls back to SLJIT_NOP in those cases. */
+#define SLJIT_BREAKPOINT               0
+/* Flags: - (never set any flags)
+   Note: may or may not cause an extra cycle wait
+         it can even decrease the runtime in a few cases. */
+#define SLJIT_NOP                      1
+/* Flags: may destroy flags
+   Unsigned multiplication of SLJIT_TEMPORARY_REG1 and SLJIT_TEMPORARY_REG2.
+   Result goes to SLJIT_TEMPORARY_REG2:SLJIT_TEMPORARY_REG1 (high:low) word */
+#define SLJIT_UMUL                     2
+/* Flags: may destroy flags
+   Signed multiplication of SLJIT_TEMPORARY_REG1 and SLJIT_TEMPORARY_REG2.
+   Result goes to SLJIT_TEMPORARY_REG2:SLJIT_TEMPORARY_REG1 (high:low) word */
+#define SLJIT_SMUL                     3
+/* Flags: I | may destroy flags
+   Unsigned divide of the value in SLJIT_TEMPORARY_REG1 by the value in SLJIT_TEMPORARY_REG2.
+   The result is placed in SLJIT_TEMPORARY_REG1 and the remainder goes to SLJIT_TEMPORARY_REG2.
+   Note: if SLJIT_TEMPORARY_REG2 contains 0, the behaviour is undefined. */
+#define SLJIT_UDIV                     4
+/* Flags: I | may destroy flags
+   Signed divide of the value in SLJIT_TEMPORARY_REG1 by the value in SLJIT_TEMPORARY_REG2.
+   The result is placed in SLJIT_TEMPORARY_REG1 and the remainder goes to SLJIT_TEMPORARY_REG2.
+   Note: if SLJIT_TEMPORARY_REG2 contains 0, the behaviour is undefined. */
+#define SLJIT_SDIV                     5
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op);
+
+/* Notes for MOV instructions:
+   U = Mov with update (post form). If source or destination defined as SLJIT_MEM1(r1)
+       or SLJIT_MEM2(r1, r2), r1 is increased by the sum of r2 and the constant argument
+   UB = unsigned byte (8 bit)
+   SB = signed byte (8 bit)
+   UH = unsgined half (16 bit)
+   SH = unsgined half (16 bit) */
+
+/* Flags: - (never set any flags) */
+#define SLJIT_MOV                      6
+/* Flags: - (never set any flags) */
+#define SLJIT_MOV_UB                   7
+/* Flags: - (never set any flags) */
+#define SLJIT_MOV_SB                   8
+/* Flags: - (never set any flags) */
+#define SLJIT_MOV_UH                   9
+/* Flags: - (never set any flags) */
+#define SLJIT_MOV_SH                   10
+/* Flags: - (never set any flags) */
+#define SLJIT_MOV_UI                   11
+/* Flags: - (never set any flags) */
+#define SLJIT_MOV_SI                   12
+/* Flags: - (never set any flags) */
+#define SLJIT_MOVU                     13
+/* Flags: - (never set any flags) */
+#define SLJIT_MOVU_UB                  14
+/* Flags: - (never set any flags) */
+#define SLJIT_MOVU_SB                  15
+/* Flags: - (never set any flags) */
+#define SLJIT_MOVU_UH                  16
+/* Flags: - (never set any flags) */
+#define SLJIT_MOVU_SH                  17
+/* Flags: - (never set any flags) */
+#define SLJIT_MOVU_UI                  18
+/* Flags: - (never set any flags) */
+#define SLJIT_MOVU_SI                  19
+/* Flags: I | E | K */
+#define SLJIT_NOT                      20
+/* Flags: I | E | O | K */
+#define SLJIT_NEG                      21
+/* Count leading zeroes
+   Flags: I | E | K */
+#define SLJIT_CLZ                      22
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw);
+
+/* Flags: I | E | O | C | K */
+#define SLJIT_ADD                      23
+/* Flags: I | C | K */
+#define SLJIT_ADDC                     24
+/* Flags: I | E | S | U | O | C | K */
+#define SLJIT_SUB                      25
+/* Flags: I | C | K */
+#define SLJIT_SUBC                     26
+/* Note: integer mul
+   Flags: I | O (see SLJIT_C_MUL_*) | K */
+#define SLJIT_MUL                      27
+/* Flags: I | E | K */
+#define SLJIT_AND                      28
+/* Flags: I | E | K */
+#define SLJIT_OR                       29
+/* Flags: I | E | K */
+#define SLJIT_XOR                      30
+/* Flags: I | E | K
+   Let bit_length be the length of the shift operation: 32 or 64.
+   If src2 is immediate, src2w is masked by (bit_length - 1).
+   Otherwise, if the content of src2 is outside the range from 0
+   to bit_length - 1, the operation is undefined. */
+#define SLJIT_SHL                      31
+/* Flags: I | E | K
+   Let bit_length be the length of the shift operation: 32 or 64.
+   If src2 is immediate, src2w is masked by (bit_length - 1).
+   Otherwise, if the content of src2 is outside the range from 0
+   to bit_length - 1, the operation is undefined. */
+#define SLJIT_LSHR                     32
+/* Flags: I | E | K
+   Let bit_length be the length of the shift operation: 32 or 64.
+   If src2 is immediate, src2w is masked by (bit_length - 1).
+   Otherwise, if the content of src2 is outside the range from 0
+   to bit_length - 1, the operation is undefined. */
+#define SLJIT_ASHR                     33
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w);
+
+/* The following function is a helper function for sljit_emit_op_custom.
+   It returns with the real machine register index of any SLJIT_TEMPORARY
+   SLJIT_SAVED or SLJIT_LOCALS register.
+   Note: it returns with -1 for virtual registers (all EREGs on x86-32).
+   Note: register returned by SLJIT_LOCALS_REG is not necessary the real
+         stack pointer register of the target architecture. */
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg);
+
+/* Any instruction can be inserted into the instruction stream by
+   sljit_emit_op_custom. It has a similar purpose as inline assembly.
+   The size parameter must match to the instruction size of the target
+   architecture:
+
+         x86: 0 < size <= 15. The instruction argument can be byte aligned.
+      Thumb2: if size == 2, the instruction argument must be 2 byte aligned.
+              if size == 4, the instruction argument must be 4 byte aligned.
+   Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, int size);
+
+/* Returns with non-zero if fpu is available. */
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void);
+
+/* Note: dst is the left and src is the right operand for SLJIT_FCMP.
+   Note: NaN check is always performed. If SLJIT_C_FLOAT_NAN is set,
+         the comparison result is unpredictable.
+   Flags: E | S (see SLJIT_C_FLOAT_*) */
+#define SLJIT_FCMP                     34
+/* Flags: - (never set any flags) */
+#define SLJIT_FMOV                     35
+/* Flags: - (never set any flags) */
+#define SLJIT_FNEG                     36
+/* Flags: - (never set any flags) */
+#define SLJIT_FABS                     37
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw);
+
+/* Flags: - (never set any flags) */
+#define SLJIT_FADD                     38
+/* Flags: - (never set any flags) */
+#define SLJIT_FSUB                     39
+/* Flags: - (never set any flags) */
+#define SLJIT_FMUL                     40
+/* Flags: - (never set any flags) */
+#define SLJIT_FDIV                     41
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w);
+
+/* Label and jump instructions. */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler);
+
+/* Invert conditional instruction: xor (^) with 0x1 */
+#define SLJIT_C_EQUAL                  0
+#define SLJIT_C_ZERO                   0
+#define SLJIT_C_NOT_EQUAL              1
+#define SLJIT_C_NOT_ZERO               1
+
+#define SLJIT_C_LESS                   2
+#define SLJIT_C_GREATER_EQUAL          3
+#define SLJIT_C_GREATER                        4
+#define SLJIT_C_LESS_EQUAL             5
+#define SLJIT_C_SIG_LESS               6
+#define SLJIT_C_SIG_GREATER_EQUAL      7
+#define SLJIT_C_SIG_GREATER            8
+#define SLJIT_C_SIG_LESS_EQUAL         9
+
+#define SLJIT_C_OVERFLOW               10
+#define SLJIT_C_NOT_OVERFLOW           11
+
+#define SLJIT_C_MUL_OVERFLOW           12
+#define SLJIT_C_MUL_NOT_OVERFLOW       13
+
+#define SLJIT_C_FLOAT_EQUAL            14
+#define SLJIT_C_FLOAT_NOT_EQUAL                15
+#define SLJIT_C_FLOAT_LESS             16
+#define SLJIT_C_FLOAT_GREATER_EQUAL    17
+#define SLJIT_C_FLOAT_GREATER          18
+#define SLJIT_C_FLOAT_LESS_EQUAL       19
+#define SLJIT_C_FLOAT_NAN              20
+#define SLJIT_C_FLOAT_NOT_NAN          21
+
+#define SLJIT_JUMP                     22
+#define SLJIT_FAST_CALL                        23
+#define SLJIT_CALL0                    24
+#define SLJIT_CALL1                    25
+#define SLJIT_CALL2                    26
+#define SLJIT_CALL3                    27
+
+/* Fast calling method. See sljit_emit_fast_enter / sljit_emit_fast_return. */
+
+/* The target can be changed during runtime (see: sljit_set_jump_addr). */
+#define SLJIT_REWRITABLE_JUMP          0x1000
+
+/* Emit a jump instruction. The destination is not set, only the type of the jump.
+    type must be between SLJIT_C_EQUAL and SLJIT_CALL3
+    type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
+   Flags: - (never set any flags) for both conditional and unconditional jumps.
+   Flags: destroy all flags for calls. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type);
+
+/* Basic arithmetic comparison. In most architectures it is implemented as
+   an SLJIT_SUB operation (with SLJIT_UNUSED destination and setting
+   appropriate flags) followed by a sljit_emit_jump. However some
+   architectures (i.e: MIPS) may employ special optimizations here. It is
+   suggested to use this comparison form when appropriate.
+    type must be between SLJIT_C_EQUAL and SLJIT_C_SIG_LESS_EQUAL
+    type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP or SLJIT_INT_OP
+   Flags: destroy flags. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, int type,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w);
+
+/* Basic floating point comparison. In most architectures it is implemented as
+   an SLJIT_FCMP operation (setting appropriate flags) followed by a
+   sljit_emit_jump. However some architectures (i.e: MIPS) may employ
+   special optimizations here. It is suggested to use this comparison form
+   when appropriate.
+    type must be between SLJIT_C_FLOAT_EQUAL and SLJIT_C_FLOAT_NOT_NAN
+    type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
+   Flags: destroy flags.
+   Note: if either operand is NaN, the behaviour is undefined for
+         type <= SLJIT_C_FLOAT_LESS_EQUAL. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w);
+
+/* Set the destination of the jump to this label. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label);
+/* Only for jumps defined with SLJIT_REWRITABLE_JUMP flag.
+   Note: use sljit_emit_ijump for fixed jumps. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target);
+
+/* Call function or jump anywhere. Both direct and indirect form
+    type must be between SLJIT_JUMP and SLJIT_CALL3
+    Direct form: set src to SLJIT_IMM() and srcw to the address
+    Indirect form: any other valid addressing mode
+   Flags: - (never set any flags) for unconditional jumps.
+   Flags: destroy all flags for calls. */
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw);
+
+/* If op == SLJIT_MOV:
+     Set dst to 1 if condition is fulfilled, 0 otherwise
+       type must be between SLJIT_C_EQUAL and SLJIT_C_FLOAT_NOT_NAN
+     Flags: - (never set any flags)
+   If op == SLJIT_OR
+     Dst is used as src as well, and set its lowest bit to 1 if
+     the condition is fulfilled. Otherwise it does nothing.
+     Flags: E | K
+   Note: sljit_emit_cond_value does nothing, if dst is SLJIT_UNUSED (regardless of op). */
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type);
+
+/* The constant can be changed runtime (see: sljit_set_const)
+   Flags: - (never set any flags) */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value);
+
+/* After the code generation the address for label, jump and const instructions
+   are computed. Since these structures are freed sljit_free_compiler, the
+   addresses must be preserved by the user program elsewere. */
+static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { return label->addr; }
+static SLJIT_INLINE sljit_uw sljit_get_jump_addr(struct sljit_jump *jump) { return jump->addr; }
+static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) { return const_->addr; }
+
+/* Only the address is required to rewrite the code. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr);
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant);
+
+/* --------------------------------------------------------------------- */
+/*  Miscellaneous utility functions                                      */
+/* --------------------------------------------------------------------- */
+
+#define SLJIT_MAJOR_VERSION    0
+#define SLJIT_MINOR_VERSION    87
+
+/* Get the human readable name of the platfrom.
+   Can be useful for debugging on platforms like ARM, where ARM and
+   Thumb2 functions can be mixed. */
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void);
+
+/* Portble helper function to get an offset of a member. */
+#define SLJIT_OFFSETOF(base, member) ((sljit_w)(&((base*)0x10)->member) - 0x10)
+
+#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
+/* This global lock is useful to compile common functions. */
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void);
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void);
+#endif
+
+#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
+
+/* The sljit_stack is a utiliy feature of sljit, which allocates a
+   writable memory region between base (inclusive) and limit (exclusive).
+   Both base and limit is a pointer, and base is always <= than limit.
+   This feature uses the "address space reserve" feature
+   of modern operating systems. Basically we don't need to allocate a
+   huge memory block in one step for the worst case, we can start with
+   a smaller chunk and extend it later. Since the address space is
+   reserved, the data never copied to other regions, thus it is safe
+   to store pointers here. */
+
+/* Note: The base field is aligned to PAGE_SIZE bytes (usually 4k or more).
+   Note: stack growing should not happen in small steps: 4k, 16k or even
+     bigger growth is better.
+   Note: this structure may not be supported by all operating systems.
+     Some kind of fallback mechanism is suggested when SLJIT_UTIL_STACK
+     is not defined. */
+
+struct sljit_stack {
+       /* User data, anything can be stored here.
+          Starting with the same value as base. */
+       sljit_uw top;
+       /* These members are read only. */
+       sljit_uw base;
+       sljit_uw limit;
+       sljit_uw max_limit;
+};
+
+/* Returns NULL if unsuccessful.
+   Note: limit and max_limit contains the size for stack allocation
+   Note: the top field is initialized to base. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit);
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* stack);
+
+/* Can be used to increase (allocate) or decrease (free) the memory area.
+   Returns with a non-zero value if unsuccessful. If new_limit is greater than
+   max_limit, it will fail. It is very easy to implement a stack data structure,
+   since the growth ratio can be added to the current limit, and sljit_stack_resize
+   will do all the necessary checks. The fields of the stack are not changed if
+   sljit_stack_resize fails. */
+SLJIT_API_FUNC_ATTRIBUTE sljit_w SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit);
+
+#endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */
+
+#if !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+
+/* Get the entry address of a given function. */
+#define SLJIT_FUNC_OFFSET(func_name)   ((sljit_w)func_name)
+
+#else /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */
+
+/* All JIT related code should be placed in the same context (library, binary, etc.). */
+
+#define SLJIT_FUNC_OFFSET(func_name)   ((sljit_w)*(void**)func_name)
+
+/* For powerpc64, the function pointers point to a context descriptor. */
+struct sljit_function_context {
+       sljit_w addr;
+       sljit_w r2;
+       sljit_w r11;
+};
+
+/* Fill the context arguments using the addr and the function.
+   If func_ptr is NULL, it will not be set to the address of context
+   If addr is NULL, the function address also comes from the func pointer. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_w addr, void* func);
+
+#endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */
+
+#endif /* _SLJIT_LIR_H_ */
diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c b/src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c
new file mode 100644 (file)
index 0000000..a51536b
--- /dev/null
@@ -0,0 +1,1913 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
+{
+       return "ARM-Thumb2" SLJIT_CPUINFO;
+}
+
+/* Last register + 1. */
+#define TMP_REG1       (SLJIT_NO_REGISTERS + 1)
+#define TMP_REG2       (SLJIT_NO_REGISTERS + 2)
+#define TMP_REG3       (SLJIT_NO_REGISTERS + 3)
+#define TMP_PC         (SLJIT_NO_REGISTERS + 4)
+
+#define TMP_FREG1      (SLJIT_FLOAT_REG4 + 1)
+#define TMP_FREG2      (SLJIT_FLOAT_REG4 + 2)
+
+/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
+static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
+  0, 0, 1, 2, 12, 5, 6, 7, 8, 10, 11, 13, 3, 4, 14, 15
+};
+
+#define COPY_BITS(src, from, to, bits) \
+       ((from >= to ? (src >> (from - to)) : (src << (to - from))) & (((1 << bits) - 1) << to))
+
+/* Thumb16 encodings. */
+#define RD3(rd) (reg_map[rd])
+#define RN3(rn) (reg_map[rn] << 3)
+#define RM3(rm) (reg_map[rm] << 6)
+#define RDN3(rdn) (reg_map[rdn] << 8)
+#define IMM3(imm) (imm << 6)
+#define IMM8(imm) (imm)
+
+/* Thumb16 helpers. */
+#define SET_REGS44(rd, rn) \
+       ((reg_map[rn] << 3) | (reg_map[rd] & 0x7) | ((reg_map[rd] & 0x8) << 4))
+#define IS_2_LO_REGS(reg1, reg2) \
+       (reg_map[reg1] <= 7 && reg_map[reg2] <= 7)
+#define IS_3_LO_REGS(reg1, reg2, reg3) \
+       (reg_map[reg1] <= 7 && reg_map[reg2] <= 7 && reg_map[reg3] <= 7)
+
+/* Thumb32 encodings. */
+#define RD4(rd) (reg_map[rd] << 8)
+#define RN4(rn) (reg_map[rn] << 16)
+#define RM4(rm) (reg_map[rm])
+#define RT4(rt) (reg_map[rt] << 12)
+#define DD4(dd) ((dd) << 12)
+#define DN4(dn) ((dn) << 16)
+#define DM4(dm) (dm)
+#define IMM5(imm) \
+       (COPY_BITS(imm, 2, 12, 3) | ((imm & 0x3) << 6))
+#define IMM12(imm) \
+       (COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))
+
+typedef sljit_ui sljit_ins;
+
+/* --------------------------------------------------------------------- */
+/*  Instrucion forms                                                     */
+/* --------------------------------------------------------------------- */
+
+/* dot '.' changed to _
+   I immediate form (possibly followed by number of immediate bits). */
+#define ADCI           0xf1400000
+#define ADCS           0x4140
+#define ADC_W          0xeb400000
+#define ADD            0x4400
+#define ADDS           0x1800
+#define ADDSI3         0x1c00
+#define ADDSI8         0x3000
+#define ADD_W          0xeb000000
+#define ADDWI          0xf2000000
+#define ADD_SP         0xb000
+#define ADD_W          0xeb000000
+#define ADD_WI         0xf1000000
+#define ANDI           0xf0000000
+#define ANDS           0x4000
+#define AND_W          0xea000000
+#define ASRS           0x4100
+#define ASRSI          0x1000
+#define ASR_W          0xfa40f000
+#define ASR_WI         0xea4f0020
+#define BICI           0xf0200000
+#define BKPT           0xbe00
+#define BLX            0x4780
+#define BX             0x4700
+#define CLZ            0xfab0f080
+#define CMPI           0x2800
+#define CMP_W          0xebb00f00
+#define EORI           0xf0800000
+#define EORS           0x4040
+#define EOR_W          0xea800000
+#define IT             0xbf00
+#define LSLS           0x4080
+#define LSLSI          0x0000
+#define LSL_W          0xfa00f000
+#define LSL_WI         0xea4f0000
+#define LSRS           0x40c0
+#define LSRSI          0x0800
+#define LSR_W          0xfa20f000
+#define LSR_WI         0xea4f0010
+#define MOV            0x4600
+#define MOVS           0x0000
+#define MOVSI          0x2000
+#define MOVT           0xf2c00000
+#define MOVW           0xf2400000
+#define MOV_W          0xea4f0000
+#define MOV_WI         0xf04f0000
+#define MUL            0xfb00f000
+#define MVNS           0x43c0
+#define MVN_W          0xea6f0000
+#define MVN_WI         0xf06f0000
+#define NOP            0xbf00
+#define ORNI           0xf0600000
+#define ORRI           0xf0400000
+#define ORRS           0x4300
+#define ORR_W          0xea400000
+#define POP            0xbd00
+#define POP_W          0xe8bd0000
+#define PUSH           0xb500
+#define PUSH_W         0xe92d0000
+#define RSB_WI         0xf1c00000
+#define RSBSI          0x4240
+#define SBCI           0xf1600000
+#define SBCS           0x4180
+#define SBC_W          0xeb600000
+#define SMULL          0xfb800000
+#define STR_SP         0x9000
+#define SUBS           0x1a00
+#define SUBSI3         0x1e00
+#define SUBSI8         0x3800
+#define SUB_W          0xeba00000
+#define SUBWI          0xf2a00000
+#define SUB_SP         0xb080
+#define SUB_WI         0xf1a00000
+#define SXTB           0xb240
+#define SXTB_W         0xfa4ff080
+#define SXTH           0xb200
+#define SXTH_W         0xfa0ff080
+#define TST            0x4200
+#define UMULL          0xfba00000
+#define UXTB           0xb2c0
+#define UXTB_W         0xfa5ff080
+#define UXTH           0xb280
+#define UXTH_W         0xfa1ff080
+#define VABS_F64       0xeeb00bc0
+#define VADD_F64       0xee300b00
+#define VCMP_F64       0xeeb40b40
+#define VDIV_F64       0xee800b00
+#define VMOV_F64       0xeeb00b40
+#define VMRS           0xeef1fa10
+#define VMUL_F64       0xee200b00
+#define VNEG_F64       0xeeb10b40
+#define VSTR           0xed000b00
+#define VSUB_F64       0xee300b40
+
+static int push_inst16(struct sljit_compiler *compiler, sljit_ins inst)
+{
+       sljit_uh *ptr;
+       SLJIT_ASSERT(!(inst & 0xffff0000));
+
+       ptr = (sljit_uh*)ensure_buf(compiler, sizeof(sljit_uh));
+       FAIL_IF(!ptr);
+       *ptr = inst;
+       compiler->size++;
+       return SLJIT_SUCCESS;
+}
+
+static int push_inst32(struct sljit_compiler *compiler, sljit_ins inst)
+{
+       sljit_uh *ptr = (sljit_uh*)ensure_buf(compiler, sizeof(sljit_ins));
+       FAIL_IF(!ptr);
+       *ptr++ = inst >> 16;
+       *ptr = inst;
+       compiler->size += 2;
+       return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE int emit_imm32_const(struct sljit_compiler *compiler, int dst, sljit_uw imm)
+{
+       FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) |
+               COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)));
+       return push_inst32(compiler, MOVT | RD4(dst) |
+               COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));
+}
+
+static SLJIT_INLINE void modify_imm32_const(sljit_uh* inst, sljit_uw new_imm)
+{
+       int dst = inst[1] & 0x0f00;
+       SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00));
+       inst[0] = (MOVW >> 16) | COPY_BITS(new_imm, 12, 0, 4) | COPY_BITS(new_imm, 11, 10, 1);
+       inst[1] = dst | COPY_BITS(new_imm, 8, 12, 3) | (new_imm & 0xff);
+       inst[2] = (MOVT >> 16) | COPY_BITS(new_imm, 12 + 16, 0, 4) | COPY_BITS(new_imm, 11 + 16, 10, 1);
+       inst[3] = dst | COPY_BITS(new_imm, 8 + 16, 12, 3) | ((new_imm & 0xff0000) >> 16);
+}
+
+static SLJIT_INLINE int detect_jump_type(struct sljit_jump *jump, sljit_uh *code_ptr, sljit_uh *code)
+{
+       sljit_w diff;
+
+       if (jump->flags & SLJIT_REWRITABLE_JUMP)
+               return 0;
+
+       if (jump->flags & JUMP_ADDR) {
+               /* Branch to ARM code is not optimized yet. */
+               if (!(jump->u.target & 0x1))
+                       return 0;
+               diff = ((sljit_w)jump->u.target - (sljit_w)(code_ptr + 2)) >> 1;
+       }
+       else {
+               SLJIT_ASSERT(jump->flags & JUMP_LABEL);
+               diff = ((sljit_w)(code + jump->u.label->size) - (sljit_w)(code_ptr + 2)) >> 1;
+       }
+
+       if (jump->flags & IS_CONDITIONAL) {
+               SLJIT_ASSERT(!(jump->flags & IS_BL));
+               if (diff <= 127 && diff >= -128) {
+                       jump->flags |= B_TYPE1;
+                       return 5;
+               }
+               if (diff <= 524287 && diff >= -524288) {
+                       jump->flags |= B_TYPE2;
+                       return 4;
+               }
+               /* +1 comes from the prefix IT instruction. */
+               diff--;
+               if (diff <= 8388607 && diff >= -8388608) {
+                       jump->flags |= B_TYPE3;
+                       return 3;
+               }
+       }
+       else if (jump->flags & IS_BL) {
+               if (diff <= 8388607 && diff >= -8388608) {
+                       jump->flags |= BL_TYPE6;
+                       return 3;
+               }
+       }
+       else {
+               if (diff <= 1023 && diff >= -1024) {
+                       jump->flags |= B_TYPE4;
+                       return 4;
+               }
+               if (diff <= 8388607 && diff >= -8388608) {
+                       jump->flags |= B_TYPE5;
+                       return 3;
+               }
+       }
+
+       return 0;
+}
+
+static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr, int flush)
+{
+       sljit_uh* inst = (sljit_uh*)addr;
+       modify_imm32_const(inst, new_addr);
+       if (flush) {
+               SLJIT_CACHE_FLUSH(inst, inst + 3);
+       }
+}
+
+static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump)
+{
+       int type = (jump->flags >> 4) & 0xf;
+       sljit_w diff;
+       sljit_uh *jump_inst;
+       int s, j1, j2;
+
+       if (SLJIT_UNLIKELY(type == 0)) {
+               inline_set_jump_addr(jump->addr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
+               return;
+       }
+
+       if (jump->flags & JUMP_ADDR) {
+               SLJIT_ASSERT(jump->u.target & 0x1);
+               diff = ((sljit_w)jump->u.target - (sljit_w)(jump->addr + 4)) >> 1;
+       }
+       else
+               diff = ((sljit_w)(jump->u.label->addr) - (sljit_w)(jump->addr + 4)) >> 1;
+       jump_inst = (sljit_uh*)jump->addr;
+
+       switch (type) {
+       case 1:
+               /* Encoding T1 of 'B' instruction */
+               SLJIT_ASSERT(diff <= 127 && diff >= -128 && (jump->flags & IS_CONDITIONAL));
+               jump_inst[0] = 0xd000 | (jump->flags & 0xf00) | (diff & 0xff);
+               return;
+       case 2:
+               /* Encoding T3 of 'B' instruction */
+               SLJIT_ASSERT(diff <= 524287 && diff >= -524288 && (jump->flags & IS_CONDITIONAL));
+               jump_inst[0] = 0xf000 | COPY_BITS(jump->flags, 8, 6, 4) | COPY_BITS(diff, 11, 0, 6) | COPY_BITS(diff, 19, 10, 1);
+               jump_inst[1] = 0x8000 | COPY_BITS(diff, 17, 13, 1) | COPY_BITS(diff, 18, 11, 1) | (diff & 0x7ff);
+               return;
+       case 3:
+               SLJIT_ASSERT(jump->flags & IS_CONDITIONAL);
+               *jump_inst++ = IT | ((jump->flags >> 4) & 0xf0) | 0x8;
+               diff--;
+               type = 5;
+               break;
+       case 4:
+               /* Encoding T2 of 'B' instruction */
+               SLJIT_ASSERT(diff <= 1023 && diff >= -1024 && !(jump->flags & IS_CONDITIONAL));
+               jump_inst[0] = 0xe000 | (diff & 0x7ff);
+               return;
+       }
+
+       SLJIT_ASSERT(diff <= 8388607 && diff >= -8388608);
+
+       /* Really complex instruction form for branches. */
+       s = (diff >> 23) & 0x1;
+       j1 = (~(diff >> 21) ^ s) & 0x1;
+       j2 = (~(diff >> 22) ^ s) & 0x1;
+       jump_inst[0] = 0xf000 | (s << 10) | COPY_BITS(diff, 11, 0, 10);
+       jump_inst[1] = (j1 << 13) | (j2 << 11) | (diff & 0x7ff);
+
+       /* The others have a common form. */
+       if (type == 5) /* Encoding T4 of 'B' instruction */
+               jump_inst[1] |= 0x9000;
+       else if (type == 6) /* Encoding T1 of 'BL' instruction */
+               jump_inst[1] |= 0xd000;
+       else
+               SLJIT_ASSERT_STOP();
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
+{
+       struct sljit_memory_fragment *buf;
+       sljit_uh *code;
+       sljit_uh *code_ptr;
+       sljit_uh *buf_ptr;
+       sljit_uh *buf_end;
+       sljit_uw half_count;
+
+       struct sljit_label *label;
+       struct sljit_jump *jump;
+       struct sljit_const *const_;
+
+       CHECK_ERROR_PTR();
+       check_sljit_generate_code(compiler);
+       reverse_buf(compiler);
+
+       code = (sljit_uh*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_uh));
+       PTR_FAIL_WITH_EXEC_IF(code);
+       buf = compiler->buf;
+
+       code_ptr = code;
+       half_count = 0;
+       label = compiler->labels;
+       jump = compiler->jumps;
+       const_ = compiler->consts;
+
+       do {
+               buf_ptr = (sljit_uh*)buf->memory;
+               buf_end = buf_ptr + (buf->used_size >> 1);
+               do {
+                       *code_ptr = *buf_ptr++;
+                       /* These structures are ordered by their address. */
+                       SLJIT_ASSERT(!label || label->size >= half_count);
+                       SLJIT_ASSERT(!jump || jump->addr >= half_count);
+                       SLJIT_ASSERT(!const_ || const_->addr >= half_count);
+                       if (label && label->size == half_count) {
+                               label->addr = ((sljit_uw)code_ptr) | 0x1;
+                               label->size = code_ptr - code;
+                               label = label->next;
+                       }
+                       if (jump && jump->addr == half_count) {
+                                       jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_CONDITIONAL) ? 10 : 8);
+                                       code_ptr -= detect_jump_type(jump, code_ptr, code);
+                                       jump = jump->next;
+                       }
+                       if (const_ && const_->addr == half_count) {
+                               const_->addr = (sljit_uw)code_ptr;
+                               const_ = const_->next;
+                       }
+                       code_ptr ++;
+                       half_count ++;
+               } while (buf_ptr < buf_end);
+
+               buf = buf->next;
+       } while (buf);
+
+       if (label && label->size == half_count) {
+               label->addr = ((sljit_uw)code_ptr) | 0x1;
+               label->size = code_ptr - code;
+               label = label->next;
+       }
+
+       SLJIT_ASSERT(!label);
+       SLJIT_ASSERT(!jump);
+       SLJIT_ASSERT(!const_);
+       SLJIT_ASSERT(code_ptr - code <= (int)compiler->size);
+
+       jump = compiler->jumps;
+       while (jump) {
+               set_jump_instruction(jump);
+               jump = jump->next;
+       }
+
+       SLJIT_CACHE_FLUSH(code, code_ptr);
+       compiler->error = SLJIT_ERR_COMPILED;
+       compiler->executable_size = compiler->size * sizeof(sljit_uh);
+       /* Set thumb mode flag. */
+       return (void*)((sljit_uw)code | 0x1);
+}
+
+#define INVALID_IMM    0x80000000
+static sljit_uw get_imm(sljit_uw imm)
+{
+       /* Thumb immediate form. */
+       int counter;
+
+       if (imm <= 0xff)
+               return imm;
+
+       if ((imm & 0xffff) == (imm >> 16)) {
+               /* Some special cases. */
+               if (!(imm & 0xff00))
+                       return (1 << 12) | (imm & 0xff);
+               if (!(imm & 0xff))
+                       return (2 << 12) | ((imm >> 8) & 0xff);
+               if ((imm & 0xff00) == ((imm & 0xff) << 8))
+                       return (3 << 12) | (imm & 0xff);
+       }
+
+       /* Assembly optimization: count leading zeroes? */
+       counter = 8;
+       if (!(imm & 0xffff0000)) {
+               counter += 16;
+               imm <<= 16;
+       }
+       if (!(imm & 0xff000000)) {
+               counter += 8;
+               imm <<= 8;
+       }
+       if (!(imm & 0xf0000000)) {
+               counter += 4;
+               imm <<= 4;
+       }
+       if (!(imm & 0xc0000000)) {
+               counter += 2;
+               imm <<= 2;
+       }
+       if (!(imm & 0x80000000)) {
+               counter += 1;
+               imm <<= 1;
+       }
+       /* Since imm >= 128, this must be true. */
+       SLJIT_ASSERT(counter <= 31);
+
+       if (imm & 0x00ffffff)
+               return INVALID_IMM; /* Cannot be encoded. */
+
+       return ((imm >> 24) & 0x7f) | COPY_BITS(counter, 4, 26, 1) | COPY_BITS(counter, 1, 12, 3) | COPY_BITS(counter, 0, 7, 1);
+}
+
+static int load_immediate(struct sljit_compiler *compiler, int dst, sljit_uw imm)
+{
+       sljit_uw tmp;
+
+       if (imm >= 0x10000) {
+               tmp = get_imm(imm);
+               if (tmp != INVALID_IMM)
+                       return push_inst32(compiler, MOV_WI | RD4(dst) | tmp);
+               tmp = get_imm(~imm);
+               if (tmp != INVALID_IMM)
+                       return push_inst32(compiler, MVN_WI | RD4(dst) | tmp);
+       }
+
+       /* set low 16 bits, set hi 16 bits to 0. */
+       FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) |
+               COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)));
+
+       /* set hi 16 bit if needed. */
+       if (imm >= 0x10000)
+               return push_inst32(compiler, MOVT | RD4(dst) |
+                       COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));
+       return SLJIT_SUCCESS;
+}
+
+#define ARG1_IMM       0x0010000
+#define ARG2_IMM       0x0020000
+#define KEEP_FLAGS     0x0040000
+#define SET_MULOV      0x0080000
+/* SET_FLAGS must be 0x100000 as it is also the value of S bit (can be used for optimization). */
+#define SET_FLAGS      0x0100000
+#define UNUSED_RETURN  0x0200000
+#define SLOW_DEST      0x0400000
+#define SLOW_SRC1      0x0800000
+#define SLOW_SRC2      0x1000000
+
+static int emit_op_imm(struct sljit_compiler *compiler, int flags, int dst, sljit_uw arg1, sljit_uw arg2)
+{
+       /* dst must be register, TMP_REG1
+          arg1 must be register, TMP_REG1, imm
+          arg2 must be register, TMP_REG2, imm */
+       int reg;
+       sljit_uw imm;
+
+       if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) {
+               /* Both are immediates. */
+               flags &= ~ARG1_IMM;
+               FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));
+               arg1 = TMP_REG1;
+       }
+
+       if (flags & (ARG1_IMM | ARG2_IMM)) {
+               reg = (flags & ARG2_IMM) ? arg1 : arg2;
+               imm = (flags & ARG2_IMM) ? arg2 : arg1;
+
+               switch (flags & 0xffff) {
+               case SLJIT_MOV:
+                       SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG1);
+                       return load_immediate(compiler, dst, imm);
+               case SLJIT_NOT:
+                       if (!(flags & SET_FLAGS))
+                               return load_immediate(compiler, dst, ~imm);
+                       /* Since the flags should be set, we just fallback to the register mode.
+                          Although I could do some clever things here, "NOT IMM" does not worth the efforts. */
+                       break;
+               case SLJIT_CLZ:
+                       /* No form with immediate operand. */
+                       break;
+               case SLJIT_ADD:
+                       if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) {
+                               if (imm <= 0x7)
+                                       return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
+                               if (reg == dst && imm <= 0xff)
+                                       return push_inst16(compiler, ADDSI8 | IMM8(imm) | RDN3(dst));
+                       }
+                       if (imm <= 0xfff && !(flags & SET_FLAGS))
+                               return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm));
+                       imm = get_imm(imm);
+                       if (imm != INVALID_IMM)
+                               return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+                       break;
+               case SLJIT_ADDC:
+                       imm = get_imm(imm);
+                       if (imm != INVALID_IMM)
+                               return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+                       break;
+               case SLJIT_SUB:
+                       if (flags & ARG2_IMM) {
+                               if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) {
+                                       if (imm <= 0x7)
+                                               return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
+                                       if (imm <= 0xff) {
+                                               if (reg == dst)
+                                                       return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst));
+                                               if (flags & UNUSED_RETURN)
+                                                       return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg));
+                                       }
+                               }
+                               if (imm <= 0xfff && !(flags & SET_FLAGS))
+                                       return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm));
+                               imm = get_imm(imm);
+                               if (imm != INVALID_IMM)
+                                       return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+                       }
+                       else {
+                               if (!(flags & KEEP_FLAGS) && imm == 0 && IS_2_LO_REGS(reg, dst))
+                                       return push_inst16(compiler, RSBSI | RD3(dst) | RN3(reg));
+                               imm = get_imm(imm);
+                               if (imm != INVALID_IMM)
+                                       return push_inst32(compiler, RSB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+                       }
+                       break;
+               case SLJIT_SUBC:
+                       if (flags & ARG2_IMM) {
+                               imm = get_imm(imm);
+                               if (imm != INVALID_IMM)
+                                       return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+                       }
+                       break;
+               case SLJIT_MUL:
+                       /* No form with immediate operand. */
+                       break;
+               case SLJIT_AND:
+                       imm = get_imm(imm);
+                       if (imm != INVALID_IMM)
+                               return push_inst32(compiler, ANDI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+                       imm = get_imm(~((flags & ARG2_IMM) ? arg2 : arg1));
+                       if (imm != INVALID_IMM)
+                               return push_inst32(compiler, BICI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+                       break;
+               case SLJIT_OR:
+                       imm = get_imm(imm);
+                       if (imm != INVALID_IMM)
+                               return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+                       imm = get_imm(~((flags & ARG2_IMM) ? arg2 : arg1));
+                       if (imm != INVALID_IMM)
+                               return push_inst32(compiler, ORNI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+                       break;
+               case SLJIT_XOR:
+                       imm = get_imm(imm);
+                       if (imm != INVALID_IMM)
+                               return push_inst32(compiler, EORI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+                       break;
+               case SLJIT_SHL:
+                       if (flags & ARG2_IMM) {
+                               imm &= 0x1f;
+                               if (imm == 0) {
+                                       if (!(flags & SET_FLAGS))
+                                               return push_inst16(compiler, MOV | SET_REGS44(dst, reg));
+                                       if (IS_2_LO_REGS(dst, reg))
+                                               return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));
+                                       return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));
+                               }
+                               if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
+                                       return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6));
+                               return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
+                       }
+                       break;
+               case SLJIT_LSHR:
+                       if (flags & ARG2_IMM) {
+                               imm &= 0x1f;
+                               if (imm == 0) {
+                                       if (!(flags & SET_FLAGS))
+                                               return push_inst16(compiler, MOV | SET_REGS44(dst, reg));
+                                       if (IS_2_LO_REGS(dst, reg))
+                                               return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));
+                                       return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));
+                               }
+                               if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
+                                       return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6));
+                               return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
+                       }
+                       break;
+               case SLJIT_ASHR:
+                       if (flags & ARG2_IMM) {
+                               imm &= 0x1f;
+                               if (imm == 0) {
+                                       if (!(flags & SET_FLAGS))
+                                               return push_inst16(compiler, MOV | SET_REGS44(dst, reg));
+                                       if (IS_2_LO_REGS(dst, reg))
+                                               return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));
+                                       return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));
+                               }
+                               if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
+                                       return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6));
+                               return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
+                       }
+                       break;
+               default:
+                       SLJIT_ASSERT_STOP();
+                       break;
+               }
+
+               if (flags & ARG2_IMM) {
+                       FAIL_IF(load_immediate(compiler, TMP_REG2, arg2));
+                       arg2 = TMP_REG2;
+               }
+               else {
+                       FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));
+                       arg1 = TMP_REG1;
+               }
+       }
+
+       /* Both arguments are registers. */
+       switch (flags & 0xffff) {
+       case SLJIT_MOV:
+       case SLJIT_MOV_UI:
+       case SLJIT_MOV_SI:
+       case SLJIT_MOVU:
+       case SLJIT_MOVU_UI:
+       case SLJIT_MOVU_SI:
+               SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+               return push_inst16(compiler, MOV | SET_REGS44(dst, arg2));
+       case SLJIT_MOV_UB:
+       case SLJIT_MOVU_UB:
+               SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+               if (IS_2_LO_REGS(dst, arg2))
+                       return push_inst16(compiler, UXTB | RD3(dst) | RN3(arg2));
+               return push_inst32(compiler, UXTB_W | RD4(dst) | RM4(arg2));
+       case SLJIT_MOV_SB:
+       case SLJIT_MOVU_SB:
+               SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+               if (IS_2_LO_REGS(dst, arg2))
+                       return push_inst16(compiler, SXTB | RD3(dst) | RN3(arg2));
+               return push_inst32(compiler, SXTB_W | RD4(dst) | RM4(arg2));
+       case SLJIT_MOV_UH:
+       case SLJIT_MOVU_UH:
+               SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+               if (IS_2_LO_REGS(dst, arg2))
+                       return push_inst16(compiler, UXTH | RD3(dst) | RN3(arg2));
+               return push_inst32(compiler, UXTH_W | RD4(dst) | RM4(arg2));
+       case SLJIT_MOV_SH:
+       case SLJIT_MOVU_SH:
+               SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+               if (IS_2_LO_REGS(dst, arg2))
+                       return push_inst16(compiler, SXTH | RD3(dst) | RN3(arg2));
+               return push_inst32(compiler, SXTH_W | RD4(dst) | RM4(arg2));
+       case SLJIT_NOT:
+               SLJIT_ASSERT(arg1 == TMP_REG1);
+               if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+                       return push_inst16(compiler, MVNS | RD3(dst) | RN3(arg2));
+               return push_inst32(compiler, MVN_W | (flags & SET_FLAGS) | RD4(dst) | RM4(arg2));
+       case SLJIT_CLZ:
+               SLJIT_ASSERT(arg1 == TMP_REG1);
+               FAIL_IF(push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2)));
+               if (flags & SET_FLAGS) {
+                       if (reg_map[dst] <= 7)
+                               return push_inst16(compiler, CMPI | RDN3(dst));
+                       return push_inst32(compiler, ADD_WI | SET_FLAGS | RN4(dst) | RD4(dst));
+               }
+               return SLJIT_SUCCESS;
+       case SLJIT_ADD:
+               if (!(flags & KEEP_FLAGS) && IS_3_LO_REGS(dst, arg1, arg2))
+                       return push_inst16(compiler, ADDS | RD3(dst) | RN3(arg1) | RM3(arg2));
+               if (dst == arg1 && !(flags & SET_FLAGS))
+                       return push_inst16(compiler, ADD | SET_REGS44(dst, arg2));
+               return push_inst32(compiler, ADD_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+       case SLJIT_ADDC:
+               if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+                       return push_inst16(compiler, ADCS | RD3(dst) | RN3(arg2));
+               return push_inst32(compiler, ADC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+       case SLJIT_SUB:
+               if (!(flags & KEEP_FLAGS) && IS_3_LO_REGS(dst, arg1, arg2))
+                       return push_inst16(compiler, SUBS | RD3(dst) | RN3(arg1) | RM3(arg2));
+               return push_inst32(compiler, SUB_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+       case SLJIT_SUBC:
+               if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+                       return push_inst16(compiler, SBCS | RD3(dst) | RN3(arg2));
+               return push_inst32(compiler, SBC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+       case SLJIT_MUL:
+               if (!(flags & SET_FLAGS))
+                       return push_inst32(compiler, MUL | RD4(dst) | RN4(arg1) | RM4(arg2));
+               SLJIT_ASSERT(reg_map[TMP_REG2] <= 7 && dst != TMP_REG2);
+               FAIL_IF(push_inst32(compiler, SMULL | RT4(dst) | RD4(TMP_REG2) | RN4(arg1) | RM4(arg2)));
+               /* cmp TMP_REG2, dst asr #31. */
+               return push_inst32(compiler, CMP_W | RN4(TMP_REG2) | 0x70e0 | RM4(dst));
+       case SLJIT_AND:
+               if (!(flags & KEEP_FLAGS)) {
+                       if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
+                               return push_inst16(compiler, ANDS | RD3(dst) | RN3(arg2));
+                       if ((flags & UNUSED_RETURN) && IS_2_LO_REGS(arg1, arg2))
+                               return push_inst16(compiler, TST | RD3(arg1) | RN3(arg2));
+               }
+               return push_inst32(compiler, AND_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+       case SLJIT_OR:
+               if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+                       return push_inst16(compiler, ORRS | RD3(dst) | RN3(arg2));
+               return push_inst32(compiler, ORR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+       case SLJIT_XOR:
+               if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+                       return push_inst16(compiler, EORS | RD3(dst) | RN3(arg2));
+               return push_inst32(compiler, EOR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+       case SLJIT_SHL:
+               if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+                       return push_inst16(compiler, LSLS | RD3(dst) | RN3(arg2));
+               return push_inst32(compiler, LSL_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+       case SLJIT_LSHR:
+               if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+                       return push_inst16(compiler, LSRS | RD3(dst) | RN3(arg2));
+               return push_inst32(compiler, LSR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+       case SLJIT_ASHR:
+               if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2))
+                       return push_inst16(compiler, ASRS | RD3(dst) | RN3(arg2));
+               return push_inst32(compiler, ASR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+       }
+
+       SLJIT_ASSERT_STOP();
+       return SLJIT_SUCCESS;
+}
+
+#define STORE          0x01
+#define SIGNED         0x02
+
+#define WORD_SIZE      0x00
+#define BYTE_SIZE      0x04
+#define HALF_SIZE      0x08
+
+#define UPDATE         0x10
+#define ARG_TEST       0x20
+
+#define IS_WORD_SIZE(flags)            (!(flags & (BYTE_SIZE | HALF_SIZE)))
+#define OFFSET_CHECK(imm, shift)       (!(argw & ~(imm << shift)))
+
+/*
+  1st letter:
+  w = word
+  b = byte
+  h = half
+
+  2nd letter:
+  s = signed
+  u = unsigned
+
+  3rd letter:
+  l = load
+  s = store
+*/
+
+static SLJIT_CONST sljit_uw sljit_mem16[12] = {
+/* w u l */ 0x5800 /* ldr */,
+/* w u s */ 0x5000 /* str */,
+/* w s l */ 0x5800 /* ldr */,
+/* w s s */ 0x5000 /* str */,
+
+/* b u l */ 0x5c00 /* ldrb */,
+/* b u s */ 0x5400 /* strb */,
+/* b s l */ 0x5600 /* ldrsb */,
+/* b s s */ 0x5400 /* strb */,
+
+/* h u l */ 0x5a00 /* ldrh */,
+/* h u s */ 0x5200 /* strh */,
+/* h s l */ 0x5e00 /* ldrsh */,
+/* h s s */ 0x5200 /* strh */,
+};
+
+static SLJIT_CONST sljit_uw sljit_mem16_imm5[12] = {
+/* w u l */ 0x6800 /* ldr imm5 */,
+/* w u s */ 0x6000 /* str imm5 */,
+/* w s l */ 0x6800 /* ldr imm5 */,
+/* w s s */ 0x6000 /* str imm5 */,
+
+/* b u l */ 0x7800 /* ldrb imm5 */,
+/* b u s */ 0x7000 /* strb imm5 */,
+/* b s l */ 0x0000 /* not allowed */,
+/* b s s */ 0x7000 /* strb imm5 */,
+
+/* h u l */ 0x8800 /* ldrh imm5 */,
+/* h u s */ 0x8000 /* strh imm5 */,
+/* h s l */ 0x0000 /* not allowed */,
+/* h s s */ 0x8000 /* strh imm5 */,
+};
+
+#define MEM_IMM8       0xc00
+#define MEM_IMM12      0x800000
+static SLJIT_CONST sljit_uw sljit_mem32[12] = {
+/* w u l */ 0xf8500000 /* ldr.w */,
+/* w u s */ 0xf8400000 /* str.w */,
+/* w s l */ 0xf8500000 /* ldr.w */,
+/* w s s */ 0xf8400000 /* str.w */,
+
+/* b u l */ 0xf8100000 /* ldrb.w */,
+/* b u s */ 0xf8000000 /* strb.w */,
+/* b s l */ 0xf9100000 /* ldrsb.w */,
+/* b s s */ 0xf8000000 /* strb.w */,
+
+/* h u l */ 0xf8300000 /* ldrh.w */,
+/* h u s */ 0xf8200000 /* strsh.w */,
+/* h s l */ 0xf9300000 /* ldrsh.w */,
+/* h s s */ 0xf8200000 /* strsh.w */,
+};
+
+/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */
+static int emit_set_delta(struct sljit_compiler *compiler, int dst, int reg, sljit_w value)
+{
+       if (value >= 0) {
+               if (value <= 0xfff)
+                       return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(value));
+               value = get_imm(value);
+               if (value != INVALID_IMM)
+                       return push_inst32(compiler, ADD_WI | RD4(dst) | RN4(reg) | value);
+       }
+       else {
+               value = -value;
+               if (value <= 0xfff)
+                       return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(value));
+               value = get_imm(value);
+               if (value != INVALID_IMM)
+                       return push_inst32(compiler, SUB_WI | RD4(dst) | RN4(reg) | value);
+       }
+       return SLJIT_ERR_UNSUPPORTED;
+}
+
+/* Can perform an operation using at most 1 instruction. */
+static int getput_arg_fast(struct sljit_compiler *compiler, int flags, int reg, int arg, sljit_w argw)
+{
+       int tmp;
+
+       SLJIT_ASSERT(arg & SLJIT_MEM);
+
+       if (SLJIT_UNLIKELY(flags & UPDATE)) {
+               if ((arg & 0xf) && !(arg & 0xf0) && argw <= 0xff && argw >= -0xff) {
+                       flags &= ~UPDATE;
+                       arg &= 0xf;
+                       if (SLJIT_UNLIKELY(flags & ARG_TEST))
+                               return 1;
+
+                       if (argw >= 0)
+                               argw |= 0x200;
+                       else {
+                               argw = -argw;
+                       }
+                       SLJIT_ASSERT(argw >= 0 && (argw & 0xff) <= 0xff);
+                       FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | 0x100 | argw));
+                       return -1;
+               }
+               return (flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
+       }
+
+       if (SLJIT_UNLIKELY(arg & 0xf0)) {
+               argw &= 0x3;
+               tmp = (arg >> 4) & 0xf;
+               arg &= 0xf;
+               if (SLJIT_UNLIKELY(flags & ARG_TEST))
+                       return 1;
+
+               if (!argw && IS_3_LO_REGS(reg, arg, tmp))
+                       FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp)));
+               else
+                       FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp) | (argw << 4)));
+               return -1;
+       }
+
+       if (!(arg & 0xf) || argw > 0xfff || argw < -0xff)
+               return (flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
+
+       if (SLJIT_UNLIKELY(flags & ARG_TEST))
+               return 1;
+
+       arg &= 0xf;
+       if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) {
+               tmp = 3;
+               if (IS_WORD_SIZE(flags)) {
+                       if (OFFSET_CHECK(0x1f, 2))
+                               tmp = 2;
+               }
+               else if (flags & BYTE_SIZE)
+               {
+                       if (OFFSET_CHECK(0x1f, 0))
+                               tmp = 0;
+               }
+               else {
+                       SLJIT_ASSERT(flags & HALF_SIZE);
+                       if (OFFSET_CHECK(0x1f, 1))
+                               tmp = 1;
+               }
+
+               if (tmp != 3) {
+                       FAIL_IF(push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | (argw << (6 - tmp))));
+                       return -1;
+               }
+       }
+
+       /* SP based immediate. */
+       if (SLJIT_UNLIKELY(arg == SLJIT_LOCALS_REG) && OFFSET_CHECK(0xff, 2) && IS_WORD_SIZE(flags) && reg_map[reg] <= 7) {
+               FAIL_IF(push_inst16(compiler, STR_SP | ((flags & STORE) ? 0 : 0x800) | RDN3(reg) | (argw >> 2)));
+               return -1;
+       }
+
+       if (argw >= 0)
+               FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw));
+       else
+               FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | -argw));
+       return -1;
+}
+
+/* see getput_arg below.
+   Note: can_cache is called only for binary operators. Those
+   operators always uses word arguments without write back. */
+static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+{
+       /* Simple operation except for updates. */
+       if ((arg & 0xf0) || !(next_arg & SLJIT_MEM))
+               return 0;
+
+       if (!(arg & 0xf)) {
+               if ((sljit_uw)(argw - next_argw) <= 0xfff || (sljit_uw)(next_argw - argw) <= 0xfff)
+                       return 1;
+               return 0;
+       }
+
+       if (argw == next_argw)
+               return 1;
+
+       if (arg == next_arg && ((sljit_uw)(argw - next_argw) <= 0xfff || (sljit_uw)(next_argw - argw) <= 0xfff))
+               return 1;
+
+       return 0;
+}
+
+/* Emit the necessary instructions. See can_cache above. */
+static int getput_arg(struct sljit_compiler *compiler, int flags, int reg, int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+{
+       int tmp_r;
+       sljit_w tmp;
+
+       SLJIT_ASSERT(arg & SLJIT_MEM);
+       if (!(next_arg & SLJIT_MEM)) {
+               next_arg = 0;
+               next_argw = 0;
+       }
+
+       tmp_r = (flags & STORE) ? TMP_REG3 : reg;
+
+       if (SLJIT_UNLIKELY(flags & UPDATE)) {
+               flags &= ~UPDATE;
+               /* Update only applies if a base register exists. */
+               if (arg & 0xf) {
+                       /* There is no caching here. */
+                       tmp = (arg & 0xf0) >> 4;
+                       arg &= 0xf;
+
+                       if (!tmp) {
+                               if (!(argw & ~0xfff)) {
+                                       FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw));
+                                       return push_inst32(compiler, ADDWI | RD4(arg) | RN4(arg) | IMM12(argw));
+                               }
+
+                               if (compiler->cache_arg == SLJIT_MEM) {
+                                       if (argw == compiler->cache_argw) {
+                                               tmp = TMP_REG3;
+                                               argw = 0;
+                                       }
+                                       else if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
+                                               FAIL_IF(compiler->error);
+                                               compiler->cache_argw = argw;
+                                               tmp = TMP_REG3;
+                                               argw = 0;
+                                       }
+                               }
+
+                               if (argw) {
+                                       FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+                                       compiler->cache_arg = SLJIT_MEM;
+                                       compiler->cache_argw = argw;
+                                       tmp = TMP_REG3;
+                                       argw = 0;
+                               }
+                       }
+
+                       argw &= 0x3;
+                       if (!argw && IS_3_LO_REGS(reg, arg, tmp)) {
+                               FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp)));
+                               return push_inst16(compiler, ADD | SET_REGS44(arg, tmp));
+                       }
+                       FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp) | (argw << 4)));
+                       return push_inst32(compiler, ADD_W | RD4(arg) | RN4(arg) | RM4(tmp) | (argw << 6));
+               }
+       }
+
+       SLJIT_ASSERT(!(arg & 0xf0));
+
+       if (compiler->cache_arg == arg) {
+               if (!((argw - compiler->cache_argw) & ~0xfff))
+                       return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | (argw - compiler->cache_argw));
+               if (!((compiler->cache_argw - argw) & ~0xff))
+                       return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(TMP_REG3) | (compiler->cache_argw - argw));
+               if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
+                       FAIL_IF(compiler->error);
+                       return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | 0);
+               }
+       }
+
+       next_arg = (arg & 0xf) && (arg == next_arg);
+       arg &= 0xf;
+       if (arg && compiler->cache_arg == SLJIT_MEM && compiler->cache_argw == argw)
+               return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3));
+
+       compiler->cache_argw = argw;
+       if (next_arg && emit_set_delta(compiler, TMP_REG3, arg, argw) != SLJIT_ERR_UNSUPPORTED) {
+               FAIL_IF(compiler->error);
+               compiler->cache_arg = SLJIT_MEM | arg;
+               arg = 0;
+       }
+       else {
+               FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+               compiler->cache_arg = SLJIT_MEM;
+
+               if (next_arg) {
+                       FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, arg)));
+                       compiler->cache_arg = SLJIT_MEM | arg;
+                       arg = 0;
+               }
+       }
+
+       if (arg)
+               return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3));
+       return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | 0);
+}
+
+static SLJIT_INLINE int emit_op_mem(struct sljit_compiler *compiler, int flags, int reg, int arg, sljit_w argw)
+{
+       if (getput_arg_fast(compiler, flags, reg, arg, argw))
+               return compiler->error;
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+       return getput_arg(compiler, flags, reg, arg, argw, 0, 0);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       int size;
+       sljit_ins push;
+
+       CHECK_ERROR();
+       check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+
+       push = (1 << 4);
+       if (saveds >= 5)
+               push |= 1 << 11;
+       if (saveds >= 4)
+               push |= 1 << 10;
+       if (saveds >= 3)
+               push |= 1 << 8;
+       if (saveds >= 2)
+               push |= 1 << 7;
+       if (saveds >= 1)
+               push |= 1 << 6;
+        if (temporaries >= 5)
+               push |= 1 << 5;
+       FAIL_IF(saveds >= 3
+               ? push_inst32(compiler, PUSH_W | (1 << 14) | push)
+               : push_inst16(compiler, PUSH | push));
+
+       /* Stack must be aligned to 8 bytes: */
+       size = (3 + saveds) * sizeof(sljit_uw);
+       local_size += size;
+       local_size = (local_size + 7) & ~7;
+       local_size -= size;
+       compiler->local_size = local_size;
+       if (local_size > 0) {
+               if (local_size <= (127 << 2))
+                       FAIL_IF(push_inst16(compiler, SUB_SP | (local_size >> 2)));
+               else
+                       FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_LOCALS_REG, SLJIT_LOCALS_REG, local_size));
+       }
+
+       if (args >= 1)
+               FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG1, SLJIT_TEMPORARY_REG1)));
+       if (args >= 2)
+               FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG2, SLJIT_TEMPORARY_REG2)));
+       if (args >= 3)
+               FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG3, SLJIT_TEMPORARY_REG3)));
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       int size;
+
+       CHECK_ERROR_VOID();
+       check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+
+       size = (3 + saveds) * sizeof(sljit_uw);
+       local_size += size;
+       local_size = (local_size + 7) & ~7;
+       local_size -= size;
+       compiler->local_size = local_size;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+{
+       sljit_ins pop;
+
+       CHECK_ERROR();
+       check_sljit_emit_return(compiler, op, src, srcw);
+
+       FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+
+       if (compiler->local_size > 0) {
+               if (compiler->local_size <= (127 << 2))
+                       FAIL_IF(push_inst16(compiler, ADD_SP | (compiler->local_size >> 2)));
+               else
+                       FAIL_IF(emit_op_imm(compiler, SLJIT_ADD | ARG2_IMM, SLJIT_LOCALS_REG, SLJIT_LOCALS_REG, compiler->local_size));
+       }
+
+       pop = (1 << 4);
+       if (compiler->saveds >= 5)
+               pop |= 1 << 11;
+       if (compiler->saveds >= 4)
+               pop |= 1 << 10;
+       if (compiler->saveds >= 3)
+               pop |= 1 << 8;
+       if (compiler->saveds >= 2)
+               pop |= 1 << 7;
+       if (compiler->saveds >= 1)
+               pop |= 1 << 6;
+        if (compiler->temporaries >= 5)
+               pop |= 1 << 5;
+       return compiler->saveds >= 3
+               ? push_inst32(compiler, POP_W | (1 << 15) | pop)
+               : push_inst16(compiler, POP | pop);
+}
+
+/* --------------------------------------------------------------------- */
+/*  Operators                                                            */
+/* --------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__GNUC__)
+extern unsigned int __aeabi_uidivmod(unsigned numerator, unsigned denominator);
+extern unsigned int __aeabi_idivmod(unsigned numerator, unsigned denominator);
+#else
+#error "Software divmod functions are needed"
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
+{
+       CHECK_ERROR();
+       check_sljit_emit_op0(compiler, op);
+
+       op = GET_OPCODE(op);
+       switch (op) {
+       case SLJIT_BREAKPOINT:
+               push_inst16(compiler, BKPT);
+               break;
+       case SLJIT_NOP:
+               push_inst16(compiler, NOP);
+               break;
+       case SLJIT_UMUL:
+       case SLJIT_SMUL:
+               return push_inst32(compiler, (op == SLJIT_UMUL ? UMULL : SMULL)
+                       | (reg_map[SLJIT_TEMPORARY_REG2] << 8)
+                       | (reg_map[SLJIT_TEMPORARY_REG1] << 12)
+                       | (reg_map[SLJIT_TEMPORARY_REG1] << 16)
+                       | reg_map[SLJIT_TEMPORARY_REG2]);
+       case SLJIT_UDIV:
+       case SLJIT_SDIV:
+               if (compiler->temporaries >= 4) {
+                       FAIL_IF(push_inst32(compiler, 0xf84d2d04 /* str r2, [sp, #-4]! */));
+                       FAIL_IF(push_inst32(compiler, 0xf84dcd04 /* str ip, [sp, #-4]! */));
+               } else if (compiler->temporaries >= 3)
+                       FAIL_IF(push_inst32(compiler, 0xf84d2d08 /* str r2, [sp, #-8]! */));
+#if defined(__GNUC__)
+               FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
+                       (op == SLJIT_UDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
+#else
+#error "Software divmod functions are needed"
+#endif
+               if (compiler->temporaries >= 4) {
+                       FAIL_IF(push_inst32(compiler, 0xf85dcb04 /* ldr ip, [sp], #4 */));
+                       return push_inst32(compiler, 0xf85d2b04 /* ldr r2, [sp], #4 */);
+               } else if (compiler->temporaries >= 3)
+                       return push_inst32(compiler, 0xf85d2b08 /* ldr r2, [sp], #8 */);
+               return SLJIT_SUCCESS;
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       int op_type, dst_r, flags;
+
+       CHECK_ERROR();
+       check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
+
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+
+       op_type = GET_OPCODE(op);
+       dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG1;
+
+       if (op_type >= SLJIT_MOV && op_type <= SLJIT_MOVU_SI) {
+               switch (op_type) {
+               case SLJIT_MOV:
+               case SLJIT_MOV_UI:
+               case SLJIT_MOV_SI:
+                       flags = WORD_SIZE;
+                       break;
+               case SLJIT_MOV_UB:
+                       flags = BYTE_SIZE;
+                       if (src & SLJIT_IMM)
+                               srcw = (unsigned char)srcw;
+                       break;
+               case SLJIT_MOV_SB:
+                       flags = BYTE_SIZE | SIGNED;
+                       if (src & SLJIT_IMM)
+                               srcw = (signed char)srcw;
+                       break;
+               case SLJIT_MOV_UH:
+                       flags = HALF_SIZE;
+                       if (src & SLJIT_IMM)
+                               srcw = (unsigned short)srcw;
+                       break;
+               case SLJIT_MOV_SH:
+                       flags = HALF_SIZE | SIGNED;
+                       if (src & SLJIT_IMM)
+                               srcw = (signed short)srcw;
+                       break;
+               case SLJIT_MOVU:
+               case SLJIT_MOVU_UI:
+               case SLJIT_MOVU_SI:
+                       flags = WORD_SIZE | UPDATE;
+                       break;
+               case SLJIT_MOVU_UB:
+                       flags = BYTE_SIZE | UPDATE;
+                       if (src & SLJIT_IMM)
+                               srcw = (unsigned char)srcw;
+                       break;
+               case SLJIT_MOVU_SB:
+                       flags = BYTE_SIZE | SIGNED | UPDATE;
+                       if (src & SLJIT_IMM)
+                               srcw = (signed char)srcw;
+                       break;
+               case SLJIT_MOVU_UH:
+                       flags = HALF_SIZE | UPDATE;
+                       if (src & SLJIT_IMM)
+                               srcw = (unsigned short)srcw;
+                       break;
+               case SLJIT_MOVU_SH:
+                       flags = HALF_SIZE | SIGNED | UPDATE;
+                       if (src & SLJIT_IMM)
+                               srcw = (signed short)srcw;
+                       break;
+               default:
+                       SLJIT_ASSERT_STOP();
+                       flags = 0;
+                       break;
+               }
+
+               if (src & SLJIT_IMM)
+                       FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG1, srcw));
+               else if (src & SLJIT_MEM) {
+                       if (getput_arg_fast(compiler, flags, dst_r, src, srcw))
+                               FAIL_IF(compiler->error);
+                       else
+                               FAIL_IF(getput_arg(compiler, flags, dst_r, src, srcw, dst, dstw));
+               } else {
+                       if (dst_r != TMP_REG1)
+                               return emit_op_imm(compiler, op_type, dst_r, TMP_REG1, src);
+                       dst_r = src;
+               }
+
+               if (dst & SLJIT_MEM) {
+                       if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw))
+                               return compiler->error;
+                       else
+                               return getput_arg(compiler, flags | STORE, dst_r, dst, dstw, 0, 0);
+               }
+               return SLJIT_SUCCESS;
+       }
+
+       if (op_type == SLJIT_NEG) {
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+               compiler->skip_checks = 1;
+#endif
+               return sljit_emit_op2(compiler, GET_FLAGS(op) | SLJIT_SUB, dst, dstw, SLJIT_IMM, 0, src, srcw);
+       }
+
+       flags = (GET_FLAGS(op) ? SET_FLAGS : 0) | ((op & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0);
+       if (src & SLJIT_MEM) {
+               if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG2, src, srcw))
+                       FAIL_IF(compiler->error);
+               else
+                       FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src, srcw, dst, dstw));
+               src = TMP_REG2;
+       }
+
+       if (src & SLJIT_IMM)
+               flags |= ARG2_IMM;
+       else
+               srcw = src;
+
+       emit_op_imm(compiler, flags | op_type, dst_r, TMP_REG1, srcw);
+
+       if (dst & SLJIT_MEM) {
+               if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw))
+                       return compiler->error;
+               else
+                       return getput_arg(compiler, flags | STORE, dst_r, dst, dstw, 0, 0);
+       }
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       int dst_r, flags;
+
+       CHECK_ERROR();
+       check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+
+       dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG1;
+       flags = (GET_FLAGS(op) ? SET_FLAGS : 0) | ((op & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0);
+
+       if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, WORD_SIZE | STORE | ARG_TEST, TMP_REG1, dst, dstw))
+               flags |= SLOW_DEST;
+
+       if (src1 & SLJIT_MEM) {
+               if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG1, src1, src1w))
+                       FAIL_IF(compiler->error);
+               else
+                       flags |= SLOW_SRC1;
+       }
+       if (src2 & SLJIT_MEM) {
+               if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG2, src2, src2w))
+                       FAIL_IF(compiler->error);
+               else
+                       flags |= SLOW_SRC2;
+       }
+
+       if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
+               if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
+                       FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src2, src2w, src1, src1w));
+                       FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG1, src1, src1w, dst, dstw));
+               }
+               else {
+                       FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG1, src1, src1w, src2, src2w));
+                       FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src2, src2w, dst, dstw));
+               }
+       }
+       else if (flags & SLOW_SRC1)
+               FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG1, src1, src1w, dst, dstw));
+       else if (flags & SLOW_SRC2)
+               FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src2, src2w, dst, dstw));
+
+       if (src1 & SLJIT_MEM)
+               src1 = TMP_REG1;
+       if (src2 & SLJIT_MEM)
+               src2 = TMP_REG2;
+
+       if (src1 & SLJIT_IMM)
+               flags |= ARG1_IMM;
+       else
+               src1w = src1;
+       if (src2 & SLJIT_IMM)
+               flags |= ARG2_IMM;
+       else
+               src2w = src2;
+
+       if (dst == SLJIT_UNUSED)
+               flags |= UNUSED_RETURN;
+
+       if (GET_OPCODE(op) == SLJIT_MUL && (op & SLJIT_SET_O))
+               flags |= SET_MULOV;
+
+       emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src1w, src2w);
+
+       if (dst & SLJIT_MEM) {
+               if (!(flags & SLOW_DEST)) {
+                       getput_arg_fast(compiler, WORD_SIZE | STORE, dst_r, dst, dstw);
+                       return compiler->error;
+               }
+               return getput_arg(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, 0, 0);
+       }
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
+{
+       check_sljit_get_register_index(reg);
+       return reg_map[reg];
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, int size)
+{
+       CHECK_ERROR();
+       check_sljit_emit_op_custom(compiler, instruction, size);
+       SLJIT_ASSERT(size == 2 || size == 4);
+
+       if (size == 2)
+               return push_inst16(compiler, *(sljit_uh*)instruction);
+       return push_inst32(compiler, *(sljit_ins*)instruction);
+}
+
+/* --------------------------------------------------------------------- */
+/*  Floating point operators                                             */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
+{
+       return 1;
+}
+
+static int emit_fop_mem(struct sljit_compiler *compiler, int flags, int reg, int arg, sljit_w argw)
+{
+       sljit_w tmp;
+       sljit_w inst = VSTR | ((flags & STORE) ? 0 : 0x00100000);
+
+       SLJIT_ASSERT(arg & SLJIT_MEM);
+
+       /* Fast loads and stores. */
+       if (SLJIT_UNLIKELY(arg & 0xf0)) {
+               FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG2) | RN4(arg & 0xf) | RM4((arg & 0xf0) >> 4) | ((argw & 0x3) << 6)));
+               arg = SLJIT_MEM | TMP_REG2;
+               argw = 0;
+       }
+
+       if (arg & 0xf) {
+               if (!(argw & ~0x3fc))
+                       return push_inst32(compiler, inst | 0x800000 | RN4(arg & 0xf) | DD4(reg) | (argw >> 2));
+               if (!(-argw & ~0x3fc))
+                       return push_inst32(compiler, inst | RN4(arg & 0xf) | DD4(reg) | (-argw >> 2));
+       }
+
+       SLJIT_ASSERT(!(arg & 0xf0));
+       if (compiler->cache_arg == arg) {
+               tmp = argw - compiler->cache_argw;
+               if (!(tmp & ~0x3fc))
+                       return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg) | (tmp >> 2));
+               if (!(-tmp & ~0x3fc))
+                       return push_inst32(compiler, inst | RN4(TMP_REG3) | DD4(reg) | (-tmp >> 2));
+               if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, tmp) != SLJIT_ERR_UNSUPPORTED) {
+                       FAIL_IF(compiler->error);
+                       compiler->cache_argw = argw;
+                       return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg));
+               }
+       }
+
+       compiler->cache_arg = arg;
+       compiler->cache_argw = argw;
+
+       if (SLJIT_UNLIKELY(!(arg & 0xf)))
+               FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+       else if (emit_set_delta(compiler, TMP_REG3, arg & 0xf, argw) != SLJIT_ERR_UNSUPPORTED)
+               FAIL_IF(compiler->error);
+       else {
+               FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+               if (arg & 0xf)
+                       FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, (arg & 0xf))));
+       }
+       return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       int dst_r;
+
+       CHECK_ERROR();
+       check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
+
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+
+       if (GET_OPCODE(op) == SLJIT_FCMP) {
+               if (dst & SLJIT_MEM) {
+                       emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);
+                       dst = TMP_FREG1;
+               }
+               if (src & SLJIT_MEM) {
+                       emit_fop_mem(compiler, 0, TMP_FREG2, src, srcw);
+                       src = TMP_FREG2;
+               }
+               FAIL_IF(push_inst32(compiler, VCMP_F64 | DD4(dst) | DM4(src)));
+               return push_inst32(compiler, VMRS);
+       }
+
+       dst_r = (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) ? dst : TMP_FREG1;
+       if (src & SLJIT_MEM) {
+               emit_fop_mem(compiler, 0, dst_r, src, srcw);
+               src = dst_r;
+       }
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_FMOV:
+               if (src != dst_r)
+                       FAIL_IF(push_inst32(compiler, VMOV_F64 | DD4(dst_r) | DM4(src)));
+               break;
+       case SLJIT_FNEG:
+               FAIL_IF(push_inst32(compiler, VNEG_F64 | DD4(dst_r) | DM4(src)));
+               break;
+       case SLJIT_FABS:
+               FAIL_IF(push_inst32(compiler, VABS_F64 | DD4(dst_r) | DM4(src)));
+               break;
+       }
+
+       if (dst & SLJIT_MEM)
+               return emit_fop_mem(compiler, STORE, TMP_FREG1, dst, dstw);
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       int dst_r;
+
+       CHECK_ERROR();
+       check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+
+       dst_r = (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) ? dst : TMP_FREG1;
+       if (src1 & SLJIT_MEM) {
+               emit_fop_mem(compiler, 0, TMP_FREG1, src1, src1w);
+               src1 = TMP_FREG1;
+       }
+       if (src2 & SLJIT_MEM) {
+               emit_fop_mem(compiler, 0, TMP_FREG2, src2, src2w);
+               src2 = TMP_FREG2;
+       }
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_FADD:
+               FAIL_IF(push_inst32(compiler, VADD_F64 | DD4(dst_r) | DN4(src1) | DM4(src2)));
+               break;
+       case SLJIT_FSUB:
+               FAIL_IF(push_inst32(compiler, VSUB_F64 | DD4(dst_r) | DN4(src1) | DM4(src2)));
+               break;
+       case SLJIT_FMUL:
+               FAIL_IF(push_inst32(compiler, VMUL_F64 | DD4(dst_r) | DN4(src1) | DM4(src2)));
+               break;
+       case SLJIT_FDIV:
+               FAIL_IF(push_inst32(compiler, VDIV_F64 | DD4(dst_r) | DN4(src1) | DM4(src2)));
+               break;
+       }
+
+       if (dst & SLJIT_MEM)
+               return emit_fop_mem(compiler, STORE, TMP_FREG1, dst, dstw);
+       return SLJIT_SUCCESS;
+}
+
+/* --------------------------------------------------------------------- */
+/*  Other instructions                                                   */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
+{
+       int size;
+
+       CHECK_ERROR();
+       check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+
+       size = (3 + saveds) * sizeof(sljit_uw);
+       local_size += size;
+       local_size = (local_size + 7) & ~7;
+       local_size -= size;
+       compiler->local_size = local_size;
+
+       if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
+               return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG3));
+       else if (dst & SLJIT_MEM) {
+               if (getput_arg_fast(compiler, WORD_SIZE | STORE, TMP_REG3, dst, dstw))
+                       return compiler->error;
+               FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, TMP_REG3)));
+               compiler->cache_arg = 0;
+               compiler->cache_argw = 0;
+               return getput_arg(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, 0, 0);
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+{
+       CHECK_ERROR();
+       check_sljit_emit_fast_return(compiler, src, srcw);
+
+       if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
+               FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, src)));
+       else if (src & SLJIT_MEM) {
+               if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG3, src, srcw))
+                       FAIL_IF(compiler->error);
+               else {
+                       compiler->cache_arg = 0;
+                       compiler->cache_argw = 0;
+                       FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src, srcw, 0, 0));
+                       FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, TMP_REG2)));
+               }
+       }
+       else if (src & SLJIT_IMM)
+               FAIL_IF(load_immediate(compiler, TMP_REG3, srcw));
+       return push_inst16(compiler, BLX | RN3(TMP_REG3));
+}
+
+/* --------------------------------------------------------------------- */
+/*  Conditional instructions                                             */
+/* --------------------------------------------------------------------- */
+
+static sljit_uw get_cc(int type)
+{
+       switch (type) {
+       case SLJIT_C_EQUAL:
+       case SLJIT_C_MUL_NOT_OVERFLOW:
+       case SLJIT_C_FLOAT_EQUAL:
+               return 0x0;
+
+       case SLJIT_C_NOT_EQUAL:
+       case SLJIT_C_MUL_OVERFLOW:
+       case SLJIT_C_FLOAT_NOT_EQUAL:
+               return 0x1;
+
+       case SLJIT_C_LESS:
+       case SLJIT_C_FLOAT_LESS:
+               return 0x3;
+
+       case SLJIT_C_GREATER_EQUAL:
+       case SLJIT_C_FLOAT_GREATER_EQUAL:
+               return 0x2;
+
+       case SLJIT_C_GREATER:
+       case SLJIT_C_FLOAT_GREATER:
+               return 0x8;
+
+       case SLJIT_C_LESS_EQUAL:
+       case SLJIT_C_FLOAT_LESS_EQUAL:
+               return 0x9;
+
+       case SLJIT_C_SIG_LESS:
+               return 0xb;
+
+       case SLJIT_C_SIG_GREATER_EQUAL:
+               return 0xa;
+
+       case SLJIT_C_SIG_GREATER:
+               return 0xc;
+
+       case SLJIT_C_SIG_LESS_EQUAL:
+               return 0xd;
+
+       case SLJIT_C_OVERFLOW:
+       case SLJIT_C_FLOAT_NAN:
+               return 0x6;
+
+       case SLJIT_C_NOT_OVERFLOW:
+       case SLJIT_C_FLOAT_NOT_NAN:
+               return 0x7;
+
+       default: /* SLJIT_JUMP */
+               return 0xe;
+       }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+       struct sljit_label *label;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_label(compiler);
+
+       if (compiler->last_label && compiler->last_label->size == compiler->size)
+               return compiler->last_label;
+
+       label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+       PTR_FAIL_IF(!label);
+       set_label(label, compiler);
+       return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type)
+{
+       struct sljit_jump *jump;
+       int cc;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_jump(compiler, type);
+
+       jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+       PTR_FAIL_IF(!jump);
+       set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+       type &= 0xff;
+
+       /* In ARM, we don't need to touch the arguments. */
+       PTR_FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0));
+       if (type < SLJIT_JUMP) {
+               jump->flags |= IS_CONDITIONAL;
+               cc = get_cc(type);
+               jump->flags |= cc << 8;
+               PTR_FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+       }
+
+       jump->addr = compiler->size;
+       if (type <= SLJIT_JUMP)
+               PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG1)));
+       else {
+               jump->flags |= IS_BL;
+               PTR_FAIL_IF(push_inst16(compiler, BLX | RN3(TMP_REG1)));
+       }
+
+       return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
+{
+       struct sljit_jump *jump;
+
+       CHECK_ERROR();
+       check_sljit_emit_ijump(compiler, type, src, srcw);
+
+       /* In ARM, we don't need to touch the arguments. */
+       if (src & SLJIT_IMM) {
+               jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+               FAIL_IF(!jump);
+               set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
+               jump->u.target = srcw;
+
+               FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0));
+               jump->addr = compiler->size;
+               FAIL_IF(push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1)));
+       }
+       else {
+               if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
+                       return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(src));
+
+               FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw));
+               if (type >= SLJIT_FAST_CALL)
+                       return push_inst16(compiler, BLX | RN3(TMP_REG1));
+       }
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type)
+{
+       int dst_r;
+       sljit_uw cc;
+
+       CHECK_ERROR();
+       check_sljit_emit_cond_value(compiler, op, dst, dstw, type);
+
+       if (dst == SLJIT_UNUSED)
+               return SLJIT_SUCCESS;
+
+       cc = get_cc(type);
+       if (GET_OPCODE(op) == SLJIT_OR && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+               FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+               FAIL_IF(push_inst32(compiler, ORRI | RN4(dst) | RD4(dst) | 0x1));
+               if (op & SLJIT_SET_E) {
+                       if (reg_map[dst] <= 7)
+                               return push_inst16(compiler, ORRS | RD3(dst) | RN3(dst));
+                       return push_inst32(compiler, ORR_W | SET_FLAGS | RD4(TMP_REG1) | RN4(dst) | RM4(dst));
+               }
+               return SLJIT_SUCCESS;
+       }
+
+       dst_r = TMP_REG2;
+       if (op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS && reg_map[dst] <= 7)
+               dst_r = dst;
+
+       FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
+       FAIL_IF(push_inst16(compiler, MOVSI | 0x1 | RDN3(dst_r)));
+       FAIL_IF(push_inst16(compiler, MOVSI | 0x0 | RDN3(dst_r)));
+
+       if (dst_r == TMP_REG2) {
+               if (GET_OPCODE(op) == SLJIT_OR) {
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+                       compiler->skip_checks = 1;
+#endif
+                       return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REG2, 0);
+               }
+               if (dst & SLJIT_MEM)
+                       return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw);
+               else
+                       return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2));
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value)
+{
+       struct sljit_const *const_;
+       int dst_r;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_const(compiler, dst, dstw, init_value);
+
+       const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+       PTR_FAIL_IF(!const_);
+       set_const(const_, compiler);
+
+       dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG1;
+       PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, init_value));
+
+       if (dst & SLJIT_MEM)
+               PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw));
+       return const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+{
+       inline_set_jump_addr(addr, new_addr, 1);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
+{
+       sljit_uh* inst = (sljit_uh*)addr;
+       modify_imm32_const(inst, new_constant);
+       SLJIT_CACHE_FLUSH(inst, inst + 3);
+}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_v5.c b/src/3rdparty/pcre/sljit/sljitNativeARM_v5.c
new file mode 100644 (file)
index 0000000..e3a5873
--- /dev/null
@@ -0,0 +1,2424 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
+{
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+       return "ARMv7" SLJIT_CPUINFO;
+#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       return "ARMv5" SLJIT_CPUINFO;
+#else
+#error "Internal error: Unknown ARM architecture"
+#endif
+}
+
+/* Last register + 1. */
+#define TMP_REG1       (SLJIT_NO_REGISTERS + 1)
+#define TMP_REG2       (SLJIT_NO_REGISTERS + 2)
+#define TMP_REG3       (SLJIT_NO_REGISTERS + 3)
+#define TMP_PC         (SLJIT_NO_REGISTERS + 4)
+
+#define TMP_FREG1      (SLJIT_FLOAT_REG4 + 1)
+#define TMP_FREG2      (SLJIT_FLOAT_REG4 + 2)
+
+/* In ARM instruction words.
+   Cache lines are usually 32 byte aligned. */
+#define CONST_POOL_ALIGNMENT   8
+#define CONST_POOL_EMPTY       0xffffffff
+
+#define ALIGN_INSTRUCTION(ptr) \
+       (sljit_uw*)(((sljit_uw)(ptr) + (CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1) & ~((CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1))
+#define MAX_DIFFERENCE(max_diff) \
+       (((max_diff) / (int)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1))
+
+/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
+static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
+  0, 0, 1, 2, 10, 11, 4, 5, 6, 7, 8, 13, 3, 12, 14, 15
+};
+
+#define RM(rm) (reg_map[rm])
+#define RD(rd) (reg_map[rd] << 12)
+#define RN(rn) (reg_map[rn] << 16)
+
+/* --------------------------------------------------------------------- */
+/*  Instrucion forms                                                     */
+/* --------------------------------------------------------------------- */
+
+/* The instruction includes the AL condition.
+   INST_NAME - CONDITIONAL remove this flag. */
+#define COND_MASK      0xf0000000
+#define CONDITIONAL    0xe0000000
+#define PUSH_POOL      0xff000000
+
+/* DP - Data Processing instruction (use with EMIT_DATA_PROCESS_INS). */
+#define ADC_DP         0x5
+#define ADD_DP         0x4
+#define AND_DP         0x0
+#define B              0xea000000
+#define BIC_DP         0xe
+#define BL             0xeb000000
+#define BLX            0xe12fff30
+#define BX             0xe12fff10
+#define CLZ            0xe16f0f10
+#define CMP_DP         0xa
+#define BKPT           0xe1200070
+#define EOR_DP         0x1
+#define MOV_DP         0xd
+#define MUL            0xe0000090
+#define MVN_DP         0xf
+#define NOP            0xe1a00000
+#define ORR_DP         0xc
+#define PUSH           0xe92d0000
+#define POP            0xe8bd0000
+#define RSB_DP         0x3
+#define RSC_DP         0x7
+#define SBC_DP         0x6
+#define SMULL          0xe0c00090
+#define SUB_DP         0x2
+#define UMULL          0xe0800090
+#define VABS_F64       0xeeb00bc0
+#define VADD_F64       0xee300b00
+#define VCMP_F64       0xeeb40b40
+#define VDIV_F64       0xee800b00
+#define VMOV_F64       0xeeb00b40
+#define VMRS           0xeef1fa10
+#define VMUL_F64       0xee200b00
+#define VNEG_F64       0xeeb10b40
+#define VSTR           0xed000b00
+#define VSUB_F64       0xee300b40
+
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+/* Arm v7 specific instructions. */
+#define MOVW           0xe3000000
+#define MOVT           0xe3400000
+#define SXTB           0xe6af0070
+#define SXTH           0xe6bf0070
+#define UXTB           0xe6ef0070
+#define UXTH           0xe6ff0070
+#endif
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+
+static int push_cpool(struct sljit_compiler *compiler)
+{
+       /* Pushing the constant pool into the instruction stream. */
+       sljit_uw* inst;
+       sljit_uw* cpool_ptr;
+       sljit_uw* cpool_end;
+       int i;
+
+       /* The label could point the address after the constant pool. */
+       if (compiler->last_label && compiler->last_label->size == compiler->size)
+               compiler->last_label->size += compiler->cpool_fill + (CONST_POOL_ALIGNMENT - 1) + 1;
+
+       SLJIT_ASSERT(compiler->cpool_fill > 0 && compiler->cpool_fill <= CPOOL_SIZE);
+       inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
+       FAIL_IF(!inst);
+       compiler->size++;
+       *inst = 0xff000000 | compiler->cpool_fill;
+
+       for (i = 0; i < CONST_POOL_ALIGNMENT - 1; i++) {
+               inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
+               FAIL_IF(!inst);
+               compiler->size++;
+               *inst = 0;
+       }
+
+       cpool_ptr = compiler->cpool;
+       cpool_end = cpool_ptr + compiler->cpool_fill;
+       while (cpool_ptr < cpool_end) {
+               inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
+               FAIL_IF(!inst);
+               compiler->size++;
+               *inst = *cpool_ptr++;
+       }
+       compiler->cpool_diff = CONST_POOL_EMPTY;
+       compiler->cpool_fill = 0;
+       return SLJIT_SUCCESS;
+}
+
+static int push_inst(struct sljit_compiler *compiler, sljit_uw inst)
+{
+       sljit_uw* ptr;
+
+       if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)))
+               FAIL_IF(push_cpool(compiler));
+
+       ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
+       FAIL_IF(!ptr);
+       compiler->size++;
+       *ptr = inst;
+       return SLJIT_SUCCESS;
+}
+
+static int push_inst_with_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)
+{
+       sljit_uw* ptr;
+       sljit_uw cpool_index = CPOOL_SIZE;
+       sljit_uw* cpool_ptr;
+       sljit_uw* cpool_end;
+       sljit_ub* cpool_unique_ptr;
+
+       if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)))
+               FAIL_IF(push_cpool(compiler));
+       else if (compiler->cpool_fill > 0) {
+               cpool_ptr = compiler->cpool;
+               cpool_end = cpool_ptr + compiler->cpool_fill;
+               cpool_unique_ptr = compiler->cpool_unique;
+               do {
+                       if ((*cpool_ptr == literal) && !(*cpool_unique_ptr)) {
+                               cpool_index = cpool_ptr - compiler->cpool;
+                               break;
+                       }
+                       cpool_ptr++;
+                       cpool_unique_ptr++;
+               } while (cpool_ptr < cpool_end);
+       }
+
+       if (cpool_index == CPOOL_SIZE) {
+               /* Must allocate a new entry in the literal pool. */
+               if (compiler->cpool_fill < CPOOL_SIZE) {
+                       cpool_index = compiler->cpool_fill;
+                       compiler->cpool_fill++;
+               }
+               else {
+                       FAIL_IF(push_cpool(compiler));
+                       cpool_index = 0;
+                       compiler->cpool_fill = 1;
+               }
+       }
+
+       SLJIT_ASSERT((inst & 0xfff) == 0);
+       ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
+       FAIL_IF(!ptr);
+       compiler->size++;
+       *ptr = inst | cpool_index;
+
+       compiler->cpool[cpool_index] = literal;
+       compiler->cpool_unique[cpool_index] = 0;
+       if (compiler->cpool_diff == CONST_POOL_EMPTY)
+               compiler->cpool_diff = compiler->size;
+       return SLJIT_SUCCESS;
+}
+
+static int push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)
+{
+       sljit_uw* ptr;
+       if (SLJIT_UNLIKELY((compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)) || compiler->cpool_fill >= CPOOL_SIZE))
+               FAIL_IF(push_cpool(compiler));
+
+       SLJIT_ASSERT(compiler->cpool_fill < CPOOL_SIZE && (inst & 0xfff) == 0);
+       ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
+       FAIL_IF(!ptr);
+       compiler->size++;
+       *ptr = inst | compiler->cpool_fill;
+
+       compiler->cpool[compiler->cpool_fill] = literal;
+       compiler->cpool_unique[compiler->cpool_fill] = 1;
+       compiler->cpool_fill++;
+       if (compiler->cpool_diff == CONST_POOL_EMPTY)
+               compiler->cpool_diff = compiler->size;
+       return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE int prepare_blx(struct sljit_compiler *compiler)
+{
+       /* Place for at least two instruction (doesn't matter whether the first has a literal). */
+       if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4088)))
+               return push_cpool(compiler);
+       return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE int emit_blx(struct sljit_compiler *compiler)
+{
+       /* Must follow tightly the previous instruction (to be able to convert it to bl instruction). */
+       SLJIT_ASSERT(compiler->cpool_diff == CONST_POOL_EMPTY || compiler->size - compiler->cpool_diff < MAX_DIFFERENCE(4092));
+       return push_inst(compiler, BLX | RM(TMP_REG1));
+}
+
+static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_ptr, sljit_uw* const_pool, sljit_uw cpool_size)
+{
+       sljit_uw diff;
+       sljit_uw ind;
+       sljit_uw counter = 0;
+       sljit_uw* clear_const_pool = const_pool;
+       sljit_uw* clear_const_pool_end = const_pool + cpool_size;
+
+       SLJIT_ASSERT(const_pool - code_ptr <= CONST_POOL_ALIGNMENT);
+       /* Set unused flag for all literals in the constant pool.
+          I.e.: unused literals can belong to branches, which can be encoded as B or BL.
+          We can "compress" the constant pool by discarding these literals. */
+       while (clear_const_pool < clear_const_pool_end)
+               *clear_const_pool++ = (sljit_uw)(-1);
+
+       while (last_pc_patch < code_ptr) {
+               /* Data transfer instruction with Rn == r15. */
+               if ((*last_pc_patch & 0x0c0f0000) == 0x040f0000) {
+                       diff = const_pool - last_pc_patch;
+                       ind = (*last_pc_patch) & 0xfff;
+
+                       /* Must be a load instruction with immediate offset. */
+                       SLJIT_ASSERT(ind < cpool_size && !(*last_pc_patch & (1 << 25)) && (*last_pc_patch & (1 << 20)));
+                       if ((int)const_pool[ind] < 0) {
+                               const_pool[ind] = counter;
+                               ind = counter;
+                               counter++;
+                       }
+                       else
+                               ind = const_pool[ind];
+
+                       SLJIT_ASSERT(diff >= 1);
+                       if (diff >= 2 || ind > 0) {
+                               diff = (diff + ind - 2) << 2;
+                               SLJIT_ASSERT(diff <= 0xfff);
+                               *last_pc_patch = (*last_pc_patch & ~0xfff) | diff;
+                       }
+                       else
+                               *last_pc_patch = (*last_pc_patch & ~(0xfff | (1 << 23))) | 0x004;
+               }
+               last_pc_patch++;
+       }
+       return counter;
+}
+
+/* In some rare ocasions we may need future patches. The probability is close to 0 in practice. */
+struct future_patch {
+       struct future_patch* next;
+       int index;
+       int value;
+};
+
+static SLJIT_INLINE int resolve_const_pool_index(struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr)
+{
+       int value;
+       struct future_patch *curr_patch, *prev_patch;
+
+       /* Using the values generated by patch_pc_relative_loads. */
+       if (!*first_patch)
+               value = (int)cpool_start_address[cpool_current_index];
+       else {
+               curr_patch = *first_patch;
+               prev_patch = 0;
+               while (1) {
+                       if (!curr_patch) {
+                               value = (int)cpool_start_address[cpool_current_index];
+                               break;
+                       }
+                       if ((sljit_uw)curr_patch->index == cpool_current_index) {
+                               value = curr_patch->value;
+                               if (prev_patch)
+                                       prev_patch->next = curr_patch->next;
+                               else
+                                       *first_patch = curr_patch->next;
+                               SLJIT_FREE(curr_patch);
+                               break;
+                       }
+                       prev_patch = curr_patch;
+                       curr_patch = curr_patch->next;
+               }
+       }
+
+       if (value >= 0) {
+               if ((sljit_uw)value > cpool_current_index) {
+                       curr_patch = (struct future_patch*)SLJIT_MALLOC(sizeof(struct future_patch));
+                       if (!curr_patch) {
+                               while (*first_patch) {
+                                       curr_patch = *first_patch;
+                                       *first_patch = (*first_patch)->next;
+                                       SLJIT_FREE(curr_patch);
+                               }
+                               return SLJIT_ERR_ALLOC_FAILED;
+                       }
+                       curr_patch->next = *first_patch;
+                       curr_patch->index = value;
+                       curr_patch->value = cpool_start_address[value];
+                       *first_patch = curr_patch;
+               }
+               cpool_start_address[value] = *buf_ptr;
+       }
+       return SLJIT_SUCCESS;
+}
+
+#else
+
+static int push_inst(struct sljit_compiler *compiler, sljit_uw inst)
+{
+       sljit_uw* ptr;
+
+       ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
+       FAIL_IF(!ptr);
+       compiler->size++;
+       *ptr = inst;
+       return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE int emit_imm(struct sljit_compiler *compiler, int reg, sljit_w imm)
+{
+       FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)));
+       return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff));
+}
+
+#endif
+
+static SLJIT_INLINE int detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code)
+{
+       sljit_w diff;
+
+       if (jump->flags & SLJIT_REWRITABLE_JUMP)
+               return 0;
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       if (jump->flags & IS_BL)
+               code_ptr--;
+
+       if (jump->flags & JUMP_ADDR)
+               diff = ((sljit_w)jump->u.target - (sljit_w)(code_ptr + 2));
+       else {
+               SLJIT_ASSERT(jump->flags & JUMP_LABEL);
+               diff = ((sljit_w)(code + jump->u.label->size) - (sljit_w)(code_ptr + 2));
+       }
+
+       /* Branch to Thumb code has not been optimized yet. */
+       if (diff & 0x3)
+               return 0;
+
+       diff >>= 2;
+       if (jump->flags & IS_BL) {
+               if (diff <= 0x01ffffff && diff >= -0x02000000) {
+                       *code_ptr = (BL - CONDITIONAL) | (*(code_ptr + 1) & COND_MASK);
+                       jump->flags |= PATCH_B;
+                       return 1;
+               }
+       }
+       else {
+               if (diff <= 0x01ffffff && diff >= -0x02000000) {
+                       *code_ptr = (B - CONDITIONAL) | (*code_ptr & COND_MASK);
+                       jump->flags |= PATCH_B;
+               }
+       }
+#else
+       if (jump->flags & JUMP_ADDR)
+               diff = ((sljit_w)jump->u.target - (sljit_w)code_ptr);
+       else {
+               SLJIT_ASSERT(jump->flags & JUMP_LABEL);
+               diff = ((sljit_w)(code + jump->u.label->size) - (sljit_w)code_ptr);
+       }
+
+       /* Branch to Thumb code has not been optimized yet. */
+       if (diff & 0x3)
+               return 0;
+
+       diff >>= 2;
+       if (diff <= 0x01ffffff && diff >= -0x02000000) {
+               code_ptr -= 2;
+               *code_ptr = ((jump->flags & IS_BL) ? (BL - CONDITIONAL) : (B - CONDITIONAL)) | (code_ptr[2] & COND_MASK);
+               jump->flags |= PATCH_B;
+               return 1;
+       }
+#endif
+       return 0;
+}
+
+static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr, int flush)
+{
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       sljit_uw *ptr = (sljit_uw*)addr;
+       sljit_uw *inst = (sljit_uw*)ptr[0];
+       sljit_uw mov_pc = ptr[1];
+       int bl = (mov_pc & 0x0000f000) != RD(TMP_PC);
+       sljit_w diff = (sljit_w)(((sljit_w)new_addr - (sljit_w)(inst + 2)) >> 2);
+
+       if (diff <= 0x7fffff && diff >= -0x800000) {
+               /* Turn to branch. */
+               if (!bl) {
+                       inst[0] = (mov_pc & COND_MASK) | (B - CONDITIONAL) | (diff & 0xffffff);
+                       if (flush) {
+                               SLJIT_CACHE_FLUSH(inst, inst + 1);
+                       }
+               } else {
+                       inst[0] = (mov_pc & COND_MASK) | (BL - CONDITIONAL) | (diff & 0xffffff);
+                       inst[1] = NOP;
+                       if (flush) {
+                               SLJIT_CACHE_FLUSH(inst, inst + 2);
+                       }
+               }
+       } else {
+               /* Get the position of the constant. */
+               if (mov_pc & (1 << 23))
+                       ptr = inst + ((mov_pc & 0xfff) >> 2) + 2;
+               else
+                       ptr = inst + 1;
+
+               if (*inst != mov_pc) {
+                       inst[0] = mov_pc;
+                       if (!bl) {
+                               if (flush) {
+                                       SLJIT_CACHE_FLUSH(inst, inst + 1);
+                               }
+                       } else {
+                               inst[1] = BLX | RM(TMP_REG1);
+                               if (flush) {
+                                       SLJIT_CACHE_FLUSH(inst, inst + 2);
+                               }
+                       }
+               }
+               *ptr = new_addr;
+       }
+#else
+       sljit_uw *inst = (sljit_uw*)addr;
+       SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);
+       inst[0] = MOVW | (inst[0] & 0xf000) | ((new_addr << 4) & 0xf0000) | (new_addr & 0xfff);
+       inst[1] = MOVT | (inst[1] & 0xf000) | ((new_addr >> 12) & 0xf0000) | ((new_addr >> 16) & 0xfff);
+       if (flush) {
+               SLJIT_CACHE_FLUSH(inst, inst + 2);
+       }
+#endif
+}
+
+static sljit_uw get_immediate(sljit_uw imm);
+
+static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_w new_constant, int flush)
+{
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       sljit_uw *ptr = (sljit_uw*)addr;
+       sljit_uw *inst = (sljit_uw*)ptr[0];
+       sljit_uw ldr_literal = ptr[1];
+       sljit_uw src2;
+
+       src2 = get_immediate(new_constant);
+       if (src2) {
+               *inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2;
+               if (flush) {
+                       SLJIT_CACHE_FLUSH(inst, inst + 1);
+               }
+               return;
+       }
+
+       src2 = get_immediate(~new_constant);
+       if (src2) {
+               *inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2;
+               if (flush) {
+                       SLJIT_CACHE_FLUSH(inst, inst + 1);
+               }
+               return;
+       }
+
+       if (ldr_literal & (1 << 23))
+               ptr = inst + ((ldr_literal & 0xfff) >> 2) + 2;
+       else
+               ptr = inst + 1;
+
+       if (*inst != ldr_literal) {
+               *inst = ldr_literal;
+               if (flush) {
+                       SLJIT_CACHE_FLUSH(inst, inst + 1);
+               }
+       }
+       *ptr = new_constant;
+#else
+       sljit_uw *inst = (sljit_uw*)addr;
+       SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);
+       inst[0] = MOVW | (inst[0] & 0xf000) | ((new_constant << 4) & 0xf0000) | (new_constant & 0xfff);
+       inst[1] = MOVT | (inst[1] & 0xf000) | ((new_constant >> 12) & 0xf0000) | ((new_constant >> 16) & 0xfff);
+       if (flush) {
+               SLJIT_CACHE_FLUSH(inst, inst + 2);
+       }
+#endif
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
+{
+       struct sljit_memory_fragment *buf;
+       sljit_uw *code;
+       sljit_uw *code_ptr;
+       sljit_uw *buf_ptr;
+       sljit_uw *buf_end;
+       sljit_uw size;
+       sljit_uw word_count;
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       sljit_uw cpool_size;
+       sljit_uw cpool_skip_alignment;
+       sljit_uw cpool_current_index;
+       sljit_uw *cpool_start_address;
+       sljit_uw *last_pc_patch;
+       struct future_patch *first_patch;
+#endif
+
+       struct sljit_label *label;
+       struct sljit_jump *jump;
+       struct sljit_const *const_;
+
+       CHECK_ERROR_PTR();
+       check_sljit_generate_code(compiler);
+       reverse_buf(compiler);
+
+       /* Second code generation pass. */
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       size = compiler->size + (compiler->patches << 1);
+       if (compiler->cpool_fill > 0)
+               size += compiler->cpool_fill + CONST_POOL_ALIGNMENT - 1;
+#else
+       size = compiler->size;
+#endif
+       code = (sljit_uw*)SLJIT_MALLOC_EXEC(size * sizeof(sljit_uw));
+       PTR_FAIL_WITH_EXEC_IF(code);
+       buf = compiler->buf;
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       cpool_size = 0;
+       cpool_skip_alignment = 0;
+       cpool_current_index = 0;
+       cpool_start_address = NULL;
+       first_patch = NULL;
+       last_pc_patch = code;
+#endif
+
+       code_ptr = code;
+       word_count = 0;
+
+       label = compiler->labels;
+       jump = compiler->jumps;
+       const_ = compiler->consts;
+
+       if (label && label->size == 0) {
+               label->addr = (sljit_uw)code;
+               label->size = 0;
+               label = label->next;
+       }
+
+       do {
+               buf_ptr = (sljit_uw*)buf->memory;
+               buf_end = buf_ptr + (buf->used_size >> 2);
+               do {
+                       word_count++;
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+                       if (cpool_size > 0) {
+                               if (cpool_skip_alignment > 0) {
+                                       buf_ptr++;
+                                       cpool_skip_alignment--;
+                               }
+                               else {
+                                       if (SLJIT_UNLIKELY(resolve_const_pool_index(&first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {
+                                               SLJIT_FREE_EXEC(code);
+                                               compiler->error = SLJIT_ERR_ALLOC_FAILED;
+                                               return NULL;
+                                       }
+                                       buf_ptr++;
+                                       if (++cpool_current_index >= cpool_size) {
+                                               SLJIT_ASSERT(!first_patch);
+                                               cpool_size = 0;
+                                               if (label && label->size == word_count) {
+                                                       /* Points after the current instruction. */
+                                                       label->addr = (sljit_uw)code_ptr;
+                                                       label->size = code_ptr - code;
+                                                       label = label->next;
+                                               }
+                                       }
+                               }
+                       }
+                       else if ((*buf_ptr & 0xff000000) != PUSH_POOL) {
+#endif
+                               *code_ptr = *buf_ptr++;
+                               /* These structures are ordered by their address. */
+                               SLJIT_ASSERT(!label || label->size >= word_count);
+                               SLJIT_ASSERT(!jump || jump->addr >= word_count);
+                               SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+                               if (jump && jump->addr == word_count) {
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+                                       if (detect_jump_type(jump, code_ptr, code))
+                                               code_ptr--;
+                                       jump->addr = (sljit_uw)code_ptr;
+#else
+                                       jump->addr = (sljit_uw)(code_ptr - 2);
+                                       if (detect_jump_type(jump, code_ptr, code))
+                                               code_ptr -= 2;
+#endif
+                                       jump = jump->next;
+                               }
+                               if (label && label->size == word_count) {
+                                       /* code_ptr can be affected above. */
+                                       label->addr = (sljit_uw)(code_ptr + 1);
+                                       label->size = (code_ptr + 1) - code;
+                                       label = label->next;
+                               }
+                               if (const_ && const_->addr == word_count) {
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+                                       const_->addr = (sljit_uw)code_ptr;
+#else
+                                       const_->addr = (sljit_uw)(code_ptr - 1);
+#endif
+                                       const_ = const_->next;
+                               }
+                               code_ptr++;
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+                       }
+                       else {
+                               /* Fortunately, no need to shift. */
+                               cpool_size = *buf_ptr++ & ~PUSH_POOL;
+                               SLJIT_ASSERT(cpool_size > 0);
+                               cpool_start_address = ALIGN_INSTRUCTION(code_ptr + 1);
+                               cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, cpool_size);
+                               if (cpool_current_index > 0) {
+                                       /* Unconditional branch. */
+                                       *code_ptr = B | (((cpool_start_address - code_ptr) + cpool_current_index - 2) & ~PUSH_POOL);
+                                       code_ptr = cpool_start_address + cpool_current_index;
+                               }
+                               cpool_skip_alignment = CONST_POOL_ALIGNMENT - 1;
+                               cpool_current_index = 0;
+                               last_pc_patch = code_ptr;
+                       }
+#endif
+               } while (buf_ptr < buf_end);
+               buf = buf->next;
+       } while (buf);
+
+       SLJIT_ASSERT(!label);
+       SLJIT_ASSERT(!jump);
+       SLJIT_ASSERT(!const_);
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       SLJIT_ASSERT(cpool_size == 0);
+       if (compiler->cpool_fill > 0) {
+               cpool_start_address = ALIGN_INSTRUCTION(code_ptr);
+               cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, compiler->cpool_fill);
+               if (cpool_current_index > 0)
+                       code_ptr = cpool_start_address + cpool_current_index;
+
+               buf_ptr = compiler->cpool;
+               buf_end = buf_ptr + compiler->cpool_fill;
+               cpool_current_index = 0;
+               while (buf_ptr < buf_end) {
+                       if (SLJIT_UNLIKELY(resolve_const_pool_index(&first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {
+                               SLJIT_FREE_EXEC(code);
+                               compiler->error = SLJIT_ERR_ALLOC_FAILED;
+                               return NULL;
+                       }
+                       buf_ptr++;
+                       cpool_current_index++;
+               }
+               SLJIT_ASSERT(!first_patch);
+       }
+#endif
+
+       jump = compiler->jumps;
+       while (jump) {
+               buf_ptr = (sljit_uw*)jump->addr;
+
+               if (jump->flags & PATCH_B) {
+                       if (!(jump->flags & JUMP_ADDR)) {
+                               SLJIT_ASSERT(jump->flags & JUMP_LABEL);
+                               SLJIT_ASSERT(((sljit_w)jump->u.label->addr - (sljit_w)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_w)jump->u.label->addr - (sljit_w)(buf_ptr + 2)) >= -0x02000000);
+                               *buf_ptr |= (((sljit_w)jump->u.label->addr - (sljit_w)(buf_ptr + 2)) >> 2) & 0x00ffffff;
+                       }
+                       else {
+                               SLJIT_ASSERT(((sljit_w)jump->u.target - (sljit_w)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_w)jump->u.target - (sljit_w)(buf_ptr + 2)) >= -0x02000000);
+                               *buf_ptr |= (((sljit_w)jump->u.target - (sljit_w)(buf_ptr + 2)) >> 2) & 0x00ffffff;
+                       }
+               }
+               else if (jump->flags & SLJIT_REWRITABLE_JUMP) {
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+                       jump->addr = (sljit_uw)code_ptr;
+                       code_ptr[0] = (sljit_uw)buf_ptr;
+                       code_ptr[1] = *buf_ptr;
+                       inline_set_jump_addr((sljit_uw)code_ptr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
+                       code_ptr += 2;
+#else
+                       inline_set_jump_addr((sljit_uw)buf_ptr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
+#endif
+               }
+               else {
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+                       if (jump->flags & IS_BL)
+                               buf_ptr--;
+                       if (*buf_ptr & (1 << 23))
+                               buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;
+                       else
+                               buf_ptr += 1;
+                       *buf_ptr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
+#else
+                       inline_set_jump_addr((sljit_uw)buf_ptr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
+#endif
+               }
+               jump = jump->next;
+       }
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       const_ = compiler->consts;
+       while (const_) {
+               buf_ptr = (sljit_uw*)const_->addr;
+               const_->addr = (sljit_uw)code_ptr;
+
+               code_ptr[0] = (sljit_uw)buf_ptr;
+               code_ptr[1] = *buf_ptr;
+               if (*buf_ptr & (1 << 23))
+                       buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;
+               else
+                       buf_ptr += 1;
+               /* Set the value again (can be a simple constant). */
+               inline_set_const((sljit_uw)code_ptr, *buf_ptr, 0);
+               code_ptr += 2;
+
+               const_ = const_->next;
+       }
+#endif
+
+       SLJIT_ASSERT(code_ptr - code <= (int)size);
+
+       SLJIT_CACHE_FLUSH(code, code_ptr);
+       compiler->error = SLJIT_ERR_COMPILED;
+       compiler->executable_size = size * sizeof(sljit_uw);
+       return code;
+}
+
+/* emit_op inp_flags.
+   WRITE_BACK must be the first, since it is a flag. */
+#define WRITE_BACK     0x01
+#define ALLOW_IMM      0x02
+#define ALLOW_INV_IMM  0x04
+#define ALLOW_ANY_IMM  (ALLOW_IMM | ALLOW_INV_IMM)
+#define ARG_TEST       0x08
+
+/* Creates an index in data_transfer_insts array. */
+#define WORD_DATA      0x00
+#define BYTE_DATA      0x10
+#define HALF_DATA      0x20
+#define SIGNED_DATA    0x40
+#define LOAD_DATA      0x80
+
+#define EMIT_INSTRUCTION(inst) \
+       FAIL_IF(push_inst(compiler, (inst)))
+
+/* Condition: AL. */
+#define EMIT_DATA_PROCESS_INS(opcode, set_flags, dst, src1, src2) \
+       (0xe0000000 | ((opcode) << 21) | (set_flags) | RD(dst) | RN(src1) | (src2))
+
+static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w);
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       int size;
+       sljit_uw push;
+
+       CHECK_ERROR();
+       check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+
+       /* Push saved registers, temporary registers
+          stmdb sp!, {..., lr} */
+       push = PUSH | (1 << 14);
+       if (temporaries >= 5)
+               push |= 1 << 11;
+       if (temporaries >= 4)
+               push |= 1 << 10;
+       if (saveds >= 5)
+               push |= 1 << 8;
+       if (saveds >= 4)
+               push |= 1 << 7;
+       if (saveds >= 3)
+               push |= 1 << 6;
+       if (saveds >= 2)
+               push |= 1 << 5;
+       if (saveds >= 1)
+               push |= 1 << 4;
+       EMIT_INSTRUCTION(push);
+
+       /* Stack must be aligned to 8 bytes: */
+       size = (1 + saveds) * sizeof(sljit_uw);
+       if (temporaries >= 4)
+               size += (temporaries - 3) * sizeof(sljit_uw);
+       local_size += size;
+       local_size = (local_size + 7) & ~7;
+       local_size -= size;
+       compiler->local_size = local_size;
+       if (local_size > 0)
+               FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size));
+
+       if (args >= 1)
+               EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG1, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG1)));
+       if (args >= 2)
+               EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG2, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG2)));
+       if (args >= 3)
+               EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG3, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG3)));
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       int size;
+
+       CHECK_ERROR_VOID();
+       check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+
+       size = (1 + saveds) * sizeof(sljit_uw);
+       if (temporaries >= 4)
+               size += (temporaries - 3) * sizeof(sljit_uw);
+       local_size += size;
+       local_size = (local_size + 7) & ~7;
+       local_size -= size;
+       compiler->local_size = local_size;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+{
+       sljit_uw pop;
+
+       CHECK_ERROR();
+       check_sljit_emit_return(compiler, op, src, srcw);
+
+       FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+
+       if (compiler->local_size > 0)
+               FAIL_IF(emit_op(compiler, SLJIT_ADD, ALLOW_IMM, SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size));
+
+       pop = POP | (1 << 15);
+       /* Push saved registers, temporary registers
+          ldmia sp!, {..., pc} */
+       if (compiler->temporaries >= 5)
+               pop |= 1 << 11;
+       if (compiler->temporaries >= 4)
+               pop |= 1 << 10;
+       if (compiler->saveds >= 5)
+               pop |= 1 << 8;
+       if (compiler->saveds >= 4)
+               pop |= 1 << 7;
+       if (compiler->saveds >= 3)
+               pop |= 1 << 6;
+       if (compiler->saveds >= 2)
+               pop |= 1 << 5;
+       if (compiler->saveds >= 1)
+               pop |= 1 << 4;
+
+       return push_inst(compiler, pop);
+}
+
+/* --------------------------------------------------------------------- */
+/*  Operators                                                            */
+/* --------------------------------------------------------------------- */
+
+/* s/l - store/load (1 bit)
+   u/s - signed/unsigned (1 bit)
+   w/b/h/N - word/byte/half/NOT allowed (2 bit)
+   It contans 16 items, but not all are different. */
+
+static sljit_w data_transfer_insts[16] = {
+/* s u w */ 0xe5000000 /* str */,
+/* s u b */ 0xe5400000 /* strb */,
+/* s u h */ 0xe10000b0 /* strh */,
+/* s u N */ 0x00000000 /* not allowed */,
+/* s s w */ 0xe5000000 /* str */,
+/* s s b */ 0xe5400000 /* strb */,
+/* s s h */ 0xe10000b0 /* strh */,
+/* s s N */ 0x00000000 /* not allowed */,
+
+/* l u w */ 0xe5100000 /* ldr */,
+/* l u b */ 0xe5500000 /* ldrb */,
+/* l u h */ 0xe11000b0 /* ldrh */,
+/* l u N */ 0x00000000 /* not allowed */,
+/* l s w */ 0xe5100000 /* ldr */,
+/* l s b */ 0xe11000d0 /* ldrsb */,
+/* l s h */ 0xe11000f0 /* ldrsh */,
+/* l s N */ 0x00000000 /* not allowed */,
+};
+
+#define EMIT_DATA_TRANSFER(type, add, wb, target, base1, base2) \
+       (data_transfer_insts[(type) >> 4] | ((add) << 23) | ((wb) << 21) | (reg_map[target] << 12) | (reg_map[base1] << 16) | (base2))
+/* Normal ldr/str instruction.
+   Type2: ldrsb, ldrh, ldrsh */
+#define IS_TYPE1_TRANSFER(type) \
+       (data_transfer_insts[(type) >> 4] & 0x04000000)
+#define TYPE2_TRANSFER_IMM(imm) \
+       (((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22))
+
+/* flags: */
+  /* Arguments are swapped. */
+#define ARGS_SWAPPED   0x01
+  /* Inverted immediate. */
+#define INV_IMM                0x02
+  /* Source and destination is register. */
+#define REG_DEST       0x04
+#define REG_SOURCE     0x08
+  /* One instruction is enough. */
+#define FAST_DEST      0x10
+  /* Multiple instructions are required. */
+#define SLOW_DEST      0x20
+/* SET_FLAGS must be (1 << 20) as it is also the value of S bit (can be used for optimization). */
+#define SET_FLAGS      (1 << 20)
+/* dst: reg
+   src1: reg
+   src2: reg or imm (if allowed)
+   SRC2_IMM must be (1 << 25) as it is also the value of I bit (can be used for optimization). */
+#define SRC2_IMM       (1 << 25)
+
+#define EMIT_DATA_PROCESS_INS_AND_RETURN(opcode) \
+       return push_inst(compiler, EMIT_DATA_PROCESS_INS(opcode, flags & SET_FLAGS, dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)))
+
+#define EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(opcode, dst, src1, src2) \
+       return push_inst(compiler, EMIT_DATA_PROCESS_INS(opcode, flags & SET_FLAGS, dst, src1, src2))
+
+#define EMIT_SHIFT_INS_AND_RETURN(opcode) \
+       SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); \
+       if (compiler->shift_imm != 0x20) { \
+               SLJIT_ASSERT(src1 == TMP_REG1); \
+               SLJIT_ASSERT(!(flags & ARGS_SWAPPED)); \
+               if (compiler->shift_imm != 0) \
+                       return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (compiler->shift_imm << 7) | (opcode << 5) | reg_map[src2])); \
+               return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, reg_map[src2])); \
+       } \
+       return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | ((flags & ARGS_SWAPPED) ? reg_map[src2] : reg_map[src1])));
+
+static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
+       int dst, int src1, int src2)
+{
+       sljit_w mul_inst;
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_ADD:
+               SLJIT_ASSERT(!(flags & INV_IMM));
+               EMIT_DATA_PROCESS_INS_AND_RETURN(ADD_DP);
+
+       case SLJIT_ADDC:
+               SLJIT_ASSERT(!(flags & INV_IMM));
+               EMIT_DATA_PROCESS_INS_AND_RETURN(ADC_DP);
+
+       case SLJIT_SUB:
+               SLJIT_ASSERT(!(flags & INV_IMM));
+               if (!(flags & ARGS_SWAPPED))
+                       EMIT_DATA_PROCESS_INS_AND_RETURN(SUB_DP);
+               EMIT_DATA_PROCESS_INS_AND_RETURN(RSB_DP);
+
+       case SLJIT_SUBC:
+               SLJIT_ASSERT(!(flags & INV_IMM));
+               if (!(flags & ARGS_SWAPPED))
+                       EMIT_DATA_PROCESS_INS_AND_RETURN(SBC_DP);
+               EMIT_DATA_PROCESS_INS_AND_RETURN(RSC_DP);
+
+       case SLJIT_MUL:
+               SLJIT_ASSERT(!(flags & INV_IMM));
+               SLJIT_ASSERT(!(src2 & SRC2_IMM));
+               if (SLJIT_UNLIKELY(op & SLJIT_SET_O))
+                       mul_inst = SMULL | (reg_map[TMP_REG3] << 16) | (reg_map[dst] << 12);
+               else
+                       mul_inst = MUL | (reg_map[dst] << 16);
+
+               if (dst != src2)
+                       FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src1] << 8) | reg_map[src2]));
+               else if (dst != src1)
+                       FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src2] << 8) | reg_map[src1]));
+               else {
+                       /* Rm and Rd must not be the same register. */
+                       SLJIT_ASSERT(dst != TMP_REG1);
+                       FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, reg_map[src2])));
+                       FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src2] << 8) | reg_map[TMP_REG1]));
+               }
+
+               if (!(op & SLJIT_SET_O))
+                       return SLJIT_SUCCESS;
+
+               /* We need to use TMP_REG3. */
+               compiler->cache_arg = 0;
+               compiler->cache_argw = 0;
+               /* cmp TMP_REG2, dst asr #31. */
+               return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMP_DP, SET_FLAGS, SLJIT_UNUSED, TMP_REG3, RM(dst) | 0xfc0));
+
+       case SLJIT_AND:
+               if (!(flags & INV_IMM))
+                       EMIT_DATA_PROCESS_INS_AND_RETURN(AND_DP);
+               EMIT_DATA_PROCESS_INS_AND_RETURN(BIC_DP);
+
+       case SLJIT_OR:
+               SLJIT_ASSERT(!(flags & INV_IMM));
+               EMIT_DATA_PROCESS_INS_AND_RETURN(ORR_DP);
+
+       case SLJIT_XOR:
+               SLJIT_ASSERT(!(flags & INV_IMM));
+               EMIT_DATA_PROCESS_INS_AND_RETURN(EOR_DP);
+
+       case SLJIT_SHL:
+               EMIT_SHIFT_INS_AND_RETURN(0);
+
+       case SLJIT_LSHR:
+               EMIT_SHIFT_INS_AND_RETURN(1);
+
+       case SLJIT_ASHR:
+               EMIT_SHIFT_INS_AND_RETURN(2);
+
+       case SLJIT_MOV:
+               SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
+               if (dst != src2) {
+                       if (src2 & SRC2_IMM) {
+                               if (flags & INV_IMM)
+                                       EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
+                               EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
+                       }
+                       EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, reg_map[src2]);
+               }
+               return SLJIT_SUCCESS;
+
+       case SLJIT_MOV_UB:
+       case SLJIT_MOV_SB:
+               SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
+               if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) {
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+                       if (op == SLJIT_MOV_UB)
+                               return push_inst(compiler, EMIT_DATA_PROCESS_INS(AND_DP, 0, dst, src2, SRC2_IMM | 0xff));
+                       EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | reg_map[src2]));
+                       return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | (op == SLJIT_MOV_UB ? 0x20 : 0x40) | reg_map[dst]));
+#else
+                       return push_inst(compiler, (op == SLJIT_MOV_UB ? UXTB : SXTB) | RD(dst) | RM(src2));
+#endif
+               }
+               else if (dst != src2) {
+                       SLJIT_ASSERT(src2 & SRC2_IMM);
+                       if (flags & INV_IMM)
+                               EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
+                       EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
+               }
+               return SLJIT_SUCCESS;
+
+       case SLJIT_MOV_UH:
+       case SLJIT_MOV_SH:
+               SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
+               if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) {
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+                       EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | reg_map[src2]));
+                       return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | (op == SLJIT_MOV_UH ? 0x20 : 0x40) | reg_map[dst]));
+#else
+                       return push_inst(compiler, (op == SLJIT_MOV_UH ? UXTH : SXTH) | RD(dst) | RM(src2));
+#endif
+               }
+               else if (dst != src2) {
+                       SLJIT_ASSERT(src2 & SRC2_IMM);
+                       if (flags & INV_IMM)
+                               EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
+                       EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
+               }
+               return SLJIT_SUCCESS;
+
+       case SLJIT_NOT:
+               if (src2 & SRC2_IMM) {
+                       if (flags & INV_IMM)
+                               EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
+                       EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
+               }
+               EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, RM(src2));
+
+       case SLJIT_CLZ:
+               SLJIT_ASSERT(!(flags & INV_IMM));
+               SLJIT_ASSERT(!(src2 & SRC2_IMM));
+               FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2)));
+               if (flags & SET_FLAGS)
+                       EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(CMP_DP, SLJIT_UNUSED, dst, SRC2_IMM);
+               return SLJIT_SUCCESS;
+       }
+       SLJIT_ASSERT_STOP();
+       return SLJIT_SUCCESS;
+}
+
+#undef EMIT_DATA_PROCESS_INS_AND_RETURN
+#undef EMIT_FULL_DATA_PROCESS_INS_AND_RETURN
+#undef EMIT_SHIFT_INS_AND_RETURN
+
+/* Tests whether the immediate can be stored in the 12 bit imm field.
+   Returns with 0 if not possible. */
+static sljit_uw get_immediate(sljit_uw imm)
+{
+       int rol;
+
+       if (imm <= 0xff)
+               return SRC2_IMM | imm;
+
+       if (!(imm & 0xff000000)) {
+               imm <<= 8;
+               rol = 8;
+       }
+       else {
+               imm = (imm << 24) | (imm >> 8);
+               rol = 0;
+       }
+
+       if (!(imm & 0xff000000)) {
+               imm <<= 8;
+               rol += 4;
+       }
+
+       if (!(imm & 0xf0000000)) {
+               imm <<= 4;
+               rol += 2;
+       }
+
+       if (!(imm & 0xc0000000)) {
+               imm <<= 2;
+               rol += 1;
+       }
+
+       if (!(imm & 0x00ffffff))
+               return SRC2_IMM | (imm >> 24) | (rol << 8);
+       else
+               return 0;
+}
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+static int generate_int(struct sljit_compiler *compiler, int reg, sljit_uw imm, int positive)
+{
+       sljit_uw mask;
+       sljit_uw imm1;
+       sljit_uw imm2;
+       int rol;
+
+       /* Step1: Search a zero byte (8 continous zero bit). */
+       mask = 0xff000000;
+       rol = 8;
+       while(1) {
+               if (!(imm & mask)) {
+                       /* Rol imm by rol. */
+                       imm = (imm << rol) | (imm >> (32 - rol));
+                       /* Calculate arm rol. */
+                       rol = 4 + (rol >> 1);
+                       break;
+               }
+               rol += 2;
+               mask >>= 2;
+               if (mask & 0x3) {
+                       /* rol by 8. */
+                       imm = (imm << 8) | (imm >> 24);
+                       mask = 0xff00;
+                       rol = 24;
+                       while (1) {
+                               if (!(imm & mask)) {
+                                       /* Rol imm by rol. */
+                                       imm = (imm << rol) | (imm >> (32 - rol));
+                                       /* Calculate arm rol. */
+                                       rol = (rol >> 1) - 8;
+                                       break;
+                               }
+                               rol += 2;
+                               mask >>= 2;
+                               if (mask & 0x3)
+                                       return 0;
+                       }
+                       break;
+               }
+       }
+
+       /* The low 8 bit must be zero. */
+       SLJIT_ASSERT(!(imm & 0xff));
+
+       if (!(imm & 0xff000000)) {
+               imm1 = SRC2_IMM | ((imm >> 16) & 0xff) | (((rol + 4) & 0xf) << 8);
+               imm2 = SRC2_IMM | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8);
+       }
+       else if (imm & 0xc0000000) {
+               imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);
+               imm <<= 8;
+               rol += 4;
+
+               if (!(imm & 0xff000000)) {
+                       imm <<= 8;
+                       rol += 4;
+               }
+
+               if (!(imm & 0xf0000000)) {
+                       imm <<= 4;
+                       rol += 2;
+               }
+
+               if (!(imm & 0xc0000000)) {
+                       imm <<= 2;
+                       rol += 1;
+               }
+
+               if (!(imm & 0x00ffffff))
+                       imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);
+               else
+                       return 0;
+       }
+       else {
+               if (!(imm & 0xf0000000)) {
+                       imm <<= 4;
+                       rol += 2;
+               }
+
+               if (!(imm & 0xc0000000)) {
+                       imm <<= 2;
+                       rol += 1;
+               }
+
+               imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);
+               imm <<= 8;
+               rol += 4;
+
+               if (!(imm & 0xf0000000)) {
+                       imm <<= 4;
+                       rol += 2;
+               }
+
+               if (!(imm & 0xc0000000)) {
+                       imm <<= 2;
+                       rol += 1;
+               }
+
+               if (!(imm & 0x00ffffff))
+                       imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);
+               else
+                       return 0;
+       }
+
+       EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(positive ? MOV_DP : MVN_DP, 0, reg, SLJIT_UNUSED, imm1));
+       EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(positive ? ORR_DP : BIC_DP, 0, reg, reg, imm2));
+       return 1;
+}
+#endif
+
+static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_uw imm)
+{
+       sljit_uw tmp;
+
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+       if (!(imm & ~0xffff))
+               return push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff));
+#endif
+
+       /* Create imm by 1 inst. */
+       tmp = get_immediate(imm);
+       if (tmp) {
+               EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, tmp));
+               return SLJIT_SUCCESS;
+       }
+
+       tmp = get_immediate(~imm);
+       if (tmp) {
+               EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, tmp));
+               return SLJIT_SUCCESS;
+       }
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       /* Create imm by 2 inst. */
+       FAIL_IF(generate_int(compiler, reg, imm, 1));
+       FAIL_IF(generate_int(compiler, reg, ~imm, 0));
+
+       /* Load integer. */
+       return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), imm);
+#else
+       return emit_imm(compiler, reg, imm);
+#endif
+}
+
+/* Can perform an operation using at most 1 instruction. */
+static int getput_arg_fast(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw)
+{
+       sljit_uw imm;
+
+       if (arg & SLJIT_IMM) {
+               imm = get_immediate(argw);
+               if (imm) {
+                       if (inp_flags & ARG_TEST)
+                               return 1;
+                       EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, imm));
+                       return -1;
+               }
+               imm = get_immediate(~argw);
+               if (imm) {
+                       if (inp_flags & ARG_TEST)
+                               return 1;
+                       EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, imm));
+                       return -1;
+               }
+               return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
+       }
+
+       SLJIT_ASSERT(arg & SLJIT_MEM);
+
+       /* Fast loads/stores. */
+       if (arg & 0xf) {
+               if (!(arg & 0xf0)) {
+                       if (IS_TYPE1_TRANSFER(inp_flags)) {
+                               if (argw >= 0 && argw <= 0xfff) {
+                                       if (inp_flags & ARG_TEST)
+                                               return 1;
+                                       EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, argw));
+                                       return -1;
+                               }
+                               if (argw < 0 && argw >= -0xfff) {
+                                       if (inp_flags & ARG_TEST)
+                                               return 1;
+                                       EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & 0xf, -argw));
+                                       return -1;
+                               }
+                       }
+                       else {
+                               if (argw >= 0 && argw <= 0xff) {
+                                       if (inp_flags & ARG_TEST)
+                                               return 1;
+                                       EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, TYPE2_TRANSFER_IMM(argw)));
+                                       return -1;
+                               }
+                               if (argw < 0 && argw >= -0xff) {
+                                       if (inp_flags & ARG_TEST)
+                                               return 1;
+                                       argw = -argw;
+                                       EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & 0xf, TYPE2_TRANSFER_IMM(argw)));
+                                       return -1;
+                               }
+                       }
+               }
+               else if ((argw & 0x3) == 0 || IS_TYPE1_TRANSFER(inp_flags)) {
+                       if (inp_flags & ARG_TEST)
+                               return 1;
+                       EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf,
+                               RM((arg >> 4) & 0xf) | (IS_TYPE1_TRANSFER(inp_flags) ? SRC2_IMM : 0) | ((argw & 0x3) << 7)));
+                       return -1;
+               }
+       }
+
+       return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
+}
+
+/* See getput_arg below.
+   Note: can_cache is called only for binary operators. Those
+   operators always uses word arguments without write back. */
+static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+{
+       /* Immediate caching is not supported as it would be an operation on constant arguments. */
+       if (arg & SLJIT_IMM)
+               return 0;
+
+       /* Always a simple operation. */
+       if (arg & 0xf0)
+               return 0;
+
+       if (!(arg & 0xf)) {
+               /* Immediate access. */
+               if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= 0xfff || (sljit_uw)next_argw - (sljit_uw)argw <= 0xfff))
+                       return 1;
+               return 0;
+       }
+
+       if (argw <= 0xfffff && argw >= -0xfffff)
+               return 0;
+
+       if (argw == next_argw && (next_arg & SLJIT_MEM))
+               return 1;
+
+       if (arg == next_arg && ((sljit_uw)argw - (sljit_uw)next_argw <= 0xfff || (sljit_uw)next_argw - (sljit_uw)argw <= 0xfff))
+               return 1;
+
+       return 0;
+}
+
+#define GETPUT_ARG_DATA_TRANSFER(add, wb, target, base, imm) \
+       if (max_delta & 0xf00) \
+               FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, add, wb, target, base, imm))); \
+       else \
+               FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, add, wb, target, base, TYPE2_TRANSFER_IMM(imm))));
+
+#define TEST_WRITE_BACK() \
+       if (inp_flags & WRITE_BACK) { \
+               tmp_r = arg & 0xf; \
+               if (reg == tmp_r) { \
+                       /* This can only happen for stores */ \
+                       /* since ldr reg, [reg, ...]! has no meaning */ \
+                       SLJIT_ASSERT(!(inp_flags & LOAD_DATA)); \
+                       EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(reg))); \
+                       reg = TMP_REG3; \
+               } \
+       }
+
+/* Emit the necessary instructions. See can_cache above. */
+static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+{
+       int tmp_r;
+       sljit_w max_delta;
+       sljit_w sign;
+
+       if (arg & SLJIT_IMM) {
+               SLJIT_ASSERT(inp_flags & LOAD_DATA);
+               return load_immediate(compiler, reg, argw);
+       }
+
+       SLJIT_ASSERT(arg & SLJIT_MEM);
+
+       tmp_r = (inp_flags & LOAD_DATA) ? reg : TMP_REG3;
+       max_delta = IS_TYPE1_TRANSFER(inp_flags) ? 0xfff : 0xff;
+
+       if ((arg & 0xf) == SLJIT_UNUSED) {
+               /* Write back is not used. */
+               if ((compiler->cache_arg & SLJIT_IMM) && (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= (sljit_uw)max_delta || ((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= (sljit_uw)max_delta)) {
+                       if (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= (sljit_uw)max_delta) {
+                               sign = 1;
+                               argw = argw - compiler->cache_argw;
+                       }
+                       else {
+                               sign = 0;
+                               argw = compiler->cache_argw - argw;
+                       }
+
+                       if (max_delta & 0xf00) {
+                               EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, sign, 0, reg, TMP_REG3, argw));
+                       }
+                       else {
+                               EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, sign, 0, reg, TMP_REG3, TYPE2_TRANSFER_IMM(argw)));
+                       }
+                       return SLJIT_SUCCESS;
+               }
+
+               /* With write back, we can create some sophisticated loads, but
+                  it is hard to decide whether we should convert downward (0s) or upward (1s). */
+               if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= (sljit_uw)max_delta || (sljit_uw)next_argw - (sljit_uw)argw <= (sljit_uw)max_delta)) {
+                       SLJIT_ASSERT(inp_flags & LOAD_DATA);
+
+                       compiler->cache_arg = SLJIT_IMM;
+                       compiler->cache_argw = argw;
+                       tmp_r = TMP_REG3;
+               }
+
+               FAIL_IF(load_immediate(compiler, tmp_r, argw));
+               GETPUT_ARG_DATA_TRANSFER(1, 0, reg, tmp_r, 0);
+               return SLJIT_SUCCESS;
+       }
+
+       /* Extended imm addressing for [reg+imm] format. */
+       sign = (max_delta << 8) | 0xff;
+       if (!(arg & 0xf0) && argw <= sign && argw >= -sign) {
+               TEST_WRITE_BACK();
+               if (argw >= 0) {
+                       sign = 1;
+               }
+               else {
+                       sign = 0;
+                       argw = -argw;
+               }
+
+               /* Optimization: add is 0x4, sub is 0x2. Sign is 1 for add and 0 for sub. */
+               if (max_delta & 0xf00)
+                       EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP << sign, 0, tmp_r, arg & 0xf, SRC2_IMM | (argw >> 12) | 0xa00));
+               else
+                       EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP << sign, 0, tmp_r, arg & 0xf, SRC2_IMM | (argw >> 8) | 0xc00));
+
+               argw &= max_delta;
+               GETPUT_ARG_DATA_TRANSFER(sign, inp_flags & WRITE_BACK, reg, tmp_r, argw);
+               return SLJIT_SUCCESS;
+       }
+
+       if (arg & 0xf0) {
+               SLJIT_ASSERT((argw & 0x3) && !(max_delta & 0xf00));
+               if (inp_flags & WRITE_BACK)
+                       tmp_r = arg & 0xf;
+               EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & 0xf, RM((arg >> 4) & 0xf) | ((argw & 0x3) << 7)));
+               EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, 0, reg, tmp_r, TYPE2_TRANSFER_IMM(0)));
+               return SLJIT_SUCCESS;
+       }
+
+       if (compiler->cache_arg == arg && ((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= (sljit_uw)max_delta) {
+               SLJIT_ASSERT(!(inp_flags & WRITE_BACK));
+               argw = argw - compiler->cache_argw;
+               GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, argw);
+               return SLJIT_SUCCESS;
+       }
+
+       if (compiler->cache_arg == arg && ((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= (sljit_uw)max_delta) {
+               SLJIT_ASSERT(!(inp_flags & WRITE_BACK));
+               argw = compiler->cache_argw - argw;
+               GETPUT_ARG_DATA_TRANSFER(0, 0, reg, TMP_REG3, argw);
+               return SLJIT_SUCCESS;
+       }
+
+       if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) {
+               TEST_WRITE_BACK();
+               EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
+               return SLJIT_SUCCESS;
+       }
+
+       if (argw == next_argw && (next_arg & SLJIT_MEM)) {
+               SLJIT_ASSERT(inp_flags & LOAD_DATA);
+               FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+
+               compiler->cache_arg = SLJIT_IMM;
+               compiler->cache_argw = argw;
+
+               TEST_WRITE_BACK();
+               EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
+               return SLJIT_SUCCESS;
+       }
+
+       if (arg == next_arg && !(inp_flags & WRITE_BACK) && ((sljit_uw)argw - (sljit_uw)next_argw <= (sljit_uw)max_delta || (sljit_uw)next_argw - (sljit_uw)argw <= (sljit_uw)max_delta)) {
+               SLJIT_ASSERT(inp_flags & LOAD_DATA);
+               FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+               EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & 0xf]));
+
+               compiler->cache_arg = arg;
+               compiler->cache_argw = argw;
+
+               GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, 0);
+               return SLJIT_SUCCESS;
+       }
+
+       if ((arg & 0xf) == tmp_r) {
+               compiler->cache_arg = SLJIT_IMM;
+               compiler->cache_argw = argw;
+               tmp_r = TMP_REG3;
+       }
+
+       FAIL_IF(load_immediate(compiler, tmp_r, argw));
+       EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, reg_map[tmp_r] | (max_delta & 0xf00 ? SRC2_IMM : 0)));
+       return SLJIT_SUCCESS;
+}
+
+static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       /* arg1 goes to TMP_REG1 or src reg
+          arg2 goes to TMP_REG2, imm or src reg
+          TMP_REG3 can be used for caching
+          result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
+
+       /* We prefers register and simple consts. */
+       int dst_r;
+       int src1_r;
+       int src2_r = 0;
+       int sugg_src2_r = TMP_REG2;
+       int flags = GET_FLAGS(op) ? SET_FLAGS : 0;
+
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+
+       /* Destination check. */
+       if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REG3) {
+               dst_r = dst;
+               flags |= REG_DEST;
+               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+                       sugg_src2_r = dst_r;
+       }
+       else if (dst == SLJIT_UNUSED) {
+               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
+                       return SLJIT_SUCCESS;
+               dst_r = TMP_REG2;
+       }
+       else {
+               SLJIT_ASSERT(dst & SLJIT_MEM);
+               if (getput_arg_fast(compiler, inp_flags | ARG_TEST, TMP_REG2, dst, dstw)) {
+                       flags |= FAST_DEST;
+                       dst_r = TMP_REG2;
+               }
+               else {
+                       flags |= SLOW_DEST;
+                       dst_r = 0;
+               }
+       }
+
+       /* Source 1. */
+       if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= TMP_REG3)
+               src1_r = src1;
+       else if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REG3) {
+               flags |= ARGS_SWAPPED;
+               src1_r = src2;
+               src2 = src1;
+               src2w = src1w;
+       }
+       else {
+               if ((inp_flags & ALLOW_ANY_IMM) && (src1 & SLJIT_IMM)) {
+                       /* The second check will generate a hit. */
+                       src2_r = get_immediate(src1w);
+                       if (src2_r) {
+                               flags |= ARGS_SWAPPED;
+                               src1 = src2;
+                               src1w = src2w;
+                       }
+                       if (inp_flags & ALLOW_INV_IMM) {
+                               src2_r = get_immediate(~src1w);
+                               if (src2_r) {
+                                       flags |= ARGS_SWAPPED | INV_IMM;
+                                       src1 = src2;
+                                       src1w = src2w;
+                               }
+                       }
+               }
+
+               src1_r = 0;
+               if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w)) {
+                       FAIL_IF(compiler->error);
+                       src1_r = TMP_REG1;
+               }
+       }
+
+       /* Source 2. */
+       if (src2_r == 0) {
+               if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REG3) {
+                       src2_r = src2;
+                       flags |= REG_SOURCE;
+                       if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+                               dst_r = src2_r;
+               }
+               else do { /* do { } while(0) is used because of breaks. */
+                       if ((inp_flags & ALLOW_ANY_IMM) && (src2 & SLJIT_IMM)) {
+                               src2_r = get_immediate(src2w);
+                               if (src2_r)
+                                       break;
+                               if (inp_flags & ALLOW_INV_IMM) {
+                                       src2_r = get_immediate(~src2w);
+                                       if (src2_r) {
+                                               flags |= INV_IMM;
+                                               break;
+                                       }
+                               }
+                       }
+
+                       /* src2_r is 0. */
+                       if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w)) {
+                               FAIL_IF(compiler->error);
+                               src2_r = sugg_src2_r;
+                       }
+               } while (0);
+       }
+
+       /* src1_r, src2_r and dst_r can be zero (=unprocessed) or non-zero.
+          If they are zero, they must not be registers. */
+       if (src1_r == 0 && src2_r == 0 && dst_r == 0) {
+               if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
+                       SLJIT_ASSERT(!(flags & ARGS_SWAPPED));
+                       flags |= ARGS_SWAPPED;
+                       FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src2, src2w, src1, src1w));
+                       FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src1, src1w, dst, dstw));
+               }
+               else {
+                       FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
+                       FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw));
+               }
+               src1_r = TMP_REG1;
+               src2_r = TMP_REG2;
+       }
+       else if (src1_r == 0 && src2_r == 0) {
+               FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
+               src1_r = TMP_REG1;
+       }
+       else if (src1_r == 0 && dst_r == 0) {
+               FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
+               src1_r = TMP_REG1;
+       }
+       else if (src2_r == 0 && dst_r == 0) {
+               FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw));
+               src2_r = sugg_src2_r;
+       }
+
+       if (dst_r == 0)
+               dst_r = TMP_REG2;
+
+       if (src1_r == 0) {
+               FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, 0, 0));
+               src1_r = TMP_REG1;
+       }
+
+       if (src2_r == 0) {
+               FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, 0, 0));
+               src2_r = sugg_src2_r;
+       }
+
+       FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
+
+       if (flags & (FAST_DEST | SLOW_DEST)) {
+               if (flags & FAST_DEST)
+                       FAIL_IF(getput_arg_fast(compiler, inp_flags, dst_r, dst, dstw));
+               else
+                       FAIL_IF(getput_arg(compiler, inp_flags, dst_r, dst, dstw, 0, 0));
+       }
+       return SLJIT_SUCCESS;
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__GNUC__)
+extern unsigned int __aeabi_uidivmod(unsigned numerator, unsigned denominator);
+extern unsigned int __aeabi_idivmod(unsigned numerator, unsigned denominator);
+#else
+#error "Software divmod functions are needed"
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
+{
+       CHECK_ERROR();
+       check_sljit_emit_op0(compiler, op);
+
+       op = GET_OPCODE(op);
+       switch (op) {
+       case SLJIT_BREAKPOINT:
+               EMIT_INSTRUCTION(BKPT);
+               break;
+       case SLJIT_NOP:
+               EMIT_INSTRUCTION(NOP);
+               break;
+       case SLJIT_UMUL:
+       case SLJIT_SMUL:
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+               return push_inst(compiler, (op == SLJIT_UMUL ? UMULL : SMULL)
+                       | (reg_map[SLJIT_TEMPORARY_REG2] << 16)
+                       | (reg_map[SLJIT_TEMPORARY_REG1] << 12)
+                       | (reg_map[SLJIT_TEMPORARY_REG1] << 8)
+                       | reg_map[SLJIT_TEMPORARY_REG2]);
+#else
+               EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG2)));
+               return push_inst(compiler, (op == SLJIT_UMUL ? UMULL : SMULL)
+                       | (reg_map[SLJIT_TEMPORARY_REG2] << 16)
+                       | (reg_map[SLJIT_TEMPORARY_REG1] << 12)
+                       | (reg_map[SLJIT_TEMPORARY_REG1] << 8)
+                       | reg_map[TMP_REG1]);
+#endif
+       case SLJIT_UDIV:
+       case SLJIT_SDIV:
+               if (compiler->temporaries >= 3)
+                       EMIT_INSTRUCTION(0xe52d2008 /* str r2, [sp, #-8]! */);
+#if defined(__GNUC__)
+               FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
+                       (op == SLJIT_UDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
+#else
+#error "Software divmod functions are needed"
+#endif
+               if (compiler->temporaries >= 3)
+                       return push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */);
+               return SLJIT_SUCCESS;
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       CHECK_ERROR();
+       check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_MOV:
+       case SLJIT_MOV_UI:
+       case SLJIT_MOV_SI:
+               return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_MOV_UB:
+               return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw);
+
+       case SLJIT_MOV_SB:
+               return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw);
+
+       case SLJIT_MOV_UH:
+               return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw);
+
+       case SLJIT_MOV_SH:
+               return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw);
+
+       case SLJIT_MOVU:
+       case SLJIT_MOVU_UI:
+       case SLJIT_MOVU_SI:
+               return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_MOVU_UB:
+               return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw);
+
+       case SLJIT_MOVU_SB:
+               return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw);
+
+       case SLJIT_MOVU_UH:
+               return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw);
+
+       case SLJIT_MOVU_SH:
+               return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw);
+
+       case SLJIT_NOT:
+               return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_NEG:
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+               compiler->skip_checks = 1;
+#endif
+               return sljit_emit_op2(compiler, SLJIT_SUB | GET_FLAGS(op), dst, dstw, SLJIT_IMM, 0, src, srcw);
+
+       case SLJIT_CLZ:
+               return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       CHECK_ERROR();
+       check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_ADD:
+       case SLJIT_ADDC:
+       case SLJIT_SUB:
+       case SLJIT_SUBC:
+       case SLJIT_OR:
+       case SLJIT_XOR:
+               return emit_op(compiler, op, ALLOW_IMM, dst, dstw, src1, src1w, src2, src2w);
+
+       case SLJIT_MUL:
+               return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);
+
+       case SLJIT_AND:
+               return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, src1, src1w, src2, src2w);
+
+       case SLJIT_SHL:
+       case SLJIT_LSHR:
+       case SLJIT_ASHR:
+               if (src2 & SLJIT_IMM) {
+                       compiler->shift_imm = src2w & 0x1f;
+                       return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src1, src1w);
+               }
+               else {
+                       compiler->shift_imm = 0x20;
+                       return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);
+               }
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
+{
+       check_sljit_get_register_index(reg);
+       return reg_map[reg];
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, int size)
+{
+       CHECK_ERROR();
+       check_sljit_emit_op_custom(compiler, instruction, size);
+       SLJIT_ASSERT(size == 4);
+
+       return push_inst(compiler, *(sljit_uw*)instruction);
+}
+
+/* --------------------------------------------------------------------- */
+/*  Floating point operators                                             */
+/* --------------------------------------------------------------------- */
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+
+/* 0 - no fpu
+   1 - vfp */
+static int arm_fpu_type = -1;
+
+static void init_compiler()
+{
+       if (arm_fpu_type != -1)
+               return;
+
+       /* TODO: Only the OS can help to determine the correct fpu type. */
+       arm_fpu_type = 1;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
+{
+       if (arm_fpu_type == -1)
+               init_compiler();
+       return arm_fpu_type;
+}
+
+#else
+
+#define arm_fpu_type 1
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
+{
+       /* Always available. */
+       return 1;
+}
+
+#endif
+
+#define EMIT_FPU_DATA_TRANSFER(add, load, base, freg, offs) \
+       (VSTR | ((add) << 23) | ((load) << 20) | (reg_map[base] << 16) | (freg << 12) | (offs))
+#define EMIT_FPU_OPERATION(opcode, dst, src1, src2) \
+       ((opcode) | ((dst) << 12) | (src1) | ((src2) << 16))
+
+static int emit_fpu_data_transfer(struct sljit_compiler *compiler, int fpu_reg, int load, int arg, sljit_w argw)
+{
+       SLJIT_ASSERT(arg & SLJIT_MEM);
+
+       /* Fast loads and stores. */
+       if ((arg & 0xf) && !(arg & 0xf0) && (argw & 0x3) == 0) {
+               if (argw >= 0 && argw <= 0x3ff) {
+                       EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, arg & 0xf, fpu_reg, argw >> 2));
+                       return SLJIT_SUCCESS;
+               }
+               if (argw < 0 && argw >= -0x3ff) {
+                       EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(0, load, arg & 0xf, fpu_reg, (-argw) >> 2));
+                       return SLJIT_SUCCESS;
+               }
+               if (argw >= 0 && argw <= 0x3ffff) {
+                       SLJIT_ASSERT(get_immediate(argw & 0x3fc00));
+                       EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, get_immediate(argw & 0x3fc00)));
+                       argw &= 0x3ff;
+                       EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG1, fpu_reg, argw >> 2));
+                       return SLJIT_SUCCESS;
+               }
+               if (argw < 0 && argw >= -0x3ffff) {
+                       argw = -argw;
+                       SLJIT_ASSERT(get_immediate(argw & 0x3fc00));
+                       EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & 0xf, get_immediate(argw & 0x3fc00)));
+                       argw &= 0x3ff;
+                       EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(0, load, TMP_REG1, fpu_reg, argw >> 2));
+                       return SLJIT_SUCCESS;
+               }
+       }
+
+       if (arg & 0xf0) {
+               EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, RM((arg >> 4) & 0xf) | ((argw & 0x3) << 7)));
+               EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG1, fpu_reg, 0));
+               return SLJIT_SUCCESS;
+       }
+
+       if (compiler->cache_arg == arg && ((argw - compiler->cache_argw) & 0x3) == 0) {
+               if (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= 0x3ff) {
+                       EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG3, fpu_reg, (argw - compiler->cache_argw) >> 2));
+                       return SLJIT_SUCCESS;
+               }
+               if (((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= 0x3ff) {
+                       EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(0, load, TMP_REG3, fpu_reg, (compiler->cache_argw - argw) >> 2));
+                       return SLJIT_SUCCESS;
+               }
+       }
+
+       compiler->cache_arg = arg;
+       compiler->cache_argw = argw;
+       if (arg & 0xf) {
+               FAIL_IF(load_immediate(compiler, TMP_REG1, argw));
+               EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, arg & 0xf, reg_map[TMP_REG1]));
+       }
+       else
+               FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+
+       EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG3, fpu_reg, 0));
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       int dst_freg;
+
+       CHECK_ERROR();
+       check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
+
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+
+       if (GET_OPCODE(op) == SLJIT_FCMP) {
+               if (dst > SLJIT_FLOAT_REG4) {
+                       FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, dst, dstw));
+                       dst = TMP_FREG1;
+               }
+               if (src > SLJIT_FLOAT_REG4) {
+                       FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src, srcw));
+                       src = TMP_FREG2;
+               }
+               EMIT_INSTRUCTION(VCMP_F64 | (dst << 12) | src);
+               EMIT_INSTRUCTION(VMRS);
+               return SLJIT_SUCCESS;
+       }
+
+       dst_freg = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst;
+
+       if (src > SLJIT_FLOAT_REG4) {
+               FAIL_IF(emit_fpu_data_transfer(compiler, dst_freg, 1, src, srcw));
+               src = dst_freg;
+       }
+
+       switch (op) {
+               case SLJIT_FMOV:
+                       if (src != dst_freg && dst_freg != TMP_FREG1)
+                               EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMOV_F64, dst_freg, src, 0));
+                       break;
+               case SLJIT_FNEG:
+                       EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VNEG_F64, dst_freg, src, 0));
+                       break;
+               case SLJIT_FABS:
+                       EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VABS_F64, dst_freg, src, 0));
+                       break;
+       }
+
+       if (dst_freg == TMP_FREG1)
+               FAIL_IF(emit_fpu_data_transfer(compiler, src, 0, dst, dstw));
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       int dst_freg;
+
+       CHECK_ERROR();
+       check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+
+       dst_freg = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst;
+
+       if (src2 > SLJIT_FLOAT_REG4) {
+               FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w));
+               src2 = TMP_FREG2;
+       }
+
+       if (src1 > SLJIT_FLOAT_REG4) {
+               FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w));
+               src1 = TMP_FREG1;
+       }
+
+       switch (op) {
+       case SLJIT_FADD:
+               EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VADD_F64, dst_freg, src2, src1));
+               break;
+
+       case SLJIT_FSUB:
+               EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VSUB_F64, dst_freg, src2, src1));
+               break;
+
+       case SLJIT_FMUL:
+               EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMUL_F64, dst_freg, src2, src1));
+               break;
+
+       case SLJIT_FDIV:
+               EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VDIV_F64, dst_freg, src2, src1));
+               break;
+       }
+
+       if (dst_freg == TMP_FREG1)
+               FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 0, dst, dstw));
+
+       return SLJIT_SUCCESS;
+}
+
+/* --------------------------------------------------------------------- */
+/*  Other instructions                                                   */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
+{
+       int size;
+
+       CHECK_ERROR();
+       check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+
+       size = (1 + saveds) * sizeof(sljit_uw);
+       if (temporaries >= 4)
+               size += (temporaries - 3) * sizeof(sljit_uw);
+       local_size += size;
+       local_size = (local_size + 7) & ~7;
+       local_size -= size;
+       compiler->local_size = local_size;
+
+       if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
+               return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, RM(TMP_REG3)));
+       else if (dst & SLJIT_MEM) {
+               if (getput_arg_fast(compiler, WORD_DATA, TMP_REG3, dst, dstw))
+                       return compiler->error;
+               EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG2, SLJIT_UNUSED, RM(TMP_REG3)));
+               compiler->cache_arg = 0;
+               compiler->cache_argw = 0;
+               return getput_arg(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0);
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+{
+       CHECK_ERROR();
+       check_sljit_emit_fast_return(compiler, src, srcw);
+
+       if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
+               EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(src)));
+       else if (src & SLJIT_MEM) {
+               if (getput_arg_fast(compiler, WORD_DATA | LOAD_DATA, TMP_REG3, src, srcw))
+                       FAIL_IF(compiler->error);
+               else {
+                       compiler->cache_arg = 0;
+                       compiler->cache_argw = 0;
+                       FAIL_IF(getput_arg(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, 0, 0));
+                       EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(TMP_REG2)));
+               }
+       }
+       else if (src & SLJIT_IMM)
+               FAIL_IF(load_immediate(compiler, TMP_REG3, srcw));
+       return push_inst(compiler, BLX | RM(TMP_REG3));
+}
+
+/* --------------------------------------------------------------------- */
+/*  Conditional instructions                                             */
+/* --------------------------------------------------------------------- */
+
+static sljit_uw get_cc(int type)
+{
+       switch (type) {
+       case SLJIT_C_EQUAL:
+       case SLJIT_C_MUL_NOT_OVERFLOW:
+       case SLJIT_C_FLOAT_EQUAL:
+               return 0x00000000;
+
+       case SLJIT_C_NOT_EQUAL:
+       case SLJIT_C_MUL_OVERFLOW:
+       case SLJIT_C_FLOAT_NOT_EQUAL:
+               return 0x10000000;
+
+       case SLJIT_C_LESS:
+       case SLJIT_C_FLOAT_LESS:
+               return 0x30000000;
+
+       case SLJIT_C_GREATER_EQUAL:
+       case SLJIT_C_FLOAT_GREATER_EQUAL:
+               return 0x20000000;
+
+       case SLJIT_C_GREATER:
+       case SLJIT_C_FLOAT_GREATER:
+               return 0x80000000;
+
+       case SLJIT_C_LESS_EQUAL:
+       case SLJIT_C_FLOAT_LESS_EQUAL:
+               return 0x90000000;
+
+       case SLJIT_C_SIG_LESS:
+               return 0xb0000000;
+
+       case SLJIT_C_SIG_GREATER_EQUAL:
+               return 0xa0000000;
+
+       case SLJIT_C_SIG_GREATER:
+               return 0xc0000000;
+
+       case SLJIT_C_SIG_LESS_EQUAL:
+               return 0xd0000000;
+
+       case SLJIT_C_OVERFLOW:
+       case SLJIT_C_FLOAT_NAN:
+               return 0x60000000;
+
+       case SLJIT_C_NOT_OVERFLOW:
+       case SLJIT_C_FLOAT_NOT_NAN:
+               return 0x70000000;
+
+       default: /* SLJIT_JUMP */
+               return 0xe0000000;
+       }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+       struct sljit_label *label;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_label(compiler);
+
+       if (compiler->last_label && compiler->last_label->size == compiler->size)
+               return compiler->last_label;
+
+       label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+       PTR_FAIL_IF(!label);
+       set_label(label, compiler);
+       return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type)
+{
+       struct sljit_jump *jump;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_jump(compiler, type);
+
+       jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+       PTR_FAIL_IF(!jump);
+       set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+       type &= 0xff;
+
+       /* In ARM, we don't need to touch the arguments. */
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       if (type >= SLJIT_FAST_CALL)
+               PTR_FAIL_IF(prepare_blx(compiler));
+       PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0,
+               type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(type), 0));
+
+       if (jump->flags & SLJIT_REWRITABLE_JUMP) {
+               jump->addr = compiler->size;
+               compiler->patches++;
+       }
+
+       if (type >= SLJIT_FAST_CALL) {
+               jump->flags |= IS_BL;
+               PTR_FAIL_IF(emit_blx(compiler));
+       }
+
+       if (!(jump->flags & SLJIT_REWRITABLE_JUMP))
+               jump->addr = compiler->size;
+#else
+       if (type >= SLJIT_FAST_CALL)
+               jump->flags |= IS_BL;
+       PTR_FAIL_IF(emit_imm(compiler, TMP_REG1, 0));
+       PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)) & ~COND_MASK) | get_cc(type)));
+       jump->addr = compiler->size;
+#endif
+       return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
+{
+       struct sljit_jump *jump;
+
+       CHECK_ERROR();
+       check_sljit_emit_ijump(compiler, type, src, srcw);
+
+       /* In ARM, we don't need to touch the arguments. */
+       if (src & SLJIT_IMM) {
+               jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+               FAIL_IF(!jump);
+               set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
+               jump->u.target = srcw;
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+               if (type >= SLJIT_FAST_CALL)
+                       FAIL_IF(prepare_blx(compiler));
+               FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0));
+               if (type >= SLJIT_FAST_CALL)
+                       FAIL_IF(emit_blx(compiler));
+#else
+               FAIL_IF(emit_imm(compiler, TMP_REG1, 0));
+               FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)));
+#endif
+               jump->addr = compiler->size;
+       }
+       else {
+               if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
+                       return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src));
+
+               SLJIT_ASSERT(src & SLJIT_MEM);
+               FAIL_IF(emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
+               return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG2));
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type)
+{
+       int reg;
+       sljit_uw cc;
+
+       CHECK_ERROR();
+       check_sljit_emit_cond_value(compiler, op, dst, dstw, type);
+
+       if (dst == SLJIT_UNUSED)
+               return SLJIT_SUCCESS;
+
+       cc = get_cc(type);
+       if (GET_OPCODE(op) == SLJIT_OR) {
+               if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+                       EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ORR_DP, 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc);
+                       if (op & SLJIT_SET_E)
+                               return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst)));
+                       return SLJIT_SUCCESS;
+               }
+
+               EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, SRC2_IMM | 0));
+               EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc);
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+               compiler->skip_checks = 1;
+#endif
+               return emit_op(compiler, op, ALLOW_IMM, dst, dstw, TMP_REG1, 0, dst, dstw);
+       }
+
+       reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2;
+
+       EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, SRC2_IMM | 0));
+       EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc);
+
+       if (reg == TMP_REG2)
+               return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value)
+{
+       struct sljit_const *const_;
+       int reg;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_const(compiler, dst, dstw, init_value);
+
+       const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+       PTR_FAIL_IF(!const_);
+
+       reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2;
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+       PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), init_value));
+       compiler->patches++;
+#else
+       PTR_FAIL_IF(emit_imm(compiler, reg, init_value));
+#endif
+       set_const(const_, compiler);
+
+       if (reg == TMP_REG2 && dst != SLJIT_UNUSED)
+               if (emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, TMP_REG2, 0))
+                       return NULL;
+       return const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+{
+       inline_set_jump_addr(addr, new_addr, 1);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
+{
+       inline_set_const(addr, new_constant, 1);
+}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c b/src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c
new file mode 100644 (file)
index 0000000..c0cc8b5
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+/* mips 32-bit arch dependent functions. */
+
+static int load_immediate(struct sljit_compiler *compiler, int dst_ar, sljit_w imm)
+{
+       if (!(imm & ~0xffff))
+               return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
+
+       if (imm < 0 && imm >= SIMM_MIN)
+               return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
+
+       FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
+       return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
+}
+
+#define EMIT_LOGICAL(op_imm, op_norm) \
+       if (flags & SRC2_IMM) { \
+               if (op & SLJIT_SET_E) \
+                       FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
+               if (CHECK_FLAGS(SLJIT_SET_E)) \
+                       FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
+       } \
+       else { \
+               if (op & SLJIT_SET_E) \
+                       FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
+               if (CHECK_FLAGS(SLJIT_SET_E)) \
+                       FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
+       }
+
+#define EMIT_SHIFT(op_imm, op_norm) \
+       if (flags & SRC2_IMM) { \
+               if (op & SLJIT_SET_E) \
+                       FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
+               if (CHECK_FLAGS(SLJIT_SET_E)) \
+                       FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
+       } \
+       else { \
+               if (op & SLJIT_SET_E) \
+                       FAIL_IF(push_inst(compiler, op_norm | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
+               if (CHECK_FLAGS(SLJIT_SET_E)) \
+                       FAIL_IF(push_inst(compiler, op_norm | S(src2) | T(src1) | D(dst), DR(dst))); \
+       }
+
+static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
+       int dst, int src1, sljit_w src2)
+{
+       int overflow_ra = 0;
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_ADD:
+               if (flags & SRC2_IMM) {
+                       if (op & SLJIT_SET_O) {
+                               FAIL_IF(push_inst(compiler, SRL | T(src1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
+                               if (src2 < 0)
+                                       FAIL_IF(push_inst(compiler, XORI | SA(TMP_EREG1) | TA(TMP_EREG1) | IMM(1), TMP_EREG1));
+                       }
+                       if (op & SLJIT_SET_E)
+                               FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
+                       if (op & SLJIT_SET_C) {
+                               if (src2 >= 0)
+                                       FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
+                               else {
+                                       FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
+                                       FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
+                               }
+                       }
+                       /* dst may be the same as src1 or src2. */
+                       if (CHECK_FLAGS(SLJIT_SET_E))
+                               FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
+                       if (op & SLJIT_SET_O) {
+                               FAIL_IF(push_inst(compiler, SRL | T(dst) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
+                               if (src2 < 0)
+                                       FAIL_IF(push_inst(compiler, XORI | SA(OVERFLOW_FLAG) | TA(OVERFLOW_FLAG) | IMM(1), OVERFLOW_FLAG));
+                       }
+               }
+               else {
+                       if (op & SLJIT_SET_O) {
+                               FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
+                               FAIL_IF(push_inst(compiler, SRL | TA(TMP_EREG1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
+                               if (src1 != dst)
+                                       overflow_ra = DR(src1);
+                               else if (src2 != dst)
+                                       overflow_ra = DR(src2);
+                               else {
+                                       /* Rare ocasion. */
+                                       FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2));
+                                       overflow_ra = TMP_EREG2;
+                               }
+                       }
+                       if (op & SLJIT_SET_E)
+                               FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+                       if (op & SLJIT_SET_C)
+                               FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
+                       /* dst may be the same as src1 or src2. */
+                       if (CHECK_FLAGS(SLJIT_SET_E))
+                               FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
+                       if (op & SLJIT_SET_O) {
+                               FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(overflow_ra) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                               FAIL_IF(push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
+                       }
+               }
+
+               /* a + b >= a | b (otherwise, the carry should be set to 1). */
+               if (op & SLJIT_SET_C)
+                       FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
+               if (op & SLJIT_SET_O)
+                       return push_inst(compiler, MOVN | SA(0) | TA(TMP_EREG1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
+               return SLJIT_SUCCESS;
+
+       case SLJIT_ADDC:
+               if (flags & SRC2_IMM) {
+                       if (op & SLJIT_SET_C) {
+                               if (src2 >= 0)
+                                       FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
+                               else {
+                                       FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
+                                       FAIL_IF(push_inst(compiler, OR | S(src1) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1));
+                               }
+                       }
+                       FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
+               } else {
+                       if (op & SLJIT_SET_C)
+                               FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
+                       /* dst may be the same as src1 or src2. */
+                       FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
+               }
+               if (op & SLJIT_SET_C)
+                       FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1));
+
+               FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
+               if (!(op & SLJIT_SET_C))
+                       return SLJIT_SUCCESS;
+
+               /* Set TMP_EREG2 (dst == 0) && (ULESS_FLAG == 1). */
+               FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(TMP_EREG2) | IMM(1), TMP_EREG2));
+               FAIL_IF(push_inst(compiler, AND | SA(TMP_EREG2) | TA(ULESS_FLAG) | DA(TMP_EREG2), TMP_EREG2));
+               /* Set carry flag. */
+               return push_inst(compiler, OR | SA(TMP_EREG2) | TA(TMP_EREG1) | DA(ULESS_FLAG), ULESS_FLAG);
+
+       case SLJIT_SUB:
+               if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_S | SLJIT_SET_U)) || src2 == SIMM_MIN)) {
+                       FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
+                       src2 = TMP_REG2;
+                       flags &= ~SRC2_IMM;
+               }
+
+               if (flags & SRC2_IMM) {
+                       if (op & SLJIT_SET_O) {
+                               FAIL_IF(push_inst(compiler, SRL | T(src1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
+                               if (src2 < 0)
+                                       FAIL_IF(push_inst(compiler, XORI | SA(TMP_EREG1) | TA(TMP_EREG1) | IMM(1), TMP_EREG1));
+                               if (src1 != dst)
+                                       overflow_ra = DR(src1);
+                               else {
+                                       /* Rare ocasion. */
+                                       FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2));
+                                       overflow_ra = TMP_EREG2;
+                               }
+                       }
+                       if (op & SLJIT_SET_E)
+                               FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
+                       if (op & SLJIT_SET_C)
+                               FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
+                       /* dst may be the same as src1 or src2. */
+                       if (CHECK_FLAGS(SLJIT_SET_E))
+                               FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
+               }
+               else {
+                       if (op & SLJIT_SET_O) {
+                               FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
+                               FAIL_IF(push_inst(compiler, SRL | TA(TMP_EREG1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
+                               if (src1 != dst)
+                                       overflow_ra = DR(src1);
+                               else {
+                                       /* Rare ocasion. */
+                                       FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2));
+                                       overflow_ra = TMP_EREG2;
+                               }
+                       }
+                       if (op & SLJIT_SET_E)
+                               FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+                       if (op & (SLJIT_SET_U | SLJIT_SET_C))
+                               FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
+                       if (op & SLJIT_SET_U)
+                               FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
+                       if (op & SLJIT_SET_S) {
+                               FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG));
+                               FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
+                       }
+                       /* dst may be the same as src1 or src2. */
+                       if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_C))
+                               FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
+               }
+
+               if (op & SLJIT_SET_O) {
+                       FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(overflow_ra) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
+                       FAIL_IF(push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
+                       return push_inst(compiler, MOVZ | SA(0) | TA(TMP_EREG1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
+               }
+               return SLJIT_SUCCESS;
+
+       case SLJIT_SUBC:
+               if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
+                       FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
+                       src2 = TMP_REG2;
+                       flags &= ~SRC2_IMM;
+               }
+
+               if (flags & SRC2_IMM) {
+                       if (op & SLJIT_SET_C)
+                               FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(TMP_EREG1) | IMM(-src2), TMP_EREG1));
+                       /* dst may be the same as src1 or src2. */
+                       FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
+               }
+               else {
+                       if (op & SLJIT_SET_C)
+                               FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
+                       /* dst may be the same as src1 or src2. */
+                       FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
+               }
+
+               if (op & SLJIT_SET_C)
+                       FAIL_IF(push_inst(compiler, MOVZ | SA(ULESS_FLAG) | T(dst) | DA(TMP_EREG1), TMP_EREG1));
+
+               FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
+
+               if (op & SLJIT_SET_C)
+                       FAIL_IF(push_inst(compiler, ADDU | SA(TMP_EREG1) | TA(0) | DA(ULESS_FLAG), ULESS_FLAG));
+
+               return SLJIT_SUCCESS;
+
+       case SLJIT_MUL:
+               SLJIT_ASSERT(!(flags & SRC2_IMM));
+               if (!(op & SLJIT_SET_O)) {
+#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
+                       return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
+#else
+                       FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
+                       return push_inst(compiler, MFLO | D(dst), DR(dst));
+#endif
+               }
+               FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
+               FAIL_IF(push_inst(compiler, MFHI | DA(TMP_EREG1), TMP_EREG1));
+               FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
+               FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(TMP_EREG2) | SH_IMM(31), TMP_EREG2));
+               return push_inst(compiler, SUBU | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
+
+       case SLJIT_AND:
+               EMIT_LOGICAL(ANDI, AND);
+               return SLJIT_SUCCESS;
+
+       case SLJIT_OR:
+               EMIT_LOGICAL(ORI, OR);
+               return SLJIT_SUCCESS;
+
+       case SLJIT_XOR:
+               EMIT_LOGICAL(XORI, XOR);
+               return SLJIT_SUCCESS;
+
+       case SLJIT_SHL:
+               EMIT_SHIFT(SLL, SLLV);
+               return SLJIT_SUCCESS;
+
+       case SLJIT_LSHR:
+               EMIT_SHIFT(SRL, SRLV);
+               return SLJIT_SUCCESS;
+
+       case SLJIT_ASHR:
+               EMIT_SHIFT(SRA, SRAV);
+               return SLJIT_SUCCESS;
+
+       case SLJIT_MOV:
+       case SLJIT_MOV_UI:
+       case SLJIT_MOV_SI:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               if (dst != src2)
+                       return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst));
+               return SLJIT_SUCCESS;
+
+       case SLJIT_MOV_UB:
+       case SLJIT_MOV_SB:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+                       if (op == SLJIT_MOV_SB) {
+#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
+                               return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
+#else
+                               FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
+                               return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
+#endif
+                       }
+                       return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
+               }
+               else if (dst != src2)
+                       SLJIT_ASSERT_STOP();
+               return SLJIT_SUCCESS;
+
+       case SLJIT_MOV_UH:
+       case SLJIT_MOV_SH:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+                       if (op == SLJIT_MOV_SH) {
+#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
+                               return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
+#else
+                               FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
+                               return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
+#endif
+                       }
+                       return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
+               }
+               else if (dst != src2)
+                       SLJIT_ASSERT_STOP();
+               return SLJIT_SUCCESS;
+
+       case SLJIT_NOT:
+               SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+               if (op & SLJIT_SET_E)
+                       FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+               if (CHECK_FLAGS(SLJIT_SET_E))
+                       FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
+               return SLJIT_SUCCESS;
+
+       case SLJIT_CLZ:
+               SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
+               if (op & SLJIT_SET_E)
+                       FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
+               if (CHECK_FLAGS(SLJIT_SET_E))
+                       FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));
+#else
+               if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
+                       FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
+                       return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
+               }
+               /* Nearly all instructions are unmovable in the following sequence. */
+               FAIL_IF(push_inst(compiler, ADDU_W | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
+               /* Check zero. */
+               FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(6), UNMOVABLE_INS));
+               FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS));
+               /* Check sign bit. */
+               FAIL_IF(push_inst(compiler, BLTZ | S(TMP_REG1) | IMM(4), UNMOVABLE_INS));
+               FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(0), UNMOVABLE_INS));
+               /* Loop for searching the highest bit. */
+               FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));
+               FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
+               FAIL_IF(push_inst(compiler, ADDIU_W | S(dst) | T(dst) | IMM(1), UNMOVABLE_INS));
+               if (op & SLJIT_SET_E)
+                       return push_inst(compiler, ADDU_W | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
+#endif
+               return SLJIT_SUCCESS;
+       }
+
+       SLJIT_ASSERT_STOP();
+       return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value)
+{
+       FAIL_IF(push_inst(compiler, LUI | T(reg) | IMM(init_value >> 16), DR(reg)));
+       return push_inst(compiler, ORI | S(reg) | T(reg) | IMM(init_value), DR(reg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+{
+       sljit_ins *inst = (sljit_ins*)addr;
+
+       inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
+       inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff);
+       SLJIT_CACHE_FLUSH(inst, inst + 2);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
+{
+       sljit_ins *inst = (sljit_ins*)addr;
+
+       inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
+       inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
+       SLJIT_CACHE_FLUSH(inst, inst + 2);
+}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c b/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c
new file mode 100644 (file)
index 0000000..3c6ee66
--- /dev/null
@@ -0,0 +1,1829 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
+{
+       return "MIPS" SLJIT_CPUINFO;
+}
+
+/* Latest MIPS architecture. */
+/* Detect SLJIT_MIPS_32_64 */
+
+/* Length of an instruction word
+   Both for mips-32 and mips-64 */
+typedef sljit_ui sljit_ins;
+
+#define TMP_REG1       (SLJIT_NO_REGISTERS + 1)
+#define TMP_REG2       (SLJIT_NO_REGISTERS + 2)
+#define TMP_REG3       (SLJIT_NO_REGISTERS + 3)
+#define REAL_STACK_PTR (SLJIT_NO_REGISTERS + 4)
+
+/* For position independent code, t9 must contain the function address. */
+#define PIC_ADDR_REG           TMP_REG2
+
+/* TMP_EREG1 is used mainly for literal encoding on 64 bit. */
+#define TMP_EREG1              15
+#define TMP_EREG2              24
+/* Floating point status register. */
+#define FCSR_REG               31
+/* Return address register. */
+#define RETURN_ADDR_REG                31
+
+/* Flags are keept in volatile registers. */
+#define EQUAL_FLAG     7
+/* And carry flag as well. */
+#define ULESS_FLAG     10
+#define UGREATER_FLAG  11
+#define LESS_FLAG      12
+#define GREATER_FLAG   13
+#define OVERFLOW_FLAG  14
+
+#define TMP_FREG1      (SLJIT_FLOAT_REG4 + 1)
+#define TMP_FREG2      (SLJIT_FLOAT_REG4 + 2)
+
+/* --------------------------------------------------------------------- */
+/*  Instrucion forms                                                     */
+/* --------------------------------------------------------------------- */
+
+#define S(s)           (reg_map[s] << 21)
+#define T(t)           (reg_map[t] << 16)
+#define D(d)           (reg_map[d] << 11)
+/* Absolute registers. */
+#define SA(s)          ((s) << 21)
+#define TA(t)          ((t) << 16)
+#define DA(d)          ((d) << 11)
+#define FT(t)          ((t) << (16 + 1))
+#define FS(s)          ((s) << (11 + 1))
+#define FD(d)          ((d) << (6 + 1))
+#define IMM(imm)       ((imm) & 0xffff)
+#define SH_IMM(imm)    ((imm & 0x1f) << 6)
+
+#define DR(dr)         (reg_map[dr])
+#define HI(opcode)     ((opcode) << 26)
+#define LO(opcode)     (opcode)
+#define FMT_D          (17 << 21)
+
+#define ABS_D          (HI(17) | FMT_D | LO(5))
+#define ADD_D          (HI(17) | FMT_D | LO(0))
+#define ADDU           (HI(0) | LO(33))
+#define ADDIU          (HI(9))
+#define AND            (HI(0) | LO(36))
+#define ANDI           (HI(12))
+#define B              (HI(4))
+#define BAL            (HI(1) | (17 << 16))
+#define BC1F           (HI(17) | (8 << 21))
+#define BC1T           (HI(17) | (8 << 21) | (1 << 16))
+#define BEQ            (HI(4))
+#define BGEZ           (HI(1) | (1 << 16))
+#define BGTZ           (HI(7))
+#define BLEZ           (HI(6))
+#define BLTZ           (HI(1) | (0 << 16))
+#define BNE            (HI(5))
+#define BREAK          (HI(0) | LO(13))
+#define C_UN_D         (HI(17) | FMT_D | LO(49))
+#define C_UEQ_D                (HI(17) | FMT_D | LO(51))
+#define C_ULE_D                (HI(17) | FMT_D | LO(55))
+#define C_ULT_D                (HI(17) | FMT_D | LO(53))
+#define DIV            (HI(0) | LO(26))
+#define DIVU           (HI(0) | LO(27))
+#define DIV_D          (HI(17) | FMT_D | LO(3))
+#define J              (HI(2))
+#define JAL            (HI(3))
+#define JALR           (HI(0) | LO(9))
+#define JR             (HI(0) | LO(8))
+#define LD             (HI(55))
+#define LDC1           (HI(53))
+#define LUI            (HI(15))
+#define LW             (HI(35))
+#define NEG_D          (HI(17) | FMT_D | LO(7))
+#define MFHI           (HI(0) | LO(16))
+#define MFLO           (HI(0) | LO(18))
+#define MOV_D          (HI(17) | FMT_D | LO(6))
+#define CFC1           (HI(17) | (2 << 21))
+#define MOVN           (HI(0) | LO(11))
+#define MOVZ           (HI(0) | LO(10))
+#define MUL_D          (HI(17) | FMT_D | LO(2))
+#define MULT           (HI(0) | LO(24))
+#define MULTU          (HI(0) | LO(25))
+#define NOP            (HI(0) | LO(0))
+#define NOR            (HI(0) | LO(39))
+#define OR             (HI(0) | LO(37))
+#define ORI            (HI(13))
+#define SD             (HI(63))
+#define SDC1           (HI(61))
+#define SLT            (HI(0) | LO(42))
+#define SLTI           (HI(10))
+#define SLTIU          (HI(11))
+#define SLTU           (HI(0) | LO(43))
+#define SLL            (HI(0) | LO(0))
+#define SLLV           (HI(0) | LO(4))
+#define SRL            (HI(0) | LO(2))
+#define SRLV           (HI(0) | LO(6))
+#define SRA            (HI(0) | LO(3))
+#define SRAV           (HI(0) | LO(7))
+#define SUB_D          (HI(17) | FMT_D | LO(1))
+#define SUBU           (HI(0) | LO(35))
+#define SW             (HI(43))
+#define XOR            (HI(0) | LO(38))
+#define XORI           (HI(14))
+
+#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
+#define CLZ            (HI(28) | LO(32))
+#define MUL            (HI(28) | LO(2))
+#define SEB            (HI(31) | (16 << 6) | LO(32))
+#define SEH            (HI(31) | (24 << 6) | LO(32))
+#endif
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#define ADDU_W         ADDU
+#define ADDIU_W                ADDIU
+#define SLL_W          SLL
+#define SUBU_W         SUBU
+#else
+#define ADDU_W         DADDU
+#define ADDIU_W                DADDIU
+#define SLL_W          DSLL
+#define SUBU_W         DSUBU
+#endif
+
+#define SIMM_MAX       (0x7fff)
+#define SIMM_MIN       (-0x8000)
+#define UIMM_MAX       (0xffff)
+
+static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 6] = {
+  0, 2, 5, 6, 3, 8, 17, 18, 19, 20, 21, 16, 4, 25, 9, 29
+};
+
+/* dest_reg is the absolute name of the register
+   Useful for reordering instructions in the delay slot. */
+static int push_inst(struct sljit_compiler *compiler, sljit_ins ins, int delay_slot)
+{
+       sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+       FAIL_IF(!ptr);
+       *ptr = ins;
+       compiler->size++;
+       compiler->delay_slot = delay_slot;
+       return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_ins invert_branch(int flags)
+{
+       return (flags & IS_BIT26_COND) ? (1 << 26) : (1 << 16);
+}
+
+static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+{
+       sljit_w diff;
+       sljit_uw target_addr;
+       sljit_ins *inst;
+       sljit_ins saved_inst;
+
+       if (jump->flags & SLJIT_REWRITABLE_JUMP)
+               return code_ptr;
+
+       if (jump->flags & JUMP_ADDR)
+               target_addr = jump->u.target;
+       else {
+               SLJIT_ASSERT(jump->flags & JUMP_LABEL);
+               target_addr = (sljit_uw)(code + jump->u.label->size);
+       }
+       inst = (sljit_ins*)jump->addr;
+       if (jump->flags & IS_COND)
+               inst--;
+
+       /* B instructions. */
+       if (jump->flags & IS_MOVABLE) {
+               diff = ((sljit_w)target_addr - (sljit_w)(inst)) >> 2;
+               if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
+                       jump->flags |= PATCH_B;
+
+                       if (!(jump->flags & IS_COND)) {
+                               inst[0] = inst[-1];
+                               inst[-1] = (jump->flags & IS_JAL) ? BAL : B;
+                               jump->addr -= sizeof(sljit_ins);
+                               return inst;
+                       }
+                       saved_inst = inst[0];
+                       inst[0] = inst[-1];
+                       inst[-1] = saved_inst ^ invert_branch(jump->flags);
+                       jump->addr -= 2 * sizeof(sljit_ins);
+                       return inst;
+               }
+       }
+
+       diff = ((sljit_w)target_addr - (sljit_w)(inst + 1)) >> 2;
+       if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
+               jump->flags |= PATCH_B;
+
+               if (!(jump->flags & IS_COND)) {
+                       inst[0] = (jump->flags & IS_JAL) ? BAL : B;
+                       inst[1] = NOP;
+                       return inst + 1;
+               }
+               inst[0] = inst[0] ^ invert_branch(jump->flags);
+               inst[1] = NOP;
+               jump->addr -= sizeof(sljit_ins);
+               return inst + 1;
+       }
+
+       if (jump->flags & IS_COND) {
+               if ((target_addr & ~0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~0xfffffff)) {
+                       jump->flags |= PATCH_J;
+                       inst[0] = (inst[0] & 0xffff0000) | 3;
+                       inst[1] = NOP;
+                       inst[2] = J;
+                       inst[3] = NOP;
+                       jump->addr += sizeof(sljit_ins);
+                       return inst + 3;
+               }
+               return code_ptr;
+       }
+
+       /* J instuctions. */
+       if (jump->flags & IS_MOVABLE) {
+               if ((target_addr & ~0xfffffff) == (jump->addr & ~0xfffffff)) {
+                       jump->flags |= PATCH_J;
+                       inst[0] = inst[-1];
+                       inst[-1] = (jump->flags & IS_JAL) ? JAL : J;
+                       jump->addr -= sizeof(sljit_ins);
+                       return inst;
+               }
+       }
+
+       if ((target_addr & ~0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~0xfffffff)) {
+               jump->flags |= PATCH_J;
+               inst[0] = (jump->flags & IS_JAL) ? JAL : J;
+               inst[1] = NOP;
+               return inst + 1;
+       }
+
+       return code_ptr;
+}
+
+#ifdef __GNUC__
+static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ptr)
+{
+       SLJIT_CACHE_FLUSH(code, code_ptr);
+}
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
+{
+       struct sljit_memory_fragment *buf;
+       sljit_ins *code;
+       sljit_ins *code_ptr;
+       sljit_ins *buf_ptr;
+       sljit_ins *buf_end;
+       sljit_uw word_count;
+       sljit_uw addr;
+
+       struct sljit_label *label;
+       struct sljit_jump *jump;
+       struct sljit_const *const_;
+
+       CHECK_ERROR_PTR();
+       check_sljit_generate_code(compiler);
+       reverse_buf(compiler);
+
+       code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins));
+       PTR_FAIL_WITH_EXEC_IF(code);
+       buf = compiler->buf;
+
+       code_ptr = code;
+       word_count = 0;
+       label = compiler->labels;
+       jump = compiler->jumps;
+       const_ = compiler->consts;
+       do {
+               buf_ptr = (sljit_ins*)buf->memory;
+               buf_end = buf_ptr + (buf->used_size >> 2);
+               do {
+                       *code_ptr = *buf_ptr++;
+                       SLJIT_ASSERT(!label || label->size >= word_count);
+                       SLJIT_ASSERT(!jump || jump->addr >= word_count);
+                       SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+                       /* These structures are ordered by their address. */
+                       if (label && label->size == word_count) {
+                               /* Just recording the address. */
+                               label->addr = (sljit_uw)code_ptr;
+                               label->size = code_ptr - code;
+                               label = label->next;
+                       }
+                       if (jump && jump->addr == word_count) {
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+                               jump->addr = (sljit_uw)(code_ptr - 3);
+#else
+                               jump->addr = (sljit_uw)(code_ptr - 6);
+#endif
+                               code_ptr = optimize_jump(jump, code_ptr, code);
+                               jump = jump->next;
+                       }
+                       if (const_ && const_->addr == word_count) {
+                               /* Just recording the address. */
+                               const_->addr = (sljit_uw)code_ptr;
+                               const_ = const_->next;
+                       }
+                       code_ptr ++;
+                       word_count ++;
+               } while (buf_ptr < buf_end);
+
+               buf = buf->next;
+       } while (buf);
+
+       if (label && label->size == word_count) {
+               label->addr = (sljit_uw)code_ptr;
+               label->size = code_ptr - code;
+               label = label->next;
+       }
+
+       SLJIT_ASSERT(!label);
+       SLJIT_ASSERT(!jump);
+       SLJIT_ASSERT(!const_);
+       SLJIT_ASSERT(code_ptr - code <= (int)compiler->size);
+
+       jump = compiler->jumps;
+       while (jump) {
+               do {
+                       addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
+                       buf_ptr = (sljit_ins*)jump->addr;
+
+                       if (jump->flags & PATCH_B) {
+                               addr = (sljit_w)(addr - (jump->addr + sizeof(sljit_ins))) >> 2;
+                               SLJIT_ASSERT((sljit_w)addr <= SIMM_MAX && (sljit_w)addr >= SIMM_MIN);
+                               buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | (addr & 0xffff);
+                               break;
+                       }
+                       if (jump->flags & PATCH_J) {
+                               SLJIT_ASSERT((addr & ~0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~0xfffffff));
+                               buf_ptr[0] |= (addr >> 2) & 0x03ffffff;
+                               break;
+                       }
+
+                       /* Set the fields of immediate loads. */
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+                       buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
+                       buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
+#else
+                       buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff);
+                       buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff);
+                       buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff);
+                       buf_ptr[4] = (buf_ptr[4] & 0xffff0000) | (addr & 0xffff);
+#endif
+               } while (0);
+               jump = jump->next;
+       }
+
+       compiler->error = SLJIT_ERR_COMPILED;
+       compiler->executable_size = compiler->size * sizeof(sljit_ins);
+#ifndef __GNUC__
+       SLJIT_CACHE_FLUSH(code, code_ptr);
+#else
+       /* GCC workaround for invalid code generation with -O2. */
+       sljit_cache_flush(code, code_ptr);
+#endif
+       return code;
+}
+
+/* Creates an index in data_transfer_insts array. */
+#define WORD_DATA      0x00
+#define BYTE_DATA      0x01
+#define HALF_DATA      0x02
+#define INT_DATA       0x03
+#define SIGNED_DATA    0x04
+#define LOAD_DATA      0x08
+
+#define MEM_MASK       0x0f
+
+#define WRITE_BACK     0x00010
+#define ARG_TEST       0x00020
+#define CUMULATIVE_OP  0x00040
+#define LOGICAL_OP     0x00080
+#define IMM_OP         0x00100
+#define SRC2_IMM       0x00200
+
+#define UNUSED_DEST    0x00400
+#define REG_DEST       0x00800
+#define REG1_SOURCE    0x01000
+#define REG2_SOURCE    0x02000
+#define SLOW_SRC1      0x04000
+#define SLOW_SRC2      0x08000
+#define SLOW_DEST      0x10000
+
+/* Only these flags are set. UNUSED_DEST is not set when no flags should be set. */
+#define CHECK_FLAGS(list) \
+       (!(flags & UNUSED_DEST) || (op & GET_FLAGS(~(list))))
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#include "sljitNativeMIPS_32.c"
+#else
+#include "sljitNativeMIPS_64.c"
+#endif
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#define STACK_STORE    SW
+#define STACK_LOAD     LW
+#else
+#define STACK_STORE    SD
+#define STACK_LOAD     LD
+#endif
+
+static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w);
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       sljit_ins base;
+
+       CHECK_ERROR();
+       check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+
+       compiler->has_locals = local_size > 0;
+       local_size += (saveds + 2 + 4) * sizeof(sljit_w);
+       local_size = (local_size + 15) & ~0xf;
+       compiler->local_size = local_size;
+
+       if (local_size <= SIMM_MAX) {
+               /* Frequent case. */
+               FAIL_IF(push_inst(compiler, ADDIU_W | S(REAL_STACK_PTR) | T(REAL_STACK_PTR) | IMM(-local_size), DR(REAL_STACK_PTR)));
+               base = S(REAL_STACK_PTR);
+       }
+       else {
+               FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size));
+               FAIL_IF(push_inst(compiler, ADDU_W | S(REAL_STACK_PTR) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
+               FAIL_IF(push_inst(compiler, SUBU_W | S(REAL_STACK_PTR) | T(TMP_REG1) | D(REAL_STACK_PTR), DR(REAL_STACK_PTR)));
+               base = S(TMP_REG2);
+               local_size = 0;
+       }
+
+       FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(local_size - 1 * (int)sizeof(sljit_w)), MOVABLE_INS));
+       if (compiler->has_locals)
+               FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_LOCALS_REG) | IMM(local_size - 2 * (int)sizeof(sljit_w)), MOVABLE_INS));
+       if (saveds >= 1)
+               FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG1) | IMM(local_size - 3 * (int)sizeof(sljit_w)), MOVABLE_INS));
+       if (saveds >= 2)
+               FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG2) | IMM(local_size - 4 * (int)sizeof(sljit_w)), MOVABLE_INS));
+       if (saveds >= 3)
+               FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG3) | IMM(local_size - 5 * (int)sizeof(sljit_w)), MOVABLE_INS));
+       if (saveds >= 4)
+               FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_EREG1) | IMM(local_size - 6 * (int)sizeof(sljit_w)), MOVABLE_INS));
+       if (saveds >= 5)
+               FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_EREG2) | IMM(local_size - 7 * (int)sizeof(sljit_w)), MOVABLE_INS));
+
+       if (compiler->has_locals)
+               FAIL_IF(push_inst(compiler, ADDIU_W | S(REAL_STACK_PTR) | T(SLJIT_LOCALS_REG) | IMM(4 * sizeof(sljit_w)), DR(SLJIT_LOCALS_REG)));
+
+       if (args >= 1)
+               FAIL_IF(push_inst(compiler, ADDU_W | SA(4) | TA(0) | D(SLJIT_SAVED_REG1), DR(SLJIT_SAVED_REG1)));
+       if (args >= 2)
+               FAIL_IF(push_inst(compiler, ADDU_W | SA(5) | TA(0) | D(SLJIT_SAVED_REG2), DR(SLJIT_SAVED_REG2)));
+       if (args >= 3)
+               FAIL_IF(push_inst(compiler, ADDU_W | SA(6) | TA(0) | D(SLJIT_SAVED_REG3), DR(SLJIT_SAVED_REG3)));
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       CHECK_ERROR_VOID();
+       check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+
+       compiler->has_locals = local_size > 0;
+       local_size += (saveds + 2 + 4) * sizeof(sljit_w);
+       compiler->local_size = (local_size + 15) & ~0xf;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+{
+       int local_size;
+       sljit_ins base;
+
+       CHECK_ERROR();
+       check_sljit_emit_return(compiler, op, src, srcw);
+
+       FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+
+       local_size = compiler->local_size;
+       if (local_size <= SIMM_MAX)
+               base = S(REAL_STACK_PTR);
+       else {
+               FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size));
+               FAIL_IF(push_inst(compiler, ADDU_W | S(REAL_STACK_PTR) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1)));
+               base = S(TMP_REG1);
+               local_size = 0;
+       }
+
+       FAIL_IF(push_inst(compiler, STACK_LOAD | base | TA(RETURN_ADDR_REG) | IMM(local_size - 1 * (int)sizeof(sljit_w)), RETURN_ADDR_REG));
+       if (compiler->saveds >= 5)
+               FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_EREG2) | IMM(local_size - 7 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_EREG2)));
+       if (compiler->saveds >= 4)
+               FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_EREG1) | IMM(local_size - 6 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_EREG1)));
+       if (compiler->saveds >= 3)
+               FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG3) | IMM(local_size - 5 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_REG3)));
+       if (compiler->saveds >= 2)
+               FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG2) | IMM(local_size - 4 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_REG2)));
+       if (compiler->saveds >= 1)
+               FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG1) | IMM(local_size - 3 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_REG1)));
+       if (compiler->has_locals)
+               FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_LOCALS_REG) | IMM(local_size - 2 * (int)sizeof(sljit_w)), DR(SLJIT_LOCALS_REG)));
+
+       FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
+       if (compiler->local_size <= SIMM_MAX)
+               return push_inst(compiler, ADDIU_W | S(REAL_STACK_PTR) | T(REAL_STACK_PTR) | IMM(compiler->local_size), UNMOVABLE_INS);
+       else
+               return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(REAL_STACK_PTR), UNMOVABLE_INS);
+}
+
+#undef STACK_STORE
+#undef STACK_LOAD
+
+/* --------------------------------------------------------------------- */
+/*  Operators                                                            */
+/* --------------------------------------------------------------------- */
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#define ARCH_DEPEND(a, b)      a
+#else
+#define ARCH_DEPEND(a, b)      b
+#endif
+
+static SLJIT_CONST sljit_ins data_transfer_insts[16] = {
+/* s u w */ ARCH_DEPEND(HI(43) /* sw */, HI(63) /* sd */),
+/* s u b */ HI(40) /* sb */,
+/* s u h */ HI(41) /* sh*/,
+/* s u i */ HI(43) /* sw */,
+
+/* s s w */ ARCH_DEPEND(HI(43) /* sw */, HI(63) /* sd */),
+/* s s b */ HI(40) /* sb */,
+/* s s h */ HI(41) /* sh*/,
+/* s s i */ HI(43) /* sw */,
+
+/* l u w */ ARCH_DEPEND(HI(35) /* lw */, HI(55) /* ld */),
+/* l u b */ HI(36) /* lbu */,
+/* l u h */ HI(37) /* lhu */,
+/* l u i */ ARCH_DEPEND(HI(35) /* lw */, HI(39) /* lwu */),
+
+/* l s w */ ARCH_DEPEND(HI(35) /* lw */, HI(55) /* ld */),
+/* l s b */ HI(32) /* lb */,
+/* l s h */ HI(33) /* lh */,
+/* l s i */ HI(35) /* lw */,
+};
+
+/* reg_ar is an absoulute register! */
+
+/* Can perform an operation using at most 1 instruction. */
+static int getput_arg_fast(struct sljit_compiler *compiler, int flags, int reg_ar, int arg, sljit_w argw)
+{
+       SLJIT_ASSERT(arg & SLJIT_MEM);
+
+       if (!(flags & WRITE_BACK) && !(arg & 0xf0) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
+               /* Works for both absoulte and relative addresses. */
+               if (SLJIT_UNLIKELY(flags & ARG_TEST))
+                       return 1;
+               FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & 0xf) | TA(reg_ar) | IMM(argw), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS));
+               return -1;
+       }
+       return (flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
+}
+
+/* See getput_arg below.
+   Note: can_cache is called only for binary operators. Those
+   operators always uses word arguments without write back. */
+static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+{
+       if (!(next_arg & SLJIT_MEM))
+               return 0;
+
+       /* Simple operation except for updates. */
+       if (arg & 0xf0) {
+               argw &= 0x3;
+               next_argw &= 0x3;
+               if (argw && argw == next_argw && (arg == next_arg || (arg & 0xf0) == (next_arg & 0xf0)))
+                       return 1;
+               return 0;
+       }
+
+       if (arg == next_arg) {
+               if (((sljit_uw)(next_argw - argw) <= SIMM_MAX && (sljit_uw)(next_argw - argw) >= SIMM_MIN))
+                       return 1;
+               return 0;
+       }
+
+       return 0;
+}
+
+/* Emit the necessary instructions. See can_cache above. */
+static int getput_arg(struct sljit_compiler *compiler, int flags, int reg_ar, int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+{
+       int tmp_ar;
+       int base;
+
+       SLJIT_ASSERT(arg & SLJIT_MEM);
+       if (!(next_arg & SLJIT_MEM)) {
+               next_arg = 0;
+               next_argw = 0;
+       }
+
+       tmp_ar = (flags & LOAD_DATA) ? reg_ar : DR(TMP_REG3);
+       base = arg & 0xf;
+
+       if (SLJIT_UNLIKELY(arg & 0xf0)) {
+               argw &= 0x3;
+               if ((flags & WRITE_BACK) && reg_ar == DR(base)) {
+                       SLJIT_ASSERT(!(flags & LOAD_DATA) && DR(TMP_REG1) != reg_ar);
+                       FAIL_IF(push_inst(compiler, ADDU_W | SA(reg_ar) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
+                       reg_ar = DR(TMP_REG1);
+               }
+
+               /* Using the cache. */
+               if (argw == compiler->cache_argw) {
+                       if (!(flags & WRITE_BACK)) {
+                               if (arg == compiler->cache_arg)
+                                       return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+                               if ((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg) {
+                                       if (arg == next_arg && argw == (next_argw & 0x3)) {
+                                               compiler->cache_arg = arg;
+                                               compiler->cache_argw = argw;
+                                               FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
+                                               return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+                                       }
+                                       FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));
+                                       return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+                               }
+                       }
+                       else {
+                               if ((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg) {
+                                       FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base)));
+                                       return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+                               }
+                       }
+               }
+
+               if (SLJIT_UNLIKELY(argw)) {
+                       compiler->cache_arg = SLJIT_MEM | (arg & 0xf0);
+                       compiler->cache_argw = argw;
+                       FAIL_IF(push_inst(compiler, SLL_W | T((arg >> 4) & 0xf) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));
+               }
+
+               if (!(flags & WRITE_BACK)) {
+                       if (arg == next_arg && argw == (next_argw & 0x3)) {
+                               compiler->cache_arg = arg;
+                               compiler->cache_argw = argw;
+                               FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? ((arg >> 4) & 0xf) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
+                               tmp_ar = DR(TMP_REG3);
+                       }
+                       else
+                               FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? ((arg >> 4) & 0xf) : TMP_REG3) | DA(tmp_ar), tmp_ar));
+                       return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+               }
+               FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? ((arg >> 4) & 0xf) : TMP_REG3) | D(base), DR(base)));
+               return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+       }
+
+       if (SLJIT_UNLIKELY(flags & WRITE_BACK) && base) {
+               /* Update only applies if a base register exists. */
+               if (reg_ar == DR(base)) {
+                       SLJIT_ASSERT(!(flags & LOAD_DATA) && DR(TMP_REG1) != reg_ar);
+                       if (argw <= SIMM_MAX && argw >= SIMM_MIN) {
+                               FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar) | IMM(argw), MOVABLE_INS));
+                               if (argw)
+                                       return push_inst(compiler, ADDIU_W | S(base) | T(base) | IMM(argw), DR(base));
+                               return SLJIT_SUCCESS;
+                       }
+                       FAIL_IF(push_inst(compiler, ADDU_W | SA(reg_ar) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
+                       reg_ar = DR(TMP_REG1);
+               }
+
+               if (argw <= SIMM_MAX && argw >= SIMM_MIN) {
+                       if (argw)
+                               FAIL_IF(push_inst(compiler, ADDIU_W | S(base) | T(base) | IMM(argw), DR(base)));
+               }
+               else {
+                       if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {
+                               if (argw != compiler->cache_argw) {
+                                       FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
+                                       compiler->cache_argw = argw;
+                               }
+                               FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base)));
+                       }
+                       else {
+                               compiler->cache_arg = SLJIT_MEM;
+                               compiler->cache_argw = argw;
+                               FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));
+                               FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base)));
+                       }
+               }
+               return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+       }
+
+       if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {
+               if (argw != compiler->cache_argw) {
+                       FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
+                       compiler->cache_argw = argw;
+               }
+               return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+       }
+
+       if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {
+               if (argw != compiler->cache_argw)
+                       FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
+       }
+       else {
+               compiler->cache_arg = SLJIT_MEM;
+               FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));
+       }
+       compiler->cache_argw = argw;
+
+       if (!base)
+               return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+
+       if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {
+               compiler->cache_arg = arg;
+               FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3)));
+               return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+       }
+
+       FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar));
+       return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS);
+}
+
+static SLJIT_INLINE int emit_op_mem(struct sljit_compiler *compiler, int flags, int reg_ar, int arg, sljit_w argw)
+{
+       if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))
+               return compiler->error;
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+       return getput_arg(compiler, flags, reg_ar, arg, argw, 0, 0);
+}
+
+static int emit_op(struct sljit_compiler *compiler, int op, int flags,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       /* arg1 goes to TMP_REG1 or src reg
+          arg2 goes to TMP_REG2, imm or src reg
+          TMP_REG3 can be used for caching
+          result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
+       int dst_r = TMP_REG2;
+       int src1_r;
+       sljit_w src2_r = 0;
+       int sugg_src2_r = TMP_REG2;
+
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+
+       if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REG3) {
+               dst_r = dst;
+               flags |= REG_DEST;
+               if (GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI)
+                       sugg_src2_r = dst_r;
+       }
+       else if (dst == SLJIT_UNUSED) {
+               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
+                       return SLJIT_SUCCESS;
+               if (GET_FLAGS(op))
+                       flags |= UNUSED_DEST;
+       }
+       else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))
+               flags |= SLOW_DEST;
+
+       if (flags & IMM_OP) {
+               if ((src2 & SLJIT_IMM) && src2w) {
+                       if ((!(flags & LOGICAL_OP) && (src2w <= SIMM_MAX && src2w >= SIMM_MIN))
+                               || ((flags & LOGICAL_OP) && !(src2w & ~UIMM_MAX))) {
+                               flags |= SRC2_IMM;
+                               src2_r = src2w;
+                       }
+               }
+               if ((src1 & SLJIT_IMM) && src1w && (flags & CUMULATIVE_OP) && !(flags & SRC2_IMM)) {
+                       if ((!(flags & LOGICAL_OP) && (src1w <= SIMM_MAX && src1w >= SIMM_MIN))
+                               || ((flags & LOGICAL_OP) && !(src1w & ~UIMM_MAX))) {
+                               flags |= SRC2_IMM;
+                               src2_r = src1w;
+
+                               /* And swap arguments. */
+                               src1 = src2;
+                               src1w = src2w;
+                               src2 = SLJIT_IMM;
+                               /* src2w = src2_r unneeded. */
+                       }
+               }
+       }
+
+       /* Source 1. */
+       if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= TMP_REG3) {
+               src1_r = src1;
+               flags |= REG1_SOURCE;
+       }
+       else if (src1 & SLJIT_IMM) {
+               if (src1w) {
+                       FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
+                       src1_r = TMP_REG1;
+               }
+               else
+                       src1_r = 0;
+       }
+       else {
+               if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w))
+                       FAIL_IF(compiler->error);
+               else
+                       flags |= SLOW_SRC1;
+               src1_r = TMP_REG1;
+       }
+
+       /* Source 2. */
+       if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REG3) {
+               src2_r = src2;
+               flags |= REG2_SOURCE;
+               if (!(flags & REG_DEST) && GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI)
+                       dst_r = src2_r;
+       }
+       else if (src2 & SLJIT_IMM) {
+               if (!(flags & SRC2_IMM)) {
+                       if (src2w || (GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI)) {
+                               FAIL_IF(load_immediate(compiler, DR(sugg_src2_r), src2w));
+                               src2_r = sugg_src2_r;
+                       }
+                       else
+                               src2_r = 0;
+               }
+       }
+       else {
+               if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w))
+                       FAIL_IF(compiler->error);
+               else
+                       flags |= SLOW_SRC2;
+               src2_r = sugg_src2_r;
+       }
+
+       if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
+               SLJIT_ASSERT(src2_r == TMP_REG2);
+               if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
+                       FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));
+                       FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
+               }
+               else {
+                       FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, src2, src2w));
+                       FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, dst, dstw));
+               }
+       }
+       else if (flags & SLOW_SRC1)
+               FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
+       else if (flags & SLOW_SRC2)
+               FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w, dst, dstw));
+
+       FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
+
+       if (dst & SLJIT_MEM) {
+               if (!(flags & SLOW_DEST)) {
+                       getput_arg_fast(compiler, flags, DR(dst_r), dst, dstw);
+                       return compiler->error;
+               }
+               return getput_arg(compiler, flags, DR(dst_r), dst, dstw, 0, 0);
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
+{
+       CHECK_ERROR();
+       check_sljit_emit_op0(compiler, op);
+
+       op = GET_OPCODE(op);
+       switch (op) {
+       case SLJIT_BREAKPOINT:
+               return push_inst(compiler, BREAK, UNMOVABLE_INS);
+       case SLJIT_NOP:
+               return push_inst(compiler, NOP, UNMOVABLE_INS);
+       case SLJIT_UMUL:
+       case SLJIT_SMUL:
+               FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? MULTU : MULT) | S(SLJIT_TEMPORARY_REG1) | T(SLJIT_TEMPORARY_REG2), MOVABLE_INS));
+               FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_TEMPORARY_REG1), DR(SLJIT_TEMPORARY_REG1)));
+               return push_inst(compiler, MFHI | D(SLJIT_TEMPORARY_REG2), DR(SLJIT_TEMPORARY_REG2));
+       case SLJIT_UDIV:
+       case SLJIT_SDIV:
+#if !(defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
+               FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+               FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif
+               FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVU : DIV) | S(SLJIT_TEMPORARY_REG1) | T(SLJIT_TEMPORARY_REG2), MOVABLE_INS));
+               FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_TEMPORARY_REG1), DR(SLJIT_TEMPORARY_REG1)));
+               return push_inst(compiler, MFHI | D(SLJIT_TEMPORARY_REG2), DR(SLJIT_TEMPORARY_REG2));
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+       #define inp_flags 0
+#endif
+
+       CHECK_ERROR();
+       check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
+
+       SLJIT_COMPILE_ASSERT(SLJIT_MOV + 7 == SLJIT_MOVU, movu_offset);
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_MOV:
+               return emit_op(compiler, SLJIT_MOV, inp_flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_MOV_UI:
+               return emit_op(compiler, SLJIT_MOV_UI, inp_flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_MOV_SI:
+               return emit_op(compiler, SLJIT_MOV_SI, inp_flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_MOV_UB:
+               return emit_op(compiler, SLJIT_MOV_UB, inp_flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw);
+
+       case SLJIT_MOV_SB:
+               return emit_op(compiler, SLJIT_MOV_SB, inp_flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw);
+
+       case SLJIT_MOV_UH:
+               return emit_op(compiler, SLJIT_MOV_UH, inp_flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw);
+
+       case SLJIT_MOV_SH:
+               return emit_op(compiler, SLJIT_MOV_SH, inp_flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw);
+
+       case SLJIT_MOVU:
+               return emit_op(compiler, SLJIT_MOV, inp_flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_MOVU_UI:
+               return emit_op(compiler, SLJIT_MOV_UI, inp_flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_MOVU_SI:
+               return emit_op(compiler, SLJIT_MOV_SI, inp_flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_MOVU_UB:
+               return emit_op(compiler, SLJIT_MOV_UB, inp_flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw);
+
+       case SLJIT_MOVU_SB:
+               return emit_op(compiler, SLJIT_MOV_SB, inp_flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw);
+
+       case SLJIT_MOVU_UH:
+               return emit_op(compiler, SLJIT_MOV_UH, inp_flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw);
+
+       case SLJIT_MOVU_SH:
+               return emit_op(compiler, SLJIT_MOV_SH, inp_flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw);
+
+       case SLJIT_NOT:
+               return emit_op(compiler, op, inp_flags, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_NEG:
+               return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), inp_flags | IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);
+
+       case SLJIT_CLZ:
+               return emit_op(compiler, op, inp_flags, dst, dstw, TMP_REG1, 0, src, srcw);
+       }
+
+       return SLJIT_SUCCESS;
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+       #undef inp_flags
+#endif
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+       #define inp_flags 0
+#endif
+
+       CHECK_ERROR();
+       check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_ADD:
+       case SLJIT_ADDC:
+               return emit_op(compiler, op, inp_flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+       case SLJIT_SUB:
+       case SLJIT_SUBC:
+               return emit_op(compiler, op, inp_flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+       case SLJIT_MUL:
+               return emit_op(compiler, op, inp_flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
+
+       case SLJIT_AND:
+       case SLJIT_OR:
+       case SLJIT_XOR:
+               return emit_op(compiler, op, inp_flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+       case SLJIT_SHL:
+       case SLJIT_LSHR:
+       case SLJIT_ASHR:
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+               if (src2 & SLJIT_IMM)
+                       src2w &= 0x1f;
+#else
+               if (src2 & SLJIT_IMM)
+                       src2w &= 0x3f;
+#endif
+               return emit_op(compiler, op, inp_flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+       }
+
+       return SLJIT_SUCCESS;
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+       #undef inp_flags
+#endif
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
+{
+       check_sljit_get_register_index(reg);
+       return reg_map[reg];
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, int size)
+{
+       CHECK_ERROR();
+       check_sljit_emit_op_custom(compiler, instruction, size);
+       SLJIT_ASSERT(size == 4);
+
+       return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);
+}
+
+/* --------------------------------------------------------------------- */
+/*  Floating point operators                                             */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
+{
+#if (defined SLJIT_QEMU && SLJIT_QEMU)
+       /* Qemu says fir is 0 by default. */
+       return 1;
+#elif defined(__GNUC__)
+       sljit_w fir;
+       asm ("cfc1 %0, $0" : "=r"(fir));
+       return (fir >> 22) & 0x1;
+#else
+#error "FIR check is not implemented for this architecture"
+#endif
+}
+
+static int emit_fpu_data_transfer(struct sljit_compiler *compiler, int fpu_reg, int load, int arg, sljit_w argw)
+{
+       int hi_reg;
+
+       SLJIT_ASSERT(arg & SLJIT_MEM);
+
+       /* Fast loads and stores. */
+       if (!(arg & 0xf0)) {
+               /* Both for (arg & 0xf) == SLJIT_UNUSED and (arg & 0xf) != SLJIT_UNUSED. */
+               if (argw <= SIMM_MAX && argw >= SIMM_MIN)
+                       return push_inst(compiler, (load ? LDC1 : SDC1) | S(arg & 0xf) | FT(fpu_reg) | IMM(argw), MOVABLE_INS);
+       }
+
+       if (arg & 0xf0) {
+               argw &= 0x3;
+               hi_reg = (arg >> 4) & 0xf;
+               if (argw) {
+                       FAIL_IF(push_inst(compiler, SLL_W | T(hi_reg) | D(TMP_REG1) | SH_IMM(argw), DR(TMP_REG1)));
+                       hi_reg = TMP_REG1;
+               }
+               FAIL_IF(push_inst(compiler, ADDU_W | S(hi_reg) | T(arg & 0xf) | D(TMP_REG1), DR(TMP_REG1)));
+               return push_inst(compiler, (load ? LDC1 : SDC1) | S(TMP_REG1) | FT(fpu_reg) | IMM(0), MOVABLE_INS);
+       }
+
+       /* Use cache. */
+       if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)
+               return push_inst(compiler, (load ? LDC1 : SDC1) | S(TMP_REG3) | FT(fpu_reg) | IMM(argw - compiler->cache_argw), MOVABLE_INS);
+
+       /* Put value to cache. */
+       compiler->cache_arg = arg;
+       compiler->cache_argw = argw;
+
+       FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));
+       if (arg & 0xf)
+               FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(arg & 0xf) | D(TMP_REG3), DR(TMP_REG3)));
+       return push_inst(compiler, (load ? LDC1 : SDC1) | S(TMP_REG3) | FT(fpu_reg) | IMM(0), MOVABLE_INS);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       int dst_fr;
+
+       CHECK_ERROR();
+       check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
+
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+
+       if (GET_OPCODE(op) == SLJIT_FCMP) {
+               if (dst > SLJIT_FLOAT_REG4) {
+                       FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, dst, dstw));
+                       dst = TMP_FREG1;
+               }
+               if (src > SLJIT_FLOAT_REG4) {
+                       FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src, srcw));
+                       src = TMP_FREG2;
+               }
+
+               /* src and dst are swapped. */
+               if (op & SLJIT_SET_E) {
+                       FAIL_IF(push_inst(compiler, C_UEQ_D | FT(src) | FS(dst), UNMOVABLE_INS));
+                       FAIL_IF(push_inst(compiler, CFC1 | TA(EQUAL_FLAG) | DA(FCSR_REG), EQUAL_FLAG));
+                       FAIL_IF(push_inst(compiler, SRL | TA(EQUAL_FLAG) | DA(EQUAL_FLAG) | SH_IMM(23), EQUAL_FLAG));
+                       FAIL_IF(push_inst(compiler, ANDI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG));
+               }
+               if (op & SLJIT_SET_S) {
+                       /* Mixing the instructions for the two checks. */
+                       FAIL_IF(push_inst(compiler, C_ULT_D | FT(src) | FS(dst), UNMOVABLE_INS));
+                       FAIL_IF(push_inst(compiler, CFC1 | TA(ULESS_FLAG) | DA(FCSR_REG), ULESS_FLAG));
+                       FAIL_IF(push_inst(compiler, C_ULT_D | FT(dst) | FS(src), UNMOVABLE_INS));
+                       FAIL_IF(push_inst(compiler, SRL | TA(ULESS_FLAG) | DA(ULESS_FLAG) | SH_IMM(23), ULESS_FLAG));
+                       FAIL_IF(push_inst(compiler, ANDI | SA(ULESS_FLAG) | TA(ULESS_FLAG) | IMM(1), ULESS_FLAG));
+                       FAIL_IF(push_inst(compiler, CFC1 | TA(UGREATER_FLAG) | DA(FCSR_REG), UGREATER_FLAG));
+                       FAIL_IF(push_inst(compiler, SRL | TA(UGREATER_FLAG) | DA(UGREATER_FLAG) | SH_IMM(23), UGREATER_FLAG));
+                       FAIL_IF(push_inst(compiler, ANDI | SA(UGREATER_FLAG) | TA(UGREATER_FLAG) | IMM(1), UGREATER_FLAG));
+               }
+               return push_inst(compiler, C_UN_D | FT(src) | FS(dst), FCSR_FCC);
+       }
+
+       dst_fr = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst;
+
+       if (src > SLJIT_FLOAT_REG4) {
+               FAIL_IF(emit_fpu_data_transfer(compiler, dst_fr, 1, src, srcw));
+               src = dst_fr;
+       }
+
+       switch (op) {
+               case SLJIT_FMOV:
+                       if (src != dst_fr && dst_fr != TMP_FREG1)
+                               FAIL_IF(push_inst(compiler, MOV_D | FS(src) | FD(dst_fr), MOVABLE_INS));
+                       break;
+               case SLJIT_FNEG:
+                       FAIL_IF(push_inst(compiler, NEG_D | FS(src) | FD(dst_fr), MOVABLE_INS));
+                       break;
+               case SLJIT_FABS:
+                       FAIL_IF(push_inst(compiler, ABS_D | FS(src) | FD(dst_fr), MOVABLE_INS));
+                       break;
+       }
+
+       if (dst_fr == TMP_FREG1)
+               FAIL_IF(emit_fpu_data_transfer(compiler, src, 0, dst, dstw));
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       int dst_fr;
+
+       CHECK_ERROR();
+       check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+
+       dst_fr = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst;
+
+       if (src2 > SLJIT_FLOAT_REG4) {
+               FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w));
+               src2 = TMP_FREG2;
+       }
+
+       if (src1 > SLJIT_FLOAT_REG4) {
+               FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w));
+               src1 = TMP_FREG1;
+       }
+
+       switch (op) {
+       case SLJIT_FADD:
+               FAIL_IF(push_inst(compiler, ADD_D | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
+               break;
+
+       case SLJIT_FSUB:
+               FAIL_IF(push_inst(compiler, SUB_D | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
+               break;
+
+       case SLJIT_FMUL:
+               FAIL_IF(push_inst(compiler, MUL_D | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
+               break;
+
+       case SLJIT_FDIV:
+               FAIL_IF(push_inst(compiler, DIV_D | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS));
+               break;
+       }
+
+       if (dst_fr == TMP_FREG1)
+               FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 0, dst, dstw));
+
+       return SLJIT_SUCCESS;
+}
+
+/* --------------------------------------------------------------------- */
+/*  Other instructions                                                   */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
+{
+       CHECK_ERROR();
+       check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+
+       compiler->has_locals = local_size > 0;
+       local_size += (saveds + 2 + 4) * sizeof(sljit_w);
+       compiler->local_size = (local_size + 15) & ~0xf;
+
+       if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
+               return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), DR(dst));
+       else if (dst & SLJIT_MEM)
+               return emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw);
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+{
+       CHECK_ERROR();
+       check_sljit_emit_fast_return(compiler, src, srcw);
+
+       if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
+               FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
+       else if (src & SLJIT_MEM)
+               FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
+       else if (src & SLJIT_IMM)
+               FAIL_IF(load_immediate(compiler, RETURN_ADDR_REG, srcw));
+
+       FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
+       return push_inst(compiler, NOP, UNMOVABLE_INS);
+}
+
+/* --------------------------------------------------------------------- */
+/*  Conditional instructions                                             */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+       struct sljit_label *label;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_label(compiler);
+
+       if (compiler->last_label && compiler->last_label->size == compiler->size)
+               return compiler->last_label;
+
+       label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+       PTR_FAIL_IF(!label);
+       set_label(label, compiler);
+       compiler->delay_slot = UNMOVABLE_INS;
+       return label;
+}
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#define JUMP_LENGTH    4
+#else
+#define JUMP_LENGTH    7
+#endif
+
+#define BR_Z(src) \
+       inst = BEQ | SA(src) | TA(0) | JUMP_LENGTH; \
+       flags = IS_BIT26_COND; \
+       delay_check = src;
+
+#define BR_NZ(src) \
+       inst = BNE | SA(src) | TA(0) | JUMP_LENGTH; \
+       flags = IS_BIT26_COND; \
+       delay_check = src;
+
+#define BR_T() \
+       inst = BC1T | JUMP_LENGTH; \
+       flags = IS_BIT16_COND; \
+       delay_check = FCSR_FCC;
+
+#define BR_F() \
+       inst = BC1F | JUMP_LENGTH; \
+       flags = IS_BIT16_COND; \
+       delay_check = FCSR_FCC;
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type)
+{
+       struct sljit_jump *jump;
+       sljit_ins inst;
+       int flags = 0;
+       int delay_check = UNMOVABLE_INS;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_jump(compiler, type);
+
+       jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+       PTR_FAIL_IF(!jump);
+       set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+       type &= 0xff;
+
+       switch (type) {
+       case SLJIT_C_EQUAL:
+       case SLJIT_C_FLOAT_NOT_EQUAL:
+               BR_NZ(EQUAL_FLAG);
+               break;
+       case SLJIT_C_NOT_EQUAL:
+       case SLJIT_C_FLOAT_EQUAL:
+               BR_Z(EQUAL_FLAG);
+               break;
+       case SLJIT_C_LESS:
+       case SLJIT_C_FLOAT_LESS:
+               BR_Z(ULESS_FLAG);
+               break;
+       case SLJIT_C_GREATER_EQUAL:
+       case SLJIT_C_FLOAT_GREATER_EQUAL:
+               BR_NZ(ULESS_FLAG);
+               break;
+       case SLJIT_C_GREATER:
+       case SLJIT_C_FLOAT_GREATER:
+               BR_Z(UGREATER_FLAG);
+               break;
+       case SLJIT_C_LESS_EQUAL:
+       case SLJIT_C_FLOAT_LESS_EQUAL:
+               BR_NZ(UGREATER_FLAG);
+               break;
+       case SLJIT_C_SIG_LESS:
+               BR_Z(LESS_FLAG);
+               break;
+       case SLJIT_C_SIG_GREATER_EQUAL:
+               BR_NZ(LESS_FLAG);
+               break;
+       case SLJIT_C_SIG_GREATER:
+               BR_Z(GREATER_FLAG);
+               break;
+       case SLJIT_C_SIG_LESS_EQUAL:
+               BR_NZ(GREATER_FLAG);
+               break;
+       case SLJIT_C_OVERFLOW:
+       case SLJIT_C_MUL_OVERFLOW:
+               BR_Z(OVERFLOW_FLAG);
+               break;
+       case SLJIT_C_NOT_OVERFLOW:
+       case SLJIT_C_MUL_NOT_OVERFLOW:
+               BR_NZ(OVERFLOW_FLAG);
+               break;
+       case SLJIT_C_FLOAT_NAN:
+               BR_F();
+               break;
+       case SLJIT_C_FLOAT_NOT_NAN:
+               BR_T();
+               break;
+       default:
+               /* Not conditional branch. */
+               inst = 0;
+               break;
+       }
+
+       jump->flags |= flags;
+       if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != delay_check))
+               jump->flags |= IS_MOVABLE;
+
+       if (inst)
+               PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS));
+
+       PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
+       if (type <= SLJIT_JUMP) {
+               PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
+               jump->addr = compiler->size;
+               PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+       } else {
+               SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
+               /* Cannot be optimized out if type is >= CALL0. */
+               jump->flags |= IS_JAL | (type >= SLJIT_CALL0 ? SLJIT_REWRITABLE_JUMP : 0);
+               PTR_FAIL_IF(push_inst(compiler, JALR | S(TMP_REG2) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+               jump->addr = compiler->size;
+               /* A NOP if type < CALL1. */
+               PTR_FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_TEMPORARY_REG1) | TA(0) | DA(4), UNMOVABLE_INS));
+       }
+       return jump;
+}
+
+#define RESOLVE_IMM1() \
+       if (src1 & SLJIT_IMM) { \
+               if (src1w) { \
+                       PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \
+                       src1 = TMP_REG1; \
+               } \
+               else \
+                       src1 = 0; \
+       }
+
+#define RESOLVE_IMM2() \
+       if (src2 & SLJIT_IMM) { \
+               if (src2w) { \
+                       PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG2), src2w)); \
+                       src2 = TMP_REG2; \
+               } \
+               else \
+                       src2 = 0; \
+       }
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, int type,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       struct sljit_jump *jump;
+       int flags;
+       sljit_ins inst;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w);
+
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+       flags = ((type & SLJIT_INT_OP) ? INT_DATA : WORD_DATA) | LOAD_DATA;
+       if (src1 & SLJIT_MEM) {
+               if (getput_arg_fast(compiler, flags, DR(TMP_REG1), src1, src1w))
+                       PTR_FAIL_IF(compiler->error);
+               else
+                       PTR_FAIL_IF(getput_arg(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));
+               src1 = TMP_REG1;
+       }
+       if (src2 & SLJIT_MEM) {
+               if (getput_arg_fast(compiler, flags, DR(TMP_REG2), src2, src2w))
+                       PTR_FAIL_IF(compiler->error);
+               else
+                       PTR_FAIL_IF(getput_arg(compiler, flags, DR(TMP_REG2), src2, src2w, 0, 0));
+               src2 = TMP_REG2;
+       }
+
+       jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+       PTR_FAIL_IF(!jump);
+       set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+       type &= 0xff;
+
+       if (type <= SLJIT_C_NOT_EQUAL) {
+               RESOLVE_IMM1();
+               RESOLVE_IMM2();
+               jump->flags |= IS_BIT26_COND;
+               if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2)))
+                       jump->flags |= IS_MOVABLE;
+               PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_C_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | JUMP_LENGTH, UNMOVABLE_INS));
+       }
+       else if (type >= SLJIT_C_SIG_LESS && (((src1 & SLJIT_IMM) && (src1w == 0)) || ((src2 & SLJIT_IMM) && (src2w == 0)))) {
+               inst = NOP;
+               if ((src1 & SLJIT_IMM) && (src1w == 0)) {
+                       RESOLVE_IMM2();
+                       switch (type) {
+                       case SLJIT_C_SIG_LESS:
+                               inst = BLEZ;
+                               jump->flags |= IS_BIT26_COND;
+                               break;
+                       case SLJIT_C_SIG_GREATER_EQUAL:
+                               inst = BGTZ;
+                               jump->flags |= IS_BIT26_COND;
+                               break;
+                       case SLJIT_C_SIG_GREATER:
+                               inst = BGEZ;
+                               jump->flags |= IS_BIT16_COND;
+                               break;
+                       case SLJIT_C_SIG_LESS_EQUAL:
+                               inst = BLTZ;
+                               jump->flags |= IS_BIT16_COND;
+                               break;
+                       }
+                       src1 = src2;
+               }
+               else {
+                       RESOLVE_IMM1();
+                       switch (type) {
+                       case SLJIT_C_SIG_LESS:
+                               inst = BGEZ;
+                               jump->flags |= IS_BIT16_COND;
+                               break;
+                       case SLJIT_C_SIG_GREATER_EQUAL:
+                               inst = BLTZ;
+                               jump->flags |= IS_BIT16_COND;
+                               break;
+                       case SLJIT_C_SIG_GREATER:
+                               inst = BLEZ;
+                               jump->flags |= IS_BIT26_COND;
+                               break;
+                       case SLJIT_C_SIG_LESS_EQUAL:
+                               inst = BGTZ;
+                               jump->flags |= IS_BIT26_COND;
+                               break;
+                       }
+               }
+               PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | JUMP_LENGTH, UNMOVABLE_INS));
+       }
+       else {
+               if (type == SLJIT_C_LESS || type == SLJIT_C_GREATER_EQUAL || type == SLJIT_C_SIG_LESS || type == SLJIT_C_SIG_GREATER_EQUAL) {
+                       RESOLVE_IMM1();
+                       if ((src2 & SLJIT_IMM) && src2w <= SIMM_MAX && src2w >= SIMM_MIN)
+                               PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_C_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1)));
+                       else {
+                               RESOLVE_IMM2();
+                               PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_C_LESS_EQUAL ? SLTU : SLT) | S(src1) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));
+                       }
+                       type = (type == SLJIT_C_LESS || type == SLJIT_C_SIG_LESS) ? SLJIT_C_NOT_EQUAL : SLJIT_C_EQUAL;
+               }
+               else {
+                       RESOLVE_IMM2();
+                       if ((src1 & SLJIT_IMM) && src1w <= SIMM_MAX && src1w >= SIMM_MIN)
+                               PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_C_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1)));
+                       else {
+                               RESOLVE_IMM1();
+                               PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_C_LESS_EQUAL ? SLTU : SLT) | S(src2) | T(src1) | D(TMP_REG1), DR(TMP_REG1)));
+                       }
+                       type = (type == SLJIT_C_GREATER || type == SLJIT_C_SIG_GREATER) ? SLJIT_C_NOT_EQUAL : SLJIT_C_EQUAL;
+               }
+
+               jump->flags |= IS_BIT26_COND;
+               PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_C_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | JUMP_LENGTH, UNMOVABLE_INS));
+       }
+
+       PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
+       PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
+       jump->addr = compiler->size;
+       PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+       return jump;
+}
+
+#undef RESOLVE_IMM1
+#undef RESOLVE_IMM2
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       struct sljit_jump *jump;
+       sljit_ins inst;
+       int if_true;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w);
+
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+
+       if (src1 > SLJIT_FLOAT_REG4) {
+               PTR_FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w));
+               src1 = TMP_FREG1;
+       }
+       if (src2 > SLJIT_FLOAT_REG4) {
+               PTR_FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w));
+               src2 = TMP_FREG2;
+       }
+
+       jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+       PTR_FAIL_IF(!jump);
+       set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+       jump->flags |= IS_BIT16_COND;
+       type &= 0xff;
+
+       switch (type) {
+       case SLJIT_C_FLOAT_EQUAL:
+               inst = C_UEQ_D;
+               if_true = 1;
+               break;
+       case SLJIT_C_FLOAT_NOT_EQUAL:
+               inst = C_UEQ_D;
+               if_true = 0;
+               break;
+       case SLJIT_C_FLOAT_LESS:
+               inst = C_ULT_D;
+               if_true = 1;
+               break;
+       case SLJIT_C_FLOAT_GREATER_EQUAL:
+               inst = C_ULT_D;
+               if_true = 0;
+               break;
+       case SLJIT_C_FLOAT_GREATER:
+               inst = C_ULE_D;
+               if_true = 0;
+               break;
+       case SLJIT_C_FLOAT_LESS_EQUAL:
+               inst = C_ULE_D;
+               if_true = 1;
+               break;
+       case SLJIT_C_FLOAT_NAN:
+               inst = C_UN_D;
+               if_true = 1;
+               break;
+       case SLJIT_C_FLOAT_NOT_NAN:
+       default: /* Make compilers happy. */
+               inst = C_UN_D;
+               if_true = 0;
+               break;
+       }
+
+       PTR_FAIL_IF(push_inst(compiler, inst | FT(src2) | FS(src1), UNMOVABLE_INS));
+       /* Intentionally the other opcode. */
+       PTR_FAIL_IF(push_inst(compiler, (if_true ? BC1F : BC1T) | JUMP_LENGTH, UNMOVABLE_INS));
+       PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
+       PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
+       jump->addr = compiler->size;
+       PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+       return jump;
+}
+
+#undef JUMP_LENGTH
+#undef BR_Z
+#undef BR_NZ
+#undef BR_T
+#undef BR_F
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
+{
+       int src_r = TMP_REG2;
+       struct sljit_jump *jump = NULL;
+
+       CHECK_ERROR();
+       check_sljit_emit_ijump(compiler, type, src, srcw);
+
+       if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) {
+               if (DR(src) != 4)
+                       src_r = src;
+               else
+                       FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
+       }
+
+       if (type >= SLJIT_CALL0) {
+               SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
+               if (src & (SLJIT_IMM | SLJIT_MEM)) {
+                       if (src & SLJIT_IMM)
+                               FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
+                       else {
+                               SLJIT_ASSERT(src_r == TMP_REG2 && (src & SLJIT_MEM));
+                               FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
+                       }
+                       FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+                       /* We need an extra instruction in any case. */
+                       return push_inst(compiler, ADDU_W | S(SLJIT_TEMPORARY_REG1) | TA(0) | DA(4), UNMOVABLE_INS);
+               }
+
+               /* Register input. */
+               if (type >= SLJIT_CALL1)
+                       FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_TEMPORARY_REG1) | TA(0) | DA(4), 4));
+               FAIL_IF(push_inst(compiler, JALR | S(src_r) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+               return push_inst(compiler, ADDU_W | S(src_r) | TA(0) | D(PIC_ADDR_REG), UNMOVABLE_INS);
+       }
+
+       if (src & SLJIT_IMM) {
+               jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+               FAIL_IF(!jump);
+               set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));
+               jump->u.target = srcw;
+
+               if (compiler->delay_slot != UNMOVABLE_INS)
+                       jump->flags |= IS_MOVABLE;
+
+               FAIL_IF(emit_const(compiler, TMP_REG2, 0));
+       }
+       else if (src & SLJIT_MEM)
+               FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
+
+       FAIL_IF(push_inst(compiler, JR | S(src_r), UNMOVABLE_INS));
+       if (jump)
+               jump->addr = compiler->size;
+       FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type)
+{
+       int sugg_dst_ar, dst_ar;
+
+       CHECK_ERROR();
+       check_sljit_emit_cond_value(compiler, op, dst, dstw, type);
+
+       if (dst == SLJIT_UNUSED)
+               return SLJIT_SUCCESS;
+
+       sugg_dst_ar = DR((op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2);
+
+       switch (type) {
+       case SLJIT_C_EQUAL:
+       case SLJIT_C_NOT_EQUAL:
+               FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar));
+               dst_ar = sugg_dst_ar;
+               break;
+       case SLJIT_C_LESS:
+       case SLJIT_C_GREATER_EQUAL:
+       case SLJIT_C_FLOAT_LESS:
+       case SLJIT_C_FLOAT_GREATER_EQUAL:
+               dst_ar = ULESS_FLAG;
+               break;
+       case SLJIT_C_GREATER:
+       case SLJIT_C_LESS_EQUAL:
+       case SLJIT_C_FLOAT_GREATER:
+       case SLJIT_C_FLOAT_LESS_EQUAL:
+               dst_ar = UGREATER_FLAG;
+               break;
+       case SLJIT_C_SIG_LESS:
+       case SLJIT_C_SIG_GREATER_EQUAL:
+               dst_ar = LESS_FLAG;
+               break;
+       case SLJIT_C_SIG_GREATER:
+       case SLJIT_C_SIG_LESS_EQUAL:
+               dst_ar = GREATER_FLAG;
+               break;
+       case SLJIT_C_OVERFLOW:
+       case SLJIT_C_NOT_OVERFLOW:
+               dst_ar = OVERFLOW_FLAG;
+               break;
+       case SLJIT_C_MUL_OVERFLOW:
+       case SLJIT_C_MUL_NOT_OVERFLOW:
+               FAIL_IF(push_inst(compiler, SLTIU | SA(OVERFLOW_FLAG) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar));
+               dst_ar = sugg_dst_ar;
+               type ^= 0x1; /* Flip type bit for the XORI below. */
+               break;
+       case SLJIT_C_FLOAT_EQUAL:
+       case SLJIT_C_FLOAT_NOT_EQUAL:
+               dst_ar = EQUAL_FLAG;
+               break;
+
+       case SLJIT_C_FLOAT_NAN:
+       case SLJIT_C_FLOAT_NOT_NAN:
+               FAIL_IF(push_inst(compiler, CFC1 | TA(sugg_dst_ar) | DA(FCSR_REG), sugg_dst_ar));
+               FAIL_IF(push_inst(compiler, SRL | TA(sugg_dst_ar) | DA(sugg_dst_ar) | SH_IMM(23), sugg_dst_ar));
+               FAIL_IF(push_inst(compiler, ANDI | SA(sugg_dst_ar) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar));
+               dst_ar = sugg_dst_ar;
+               break;
+
+       default:
+               SLJIT_ASSERT_STOP();
+               dst_ar = sugg_dst_ar;
+               break;
+       }
+
+       if (type & 0x1) {
+               FAIL_IF(push_inst(compiler, XORI | SA(dst_ar) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar));
+               dst_ar = sugg_dst_ar;
+       }
+
+       if (GET_OPCODE(op) == SLJIT_OR) {
+               if (DR(TMP_REG2) != dst_ar)
+                       FAIL_IF(push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
+               return emit_op(compiler, op, CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, dst, dstw, TMP_REG2, 0);
+       }
+
+       if (dst & SLJIT_MEM)
+               return emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw);
+
+       if (sugg_dst_ar != dst_ar)
+               return push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | DA(sugg_dst_ar), sugg_dst_ar);
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value)
+{
+       struct sljit_const *const_;
+       int reg;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_const(compiler, dst, dstw, init_value);
+
+       const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+       PTR_FAIL_IF(!const_);
+       set_const(const_, compiler);
+
+       reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2;
+
+       PTR_FAIL_IF(emit_const(compiler, reg, init_value));
+
+       if (dst & SLJIT_MEM)
+               PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
+       return const_;
+}
diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_32.c b/src/3rdparty/pcre/sljit/sljitNativePPC_32.c
new file mode 100644 (file)
index 0000000..82d0508
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+/* ppc 32-bit arch dependent functions. */
+
+static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
+{
+       if (imm <= SIMM_MAX && imm >= SIMM_MIN)
+               return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
+
+       if (!(imm & ~0xffff))
+               return push_inst(compiler, ORI | S(ZERO_REG) | A(reg) | IMM(imm));
+
+       FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
+       return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
+}
+
+#define INS_CLEAR_LEFT(dst, src, from) \
+       (RLWINM | S(src) | A(dst) | ((from) << 6) | (31 << 1))
+
+static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
+       int dst, int src1, int src2)
+{
+       switch (op) {
+       case SLJIT_ADD:
+               if (flags & ALT_FORM1) {
+                       /* Flags does not set: BIN_IMM_EXTS unnecessary. */
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
+               }
+               if (flags & ALT_FORM2) {
+                       /* Flags does not set: BIN_IMM_EXTS unnecessary. */
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
+               }
+               if (flags & ALT_FORM3) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
+               }
+               if (flags & ALT_FORM4) {
+                       /* Flags does not set: BIN_IMM_EXTS unnecessary. */
+                       FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)));
+                       return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)));
+               }
+               if (!(flags & ALT_SET_FLAGS))
+                       return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
+               return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
+
+       case SLJIT_ADDC:
+               if (flags & ALT_FORM1) {
+                       FAIL_IF(push_inst(compiler, MFXER | S(0)));
+                       FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
+                       return push_inst(compiler, MTXER | S(0));
+               }
+               return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
+
+       case SLJIT_SUB:
+               if (flags & ALT_FORM1) {
+                       /* Flags does not set: BIN_IMM_EXTS unnecessary. */
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
+               }
+               if (flags & (ALT_FORM2 | ALT_FORM3)) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       if (flags & ALT_FORM2)
+                               FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm));
+                       if (flags & ALT_FORM3)
+                               return push_inst(compiler, CMPLI | CRD(4) | A(src1) | compiler->imm);
+                       return SLJIT_SUCCESS;
+               }
+               if (flags & (ALT_FORM4 | ALT_FORM5)) {
+                       if (flags & ALT_FORM4)
+                               FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2)));
+                       if (flags & ALT_FORM5)
+                               FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)));
+                       return SLJIT_SUCCESS;
+               }
+               if (!(flags & ALT_SET_FLAGS))
+                       return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
+               if (flags & ALT_FORM6)
+                       FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2)));
+               return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+
+       case SLJIT_SUBC:
+               if (flags & ALT_FORM1) {
+                       FAIL_IF(push_inst(compiler, MFXER | S(0)));
+                       FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
+                       return push_inst(compiler, MTXER | S(0));
+               }
+               return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
+
+       case SLJIT_MUL:
+               if (flags & ALT_FORM1) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
+               }
+               return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1));
+
+       case SLJIT_AND:
+               if (flags & ALT_FORM1) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
+               }
+               if (flags & ALT_FORM2) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
+               }
+               return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
+
+       case SLJIT_OR:
+               if (flags & ALT_FORM1) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
+               }
+               if (flags & ALT_FORM2) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
+               }
+               if (flags & ALT_FORM3) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm)));
+                       return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
+               }
+               return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
+
+       case SLJIT_XOR:
+               if (flags & ALT_FORM1) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
+               }
+               if (flags & ALT_FORM2) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
+               }
+               if (flags & ALT_FORM3) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm)));
+                       return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
+               }
+               return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
+
+       case SLJIT_SHL:
+               if (flags & ALT_FORM1) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       compiler->imm &= 0x1f;
+                       return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1));
+               }
+               return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2));
+
+       case SLJIT_LSHR:
+               if (flags & ALT_FORM1) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       compiler->imm &= 0x1f;
+                       return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1));
+               }
+               return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
+
+       case SLJIT_ASHR:
+               if (flags & ALT_FORM1) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       compiler->imm &= 0x1f;
+                       return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
+               }
+               return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
+
+       case SLJIT_MOV:
+       case SLJIT_MOV_UI:
+       case SLJIT_MOV_SI:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               if (dst != src2)
+                       return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
+               return SLJIT_SUCCESS;
+
+       case SLJIT_MOV_UB:
+       case SLJIT_MOV_SB:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+                       if (op == SLJIT_MOV_SB)
+                               return push_inst(compiler, EXTSB | S(src2) | A(dst));
+                       return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
+               }
+               else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
+                       return push_inst(compiler, EXTSB | S(src2) | A(dst));
+               else if (dst != src2)
+                       SLJIT_ASSERT_STOP();
+               return SLJIT_SUCCESS;
+
+       case SLJIT_MOV_UH:
+       case SLJIT_MOV_SH:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+                       if (op == SLJIT_MOV_SH)
+                               return push_inst(compiler, EXTSH | S(src2) | A(dst));
+                       return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
+               }
+               else if (dst != src2)
+                       SLJIT_ASSERT_STOP();
+               return SLJIT_SUCCESS;
+
+       case SLJIT_NOT:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
+
+       case SLJIT_NEG:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
+
+       case SLJIT_CLZ:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
+       }
+
+       SLJIT_ASSERT_STOP();
+       return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value)
+{
+       FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));
+       return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+{
+       sljit_ins *inst = (sljit_ins*)addr;
+
+       inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
+       inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff);
+       SLJIT_CACHE_FLUSH(inst, inst + 2);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
+{
+       sljit_ins *inst = (sljit_ins*)addr;
+
+       inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
+       inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
+       SLJIT_CACHE_FLUSH(inst, inst + 2);
+}
diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_64.c b/src/3rdparty/pcre/sljit/sljitNativePPC_64.c
new file mode 100644 (file)
index 0000000..cc2ae37
--- /dev/null
@@ -0,0 +1,428 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+/* ppc 64-bit arch dependent functions. */
+
+#ifdef __GNUC__
+#define ASM_SLJIT_CLZ(src, dst) \
+       asm volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )
+#else
+#error "Must implement count leading zeroes"
+#endif
+
+#define RLDI(dst, src, sh, mb, type) \
+       (HI(30) | S(src) | A(dst) | ((type) << 2) | (((sh) & 0x1f) << 11) | (((sh) & 0x20) >> 4) | (((mb) & 0x1f) << 6) | ((mb) & 0x20))
+
+#define PUSH_RLDICR(reg, shift) \
+       push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1))
+
+static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
+{
+       sljit_uw tmp;
+       sljit_uw shift;
+       sljit_uw tmp2;
+       sljit_uw shift2;
+
+       if (imm <= SIMM_MAX && imm >= SIMM_MIN)
+               return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
+
+       if (!(imm & ~0xffff))
+               return push_inst(compiler, ORI | S(ZERO_REG) | A(reg) | IMM(imm));
+
+       if (imm <= SLJIT_W(0x7fffffff) && imm >= SLJIT_W(-0x80000000)) {
+               FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
+               return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
+       }
+
+       /* Count leading zeroes. */
+       tmp = (imm >= 0) ? imm : ~imm;
+       ASM_SLJIT_CLZ(tmp, shift);
+       SLJIT_ASSERT(shift > 0);
+       shift--;
+       tmp = (imm << shift);
+
+       if ((tmp & ~0xffff000000000000ul) == 0) {
+               FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
+               shift += 15;
+               return PUSH_RLDICR(reg, shift);
+       }
+
+       if ((tmp & ~0xffffffff00000000ul) == 0) {
+               FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(tmp >> 48)));
+               FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32)));
+               shift += 31;
+               return PUSH_RLDICR(reg, shift);
+       }
+
+       /* Cut out the 16 bit from immediate. */
+       shift += 15;
+       tmp2 = imm & ((1ul << (63 - shift)) - 1);
+
+       if (tmp2 <= 0xffff) {
+               FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
+               FAIL_IF(PUSH_RLDICR(reg, shift));
+               return push_inst(compiler, ORI | S(reg) | A(reg) | tmp2);
+       }
+
+       if (tmp2 <= 0xffffffff) {
+               FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
+               FAIL_IF(PUSH_RLDICR(reg, shift));
+               FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (tmp2 >> 16)));
+               return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS;
+       }
+
+       ASM_SLJIT_CLZ(tmp2, shift2);
+       tmp2 <<= shift2;
+
+       if ((tmp2 & ~0xffff000000000000ul) == 0) {
+               FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
+               shift2 += 15;
+               shift += (63 - shift2);
+               FAIL_IF(PUSH_RLDICR(reg, shift));
+               FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (tmp2 >> 48)));
+               return PUSH_RLDICR(reg, shift2);
+       }
+
+       /* The general version. */
+       FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 48)));
+       FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32)));
+       FAIL_IF(PUSH_RLDICR(reg, 31));
+       FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16)));
+       return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm));
+}
+
+/* Simplified mnemonics: clrldi. */
+#define INS_CLEAR_LEFT(dst, src, from) \
+       (RLDICL | S(src) | A(dst) | ((from) << 6) | (1 << 5))
+
+/* Sign extension for integer operations. */
+#define UN_EXTS() \
+       if ((flags & (ALT_SIGN_EXT | REG2_SOURCE)) == (ALT_SIGN_EXT | REG2_SOURCE)) { \
+               FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
+               src2 = TMP_REG2; \
+       }
+
+#define BIN_EXTS() \
+       if (flags & ALT_SIGN_EXT) { \
+               if (flags & REG1_SOURCE) { \
+                       FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
+                       src1 = TMP_REG1; \
+               } \
+               if (flags & REG2_SOURCE) { \
+                       FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
+                       src2 = TMP_REG2; \
+               } \
+       }
+
+#define BIN_IMM_EXTS() \
+       if ((flags & (ALT_SIGN_EXT | REG1_SOURCE)) == (ALT_SIGN_EXT | REG1_SOURCE)) { \
+               FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
+               src1 = TMP_REG1; \
+       }
+
+static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
+       int dst, int src1, int src2)
+{
+       switch (op) {
+       case SLJIT_ADD:
+               if (flags & ALT_FORM1) {
+                       /* Flags does not set: BIN_IMM_EXTS unnecessary. */
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
+               }
+               if (flags & ALT_FORM2) {
+                       /* Flags does not set: BIN_IMM_EXTS unnecessary. */
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
+               }
+               if (flags & ALT_FORM3) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       BIN_IMM_EXTS();
+                       return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
+               }
+               if (flags & ALT_FORM4) {
+                       /* Flags does not set: BIN_IMM_EXTS unnecessary. */
+                       FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)));
+                       return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)));
+               }
+               if (!(flags & ALT_SET_FLAGS))
+                       return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
+               BIN_EXTS();
+               return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
+
+       case SLJIT_ADDC:
+               if (flags & ALT_FORM1) {
+                       FAIL_IF(push_inst(compiler, MFXER | S(0)));
+                       FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
+                       return push_inst(compiler, MTXER | S(0));
+               }
+               BIN_EXTS();
+               return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
+
+       case SLJIT_SUB:
+               if (flags & ALT_FORM1) {
+                       /* Flags does not set: BIN_IMM_EXTS unnecessary. */
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
+               }
+               if (flags & (ALT_FORM2 | ALT_FORM3)) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       if (flags & ALT_FORM2)
+                               FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
+                       if (flags & ALT_FORM3)
+                               return push_inst(compiler, CMPLI | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
+                       return SLJIT_SUCCESS;
+               }
+               if (flags & (ALT_FORM4 | ALT_FORM5)) {
+                       if (flags & ALT_FORM4)
+                               FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
+                       if (flags & ALT_FORM5)
+                               return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2));
+                       return SLJIT_SUCCESS;
+               }
+               if (!(flags & ALT_SET_FLAGS))
+                       return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
+               BIN_EXTS();
+               if (flags & ALT_FORM6)
+                       FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
+               return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+
+       case SLJIT_SUBC:
+               if (flags & ALT_FORM1) {
+                       FAIL_IF(push_inst(compiler, MFXER | S(0)));
+                       FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
+                       return push_inst(compiler, MTXER | S(0));
+               }
+               BIN_EXTS();
+               return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
+
+       case SLJIT_MUL:
+               if (flags & ALT_FORM1) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
+               }
+               BIN_EXTS();
+               if (flags & ALT_FORM2)
+                       return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1));
+               return push_inst(compiler, MULLD | OERC(flags) | D(dst) | A(src2) | B(src1));
+
+       case SLJIT_AND:
+               if (flags & ALT_FORM1) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
+               }
+               if (flags & ALT_FORM2) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
+               }
+               return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
+
+       case SLJIT_OR:
+               if (flags & ALT_FORM1) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
+               }
+               if (flags & ALT_FORM2) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
+               }
+               if (flags & ALT_FORM3) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm)));
+                       return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
+               }
+               return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
+
+       case SLJIT_XOR:
+               if (flags & ALT_FORM1) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
+               }
+               if (flags & ALT_FORM2) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
+               }
+               if (flags & ALT_FORM3) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm)));
+                       return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
+               }
+               return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
+
+       case SLJIT_SHL:
+               if (flags & ALT_FORM1) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       if (flags & ALT_FORM2) {
+                               compiler->imm &= 0x1f;
+                               return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1));
+                       }
+                       else {
+                               compiler->imm &= 0x3f;
+                               return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags));
+                       }
+               }
+               if (flags & ALT_FORM2)
+                       return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2));
+               return push_inst(compiler, SLD | RC(flags) | S(src1) | A(dst) | B(src2));
+
+       case SLJIT_LSHR:
+               if (flags & ALT_FORM1) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       if (flags & ALT_FORM2) {
+                               compiler->imm &= 0x1f;
+                               return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1));
+                       }
+                       else {
+                               compiler->imm &= 0x3f;
+                               return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags));
+                       }
+               }
+               if (flags & ALT_FORM2)
+                       return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
+               return push_inst(compiler, SRD | RC(flags) | S(src1) | A(dst) | B(src2));
+
+       case SLJIT_ASHR:
+               if (flags & ALT_FORM1) {
+                       SLJIT_ASSERT(src2 == TMP_REG2);
+                       if (flags & ALT_FORM2) {
+                               compiler->imm &= 0x1f;
+                               return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
+                       }
+                       else {
+                               compiler->imm &= 0x3f;
+                               return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4));
+                       }
+               }
+               if (flags & ALT_FORM2)
+                       return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
+               return push_inst(compiler, SRAD | RC(flags) | S(src1) | A(dst) | B(src2));
+
+       case SLJIT_MOV:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               if (dst != src2)
+                       return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
+               return SLJIT_SUCCESS;
+
+       case SLJIT_MOV_UI:
+       case SLJIT_MOV_SI:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+                       if (op == SLJIT_MOV_SI)
+                               return push_inst(compiler, EXTSW | S(src2) | A(dst));
+                       return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0));
+               }
+               else if (dst != src2)
+                       SLJIT_ASSERT_STOP();
+               return SLJIT_SUCCESS;
+
+       case SLJIT_MOV_UB:
+       case SLJIT_MOV_SB:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+                       if (op == SLJIT_MOV_SB)
+                               return push_inst(compiler, EXTSB | S(src2) | A(dst));
+                       return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
+               }
+               else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
+                       return push_inst(compiler, EXTSB | S(src2) | A(dst));
+               else if (dst != src2)
+                       SLJIT_ASSERT_STOP();
+               return SLJIT_SUCCESS;
+
+       case SLJIT_MOV_UH:
+       case SLJIT_MOV_SH:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+                       if (op == SLJIT_MOV_SH)
+                               return push_inst(compiler, EXTSH | S(src2) | A(dst));
+                       return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
+               }
+               else if (dst != src2)
+                       SLJIT_ASSERT_STOP();
+               return SLJIT_SUCCESS;
+
+       case SLJIT_NOT:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               UN_EXTS();
+               return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
+
+       case SLJIT_NEG:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               UN_EXTS();
+               return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
+
+       case SLJIT_CLZ:
+               SLJIT_ASSERT(src1 == TMP_REG1);
+               if (flags & ALT_FORM1)
+                       return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
+               return push_inst(compiler, CNTLZD | RC(flags) | S(src2) | A(dst));
+       }
+
+       SLJIT_ASSERT_STOP();
+       return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value)
+{
+       FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));
+       FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32)));
+       FAIL_IF(PUSH_RLDICR(reg, 31));
+       FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(init_value >> 16)));
+       return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+{
+       sljit_ins *inst = (sljit_ins*)addr;
+
+       inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 48) & 0xffff);
+       inst[1] = (inst[1] & 0xffff0000) | ((new_addr >> 32) & 0xffff);
+       inst[3] = (inst[3] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
+       inst[4] = (inst[4] & 0xffff0000) | (new_addr & 0xffff);
+       SLJIT_CACHE_FLUSH(inst, inst + 5);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
+{
+       sljit_ins *inst = (sljit_ins*)addr;
+
+       inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff);
+       inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
+       inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
+       inst[4] = (inst[4] & 0xffff0000) | (new_constant & 0xffff);
+       SLJIT_CACHE_FLUSH(inst, inst + 5);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_w addr, void* func)
+{
+       sljit_w* ptrs;
+       if (func_ptr)
+               *func_ptr = (void*)context;
+       ptrs = (sljit_w*)func;
+       context->addr = addr ? addr : ptrs[0];
+       context->r2 = ptrs[1];
+       context->r11 = ptrs[2];
+}
diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_common.c b/src/3rdparty/pcre/sljit/sljitNativePPC_common.c
new file mode 100644 (file)
index 0000000..f0f191d
--- /dev/null
@@ -0,0 +1,1872 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
+{
+       return "PowerPC" SLJIT_CPUINFO;
+}
+
+/* Length of an instruction word.
+   Both for ppc-32 and ppc-64. */
+typedef sljit_ui sljit_ins;
+
+static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
+{
+       while (from < to) {
+#ifdef __GNUC__
+               asm volatile ( "icbi 0, %0" : : "r"(from) );
+#else
+#error "Must implement icbi"
+#endif
+               from++;
+       }
+}
+
+#define TMP_REG1       (SLJIT_NO_REGISTERS + 1)
+#define TMP_REG2       (SLJIT_NO_REGISTERS + 2)
+#define TMP_REG3       (SLJIT_NO_REGISTERS + 3)
+#define ZERO_REG       (SLJIT_NO_REGISTERS + 4)
+#define REAL_STACK_PTR (SLJIT_NO_REGISTERS + 5)
+
+#define TMP_FREG1      (SLJIT_FLOAT_REG4 + 1)
+#define TMP_FREG2      (SLJIT_FLOAT_REG4 + 2)
+
+/* --------------------------------------------------------------------- */
+/*  Instrucion forms                                                     */
+/* --------------------------------------------------------------------- */
+#define D(d)           (reg_map[d] << 21)
+#define S(s)           (reg_map[s] << 21)
+#define A(a)           (reg_map[a] << 16)
+#define B(b)           (reg_map[b] << 11)
+#define C(c)           (reg_map[c] << 6)
+#define FD(fd)         ((fd) << 21)
+#define FA(fa)         ((fa) << 16)
+#define FB(fb)         ((fb) << 11)
+#define FC(fc)         ((fc) << 6)
+#define IMM(imm)       ((imm) & 0xffff)
+#define CRD(d)         ((d) << 21)
+
+/* Instruction bit sections.
+   OE and Rc flag (see ALT_SET_FLAGS). */
+#define OERC(flags)    (((flags & ALT_SET_FLAGS) >> 10) | (flags & ALT_SET_FLAGS))
+/* Rc flag (see ALT_SET_FLAGS). */
+#define RC(flags)      ((flags & ALT_SET_FLAGS) >> 10)
+#define HI(opcode)     ((opcode) << 26)
+#define LO(opcode)     ((opcode) << 1)
+
+#define ADD            (HI(31) | LO(266))
+#define ADDC           (HI(31) | LO(10))
+#define ADDE           (HI(31) | LO(138))
+#define ADDI           (HI(14))
+#define ADDIC          (HI(13))
+#define ADDIS          (HI(15))
+#define ADDME          (HI(31) | LO(234))
+#define AND            (HI(31) | LO(28))
+#define ANDI           (HI(28))
+#define ANDIS          (HI(29))
+#define Bx             (HI(18))
+#define BCx            (HI(16))
+#define BCCTR          (HI(19) | LO(528) | (3 << 11))
+#define BLR            (HI(19) | LO(16) | (0x14 << 21))
+#define CNTLZD         (HI(31) | LO(58))
+#define CNTLZW         (HI(31) | LO(26))
+#define CMP            (HI(31) | LO(0))
+#define CMPI           (HI(11))
+#define CMPL           (HI(31) | LO(32))
+#define CMPLI          (HI(10))
+#define CROR           (HI(19) | LO(449))
+#define DIVD           (HI(31) | LO(489))
+#define DIVDU          (HI(31) | LO(457))
+#define DIVW           (HI(31) | LO(491))
+#define DIVWU          (HI(31) | LO(459))
+#define EXTSB          (HI(31) | LO(954))
+#define EXTSH          (HI(31) | LO(922))
+#define EXTSW          (HI(31) | LO(986))
+#define FABS           (HI(63) | LO(264))
+#define FADD           (HI(63) | LO(21))
+#define FCMPU          (HI(63) | LO(0))
+#define FDIV           (HI(63) | LO(18))
+#define FMR            (HI(63) | LO(72))
+#define FMUL           (HI(63) | LO(25))
+#define FNEG           (HI(63) | LO(40))
+#define FSUB           (HI(63) | LO(20))
+#define LD             (HI(58) | 0)
+#define LFD            (HI(50))
+#define LFDUX          (HI(31) | LO(631))
+#define LFDX           (HI(31) | LO(599))
+#define LWZ            (HI(32))
+#define MFCR           (HI(31) | LO(19))
+#define MFLR           (HI(31) | LO(339) | 0x80000)
+#define MFXER          (HI(31) | LO(339) | 0x10000)
+#define MTCTR          (HI(31) | LO(467) | 0x90000)
+#define MTLR           (HI(31) | LO(467) | 0x80000)
+#define MTXER          (HI(31) | LO(467) | 0x10000)
+#define MULHD          (HI(31) | LO(73))
+#define MULHDU         (HI(31) | LO(9))
+#define MULHW          (HI(31) | LO(75))
+#define MULHWU         (HI(31) | LO(11))
+#define MULLD          (HI(31) | LO(233))
+#define MULLI          (HI(7))
+#define MULLW          (HI(31) | LO(235))
+#define NEG            (HI(31) | LO(104))
+#define NOP            (HI(24))
+#define NOR            (HI(31) | LO(124))
+#define OR             (HI(31) | LO(444))
+#define ORI            (HI(24))
+#define ORIS           (HI(25))
+#define RLDICL         (HI(30))
+#define RLWINM         (HI(21))
+#define SLD            (HI(31) | LO(27))
+#define SLW            (HI(31) | LO(24))
+#define SRAD           (HI(31) | LO(794))
+#define SRADI          (HI(31) | LO(413 << 1))
+#define SRAW           (HI(31) | LO(792))
+#define SRAWI          (HI(31) | LO(824))
+#define SRD            (HI(31) | LO(539))
+#define SRW            (HI(31) | LO(536))
+#define STD            (HI(62) | 0)
+#define STDU           (HI(62) | 1)
+#define STDUX          (HI(31) | LO(181))
+#define STFD           (HI(54))
+#define STFDUX         (HI(31) | LO(759))
+#define STFDX          (HI(31) | LO(727))
+#define STW            (HI(36))
+#define STWU           (HI(37))
+#define STWUX          (HI(31) | LO(183))
+#define SUBF           (HI(31) | LO(40))
+#define SUBFC          (HI(31) | LO(8))
+#define SUBFE          (HI(31) | LO(136))
+#define SUBFIC         (HI(8))
+#define XOR            (HI(31) | LO(316))
+#define XORI           (HI(26))
+#define XORIS          (HI(27))
+
+#define SIMM_MAX       (0x7fff)
+#define SIMM_MIN       (-0x8000)
+#define UIMM_MAX       (0xffff)
+
+/* SLJIT_LOCALS_REG is not the real stack register, since it must
+   point to the head of the stack chain. */
+static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 6] = {
+  0, 3, 4, 5, 6, 7, 29, 28, 27, 26, 25, 31, 8, 9, 10, 30, 1
+};
+
+static int push_inst(struct sljit_compiler *compiler, sljit_ins ins)
+{
+       sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+       FAIL_IF(!ptr);
+       *ptr = ins;
+       compiler->size++;
+       return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE int optimize_jump(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
+{
+       sljit_w diff;
+       sljit_uw target_addr;
+
+       if (jump->flags & SLJIT_REWRITABLE_JUMP)
+               return 0;
+
+       if (jump->flags & JUMP_ADDR)
+               target_addr = jump->u.target;
+       else {
+               SLJIT_ASSERT(jump->flags & JUMP_LABEL);
+               target_addr = (sljit_uw)(code + jump->u.label->size);
+       }
+       diff = ((sljit_w)target_addr - (sljit_w)(code_ptr)) & ~0x3l;
+
+       if (jump->flags & UNCOND_B) {
+               if (diff <= 0x01ffffff && diff >= -0x02000000) {
+                       jump->flags |= PATCH_B;
+                       return 1;
+               }
+               if (target_addr <= 0x03ffffff) {
+                       jump->flags |= PATCH_B | ABSOLUTE_B;
+                       return 1;
+               }
+       }
+       else {
+               if (diff <= 0x7fff && diff >= -0x8000) {
+                       jump->flags |= PATCH_B;
+                       return 1;
+               }
+               if (target_addr <= 0xffff) {
+                       jump->flags |= PATCH_B | ABSOLUTE_B;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
+{
+       struct sljit_memory_fragment *buf;
+       sljit_ins *code;
+       sljit_ins *code_ptr;
+       sljit_ins *buf_ptr;
+       sljit_ins *buf_end;
+       sljit_uw word_count;
+       sljit_uw addr;
+
+       struct sljit_label *label;
+       struct sljit_jump *jump;
+       struct sljit_const *const_;
+
+       CHECK_ERROR_PTR();
+       check_sljit_generate_code(compiler);
+       reverse_buf(compiler);
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+       compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
+#endif
+       code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins));
+       PTR_FAIL_WITH_EXEC_IF(code);
+       buf = compiler->buf;
+
+       code_ptr = code;
+       word_count = 0;
+       label = compiler->labels;
+       jump = compiler->jumps;
+       const_ = compiler->consts;
+       do {
+               buf_ptr = (sljit_ins*)buf->memory;
+               buf_end = buf_ptr + (buf->used_size >> 2);
+               do {
+                       *code_ptr = *buf_ptr++;
+                       SLJIT_ASSERT(!label || label->size >= word_count);
+                       SLJIT_ASSERT(!jump || jump->addr >= word_count);
+                       SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+                       /* These structures are ordered by their address. */
+                       if (label && label->size == word_count) {
+                               /* Just recording the address. */
+                               label->addr = (sljit_uw)code_ptr;
+                               label->size = code_ptr - code;
+                               label = label->next;
+                       }
+                       if (jump && jump->addr == word_count) {
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+                               jump->addr = (sljit_uw)(code_ptr - 3);
+#else
+                               jump->addr = (sljit_uw)(code_ptr - 6);
+#endif
+                               if (optimize_jump(jump, code_ptr, code)) {
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+                                       code_ptr[-3] = code_ptr[0];
+                                       code_ptr -= 3;
+#else
+                                       code_ptr[-6] = code_ptr[0];
+                                       code_ptr -= 6;
+#endif
+                               }
+                               jump = jump->next;
+                       }
+                       if (const_ && const_->addr == word_count) {
+                               /* Just recording the address. */
+                               const_->addr = (sljit_uw)code_ptr;
+                               const_ = const_->next;
+                       }
+                       code_ptr ++;
+                       word_count ++;
+               } while (buf_ptr < buf_end);
+
+               buf = buf->next;
+       } while (buf);
+
+       if (label && label->size == word_count) {
+               label->addr = (sljit_uw)code_ptr;
+               label->size = code_ptr - code;
+               label = label->next;
+       }
+
+       SLJIT_ASSERT(!label);
+       SLJIT_ASSERT(!jump);
+       SLJIT_ASSERT(!const_);
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+       SLJIT_ASSERT(code_ptr - code <= (int)compiler->size - ((compiler->size & 0x1) ? 3 : 2));
+#else
+       SLJIT_ASSERT(code_ptr - code <= (int)compiler->size);
+#endif
+
+       jump = compiler->jumps;
+       while (jump) {
+               do {
+                       addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
+                       buf_ptr = (sljit_ins*)jump->addr;
+                       if (jump->flags & PATCH_B) {
+                               if (jump->flags & UNCOND_B) {
+                                       if (!(jump->flags & ABSOLUTE_B)) {
+                                               addr = addr - jump->addr;
+                                               SLJIT_ASSERT((sljit_w)addr <= 0x01ffffff && (sljit_w)addr >= -0x02000000);
+                                               *buf_ptr = Bx | (addr & 0x03fffffc) | ((*buf_ptr) & 0x1);
+                                       }
+                                       else {
+                                               SLJIT_ASSERT(addr <= 0x03ffffff);
+                                               *buf_ptr = Bx | (addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1);
+                                       }
+                               }
+                               else {
+                                       if (!(jump->flags & ABSOLUTE_B)) {
+                                               addr = addr - jump->addr;
+                                               SLJIT_ASSERT((sljit_w)addr <= 0x7fff && (sljit_w)addr >= -0x8000);
+                                               *buf_ptr = BCx | (addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001);
+                                       }
+                                       else {
+                                               addr = addr & ~0x3l;
+                                               SLJIT_ASSERT(addr <= 0xffff);
+                                               *buf_ptr = BCx | (addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001);
+                                       }
+
+                               }
+                               break;
+                       }
+                       /* Set the fields of immediate loads. */
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+                       buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
+                       buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
+#else
+                       buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff);
+                       buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff);
+                       buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff);
+                       buf_ptr[4] = (buf_ptr[4] & 0xffff0000) | (addr & 0xffff);
+#endif
+               } while (0);
+               jump = jump->next;
+       }
+
+       SLJIT_CACHE_FLUSH(code, code_ptr);
+       compiler->error = SLJIT_ERR_COMPILED;
+       compiler->executable_size = compiler->size * sizeof(sljit_ins);
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+       if (((sljit_w)code_ptr) & 0x4)
+               code_ptr++;
+       sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_w)code, sljit_generate_code);
+       return code_ptr;
+#else
+       return code;
+#endif
+}
+
+/* inp_flags: */
+
+/* Creates an index in data_transfer_insts array. */
+#define WORD_DATA      0x00
+#define BYTE_DATA      0x01
+#define HALF_DATA      0x02
+#define INT_DATA       0x03
+#define SIGNED_DATA    0x04
+#define LOAD_DATA      0x08
+#define WRITE_BACK     0x10
+#define INDEXED                0x20
+
+#define MEM_MASK       0x3f
+
+/* Other inp_flags. */
+
+#define ARG_TEST       0x000100
+/* Integer opertion and set flags -> requires exts on 64 bit systems. */
+#define ALT_SIGN_EXT   0x000200
+/* This flag affects the RC() and OERC() macros. */
+#define ALT_SET_FLAGS  0x000400
+#define ALT_FORM1      0x010000
+#define ALT_FORM2      0x020000
+#define ALT_FORM3      0x040000
+#define ALT_FORM4      0x080000
+#define ALT_FORM5      0x100000
+#define ALT_FORM6      0x200000
+
+/* Source and destination is register. */
+#define REG_DEST       0x000001
+#define REG1_SOURCE    0x000002
+#define REG2_SOURCE    0x000004
+/* getput_arg_fast returned true. */
+#define FAST_DEST      0x000008
+/* Multiple instructions are required. */
+#define SLOW_DEST      0x000010
+/*
+ALT_SIGN_EXT           0x000200
+ALT_SET_FLAGS          0x000400
+ALT_FORM1              0x010000
+...
+ALT_FORM6              0x200000 */
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+#include "sljitNativePPC_32.c"
+#else
+#include "sljitNativePPC_64.c"
+#endif
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+#define STACK_STORE    STW
+#define STACK_LOAD     LWZ
+#else
+#define STACK_STORE    STD
+#define STACK_LOAD     LD
+#endif
+
+static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w);
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       CHECK_ERROR();
+       check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+       compiler->has_locals = local_size > 0;
+
+       FAIL_IF(push_inst(compiler, MFLR | D(0)));
+       if (compiler->has_locals)
+               FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_LOCALS_REG) | A(REAL_STACK_PTR) | IMM(-(int)(sizeof(sljit_w))) ));
+       FAIL_IF(push_inst(compiler, STACK_STORE | S(ZERO_REG) | A(REAL_STACK_PTR) | IMM(-2 * (int)(sizeof(sljit_w))) ));
+       if (saveds >= 1)
+               FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG1) | A(REAL_STACK_PTR) | IMM(-3 * (int)(sizeof(sljit_w))) ));
+       if (saveds >= 2)
+               FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG2) | A(REAL_STACK_PTR) | IMM(-4 * (int)(sizeof(sljit_w))) ));
+       if (saveds >= 3)
+               FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG3) | A(REAL_STACK_PTR) | IMM(-5 * (int)(sizeof(sljit_w))) ));
+       if (saveds >= 4)
+               FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_EREG1) | A(REAL_STACK_PTR) | IMM(-6 * (int)(sizeof(sljit_w))) ));
+       if (saveds >= 5)
+               FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_EREG2) | A(REAL_STACK_PTR) | IMM(-7 * (int)(sizeof(sljit_w))) ));
+       FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(REAL_STACK_PTR) | IMM(sizeof(sljit_w)) ));
+
+       FAIL_IF(push_inst(compiler, ADDI | D(ZERO_REG) | A(0) | 0));
+       if (args >= 1)
+               FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG1) | A(SLJIT_SAVED_REG1) | B(SLJIT_TEMPORARY_REG1)));
+       if (args >= 2)
+               FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG2) | A(SLJIT_SAVED_REG2) | B(SLJIT_TEMPORARY_REG2)));
+       if (args >= 3)
+               FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG3) | A(SLJIT_SAVED_REG3) | B(SLJIT_TEMPORARY_REG3)));
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+       compiler->local_size = (2 + saveds + 2) * sizeof(sljit_w) + local_size;
+#else
+       compiler->local_size = (2 + saveds + 7 + 8) * sizeof(sljit_w) + local_size;
+#endif
+       compiler->local_size = (compiler->local_size + 15) & ~0xf;
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+       if (compiler->local_size <= SIMM_MAX)
+               FAIL_IF(push_inst(compiler, STWU | S(REAL_STACK_PTR) | A(REAL_STACK_PTR) | IMM(-compiler->local_size)));
+       else {
+               FAIL_IF(load_immediate(compiler, 0, -compiler->local_size));
+               FAIL_IF(push_inst(compiler, STWUX | S(REAL_STACK_PTR) | A(REAL_STACK_PTR) | B(0)));
+       }
+       if (compiler->has_locals)
+               FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_LOCALS_REG) | A(REAL_STACK_PTR) | IMM(2 * sizeof(sljit_w))));
+#else
+       if (compiler->local_size <= SIMM_MAX)
+               FAIL_IF(push_inst(compiler, STDU | S(REAL_STACK_PTR) | A(REAL_STACK_PTR) | IMM(-compiler->local_size)));
+       else {
+               FAIL_IF(load_immediate(compiler, 0, -compiler->local_size));
+               FAIL_IF(push_inst(compiler, STDUX | S(REAL_STACK_PTR) | A(REAL_STACK_PTR) | B(0)));
+       }
+       if (compiler->has_locals)
+               FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_LOCALS_REG) | A(REAL_STACK_PTR) | IMM((7 + 8) * sizeof(sljit_w))));
+#endif
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       CHECK_ERROR_VOID();
+       check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+
+       compiler->has_locals = local_size > 0;
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+       compiler->local_size = (2 + saveds + 2) * sizeof(sljit_w) + local_size;
+#else
+       compiler->local_size = (2 + saveds + 7 + 8) * sizeof(sljit_w) + local_size;
+#endif
+       compiler->local_size = (compiler->local_size + 15) & ~0xf;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+{
+       CHECK_ERROR();
+       check_sljit_emit_return(compiler, op, src, srcw);
+
+       FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+
+       if (compiler->local_size <= SIMM_MAX)
+               FAIL_IF(push_inst(compiler, ADDI | D(REAL_STACK_PTR) | A(REAL_STACK_PTR) | IMM(compiler->local_size)));
+       else {
+               FAIL_IF(load_immediate(compiler, 0, compiler->local_size));
+               FAIL_IF(push_inst(compiler, ADD | D(REAL_STACK_PTR) | A(REAL_STACK_PTR) | B(0)));
+       }
+
+       FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(REAL_STACK_PTR) | IMM(sizeof(sljit_w))));
+       if (compiler->saveds >= 5)
+               FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_EREG2) | A(REAL_STACK_PTR) | IMM(-7 * (int)(sizeof(sljit_w))) ));
+       if (compiler->saveds >= 4)
+               FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_EREG1) | A(REAL_STACK_PTR) | IMM(-6 * (int)(sizeof(sljit_w))) ));
+       if (compiler->saveds >= 3)
+               FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG3) | A(REAL_STACK_PTR) | IMM(-5 * (int)(sizeof(sljit_w))) ));
+       if (compiler->saveds >= 2)
+               FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG2) | A(REAL_STACK_PTR) | IMM(-4 * (int)(sizeof(sljit_w))) ));
+       if (compiler->saveds >= 1)
+               FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG1) | A(REAL_STACK_PTR) | IMM(-3 * (int)(sizeof(sljit_w))) ));
+       FAIL_IF(push_inst(compiler, STACK_LOAD | D(ZERO_REG) | A(REAL_STACK_PTR) | IMM(-2 * (int)(sizeof(sljit_w))) ));
+       if (compiler->has_locals)
+               FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_LOCALS_REG) | A(REAL_STACK_PTR) | IMM(-(int)(sizeof(sljit_w))) ));
+
+       FAIL_IF(push_inst(compiler, MTLR | S(0)));
+       FAIL_IF(push_inst(compiler, BLR));
+
+       return SLJIT_SUCCESS;
+}
+
+#undef STACK_STORE
+#undef STACK_LOAD
+
+/* --------------------------------------------------------------------- */
+/*  Operators                                                            */
+/* --------------------------------------------------------------------- */
+
+/* i/x - immediate/indexed form
+   n/w - no write-back / write-back (1 bit)
+   s/l - store/load (1 bit)
+   u/s - signed/unsigned (1 bit)
+   w/b/h/i - word/byte/half/int allowed (2 bit)
+   It contans 32 items, but not all are different. */
+
+/* 64 bit only: [reg+imm] must be aligned to 4 bytes. */
+#define ADDR_MODE2     0x10000
+/* 64-bit only: there is no lwau instruction. */
+#define UPDATE_REQ     0x20000
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+#define ARCH_DEPEND(a, b)      a
+#define GET_INST_CODE(inst)    (inst)
+#else
+#define ARCH_DEPEND(a, b)      b
+#define GET_INST_CODE(index)   ((inst) & ~(ADDR_MODE2 | UPDATE_REQ))
+#endif
+
+static SLJIT_CONST sljit_ins data_transfer_insts[64] = {
+
+/* No write-back. */
+
+/* i n s u w */ ARCH_DEPEND(HI(36) /* stw */, HI(62) | ADDR_MODE2 | 0x0 /* std */),
+/* i n s u b */ HI(38) /* stb */,
+/* i n s u h */ HI(44) /* sth*/,
+/* i n s u i */ HI(36) /* stw */,
+
+/* i n s s w */ ARCH_DEPEND(HI(36) /* stw */, HI(62) | ADDR_MODE2 | 0x0 /* std */),
+/* i n s s b */ HI(38) /* stb */,
+/* i n s s h */ HI(44) /* sth*/,
+/* i n s s i */ HI(36) /* stw */,
+
+/* i n l u w */ ARCH_DEPEND(HI(32) /* lwz */, HI(58) | ADDR_MODE2 | 0x0 /* ld */),
+/* i n l u b */ HI(34) /* lbz */,
+/* i n l u h */ HI(40) /* lhz */,
+/* i n l u i */ HI(32) /* lwz */,
+
+/* i n l s w */ ARCH_DEPEND(HI(32) /* lwz */, HI(58) | ADDR_MODE2 | 0x0 /* ld */),
+/* i n l s b */ HI(34) /* lbz */ /* EXTS_REQ */,
+/* i n l s h */ HI(42) /* lha */,
+/* i n l s i */ ARCH_DEPEND(HI(32) /* lwz */, HI(58) | ADDR_MODE2 | 0x2 /* lwa */),
+
+/* Write-back. */
+
+/* i w s u w */ ARCH_DEPEND(HI(37) /* stwu */, HI(62) | ADDR_MODE2 | 0x1 /* stdu */),
+/* i w s u b */ HI(39) /* stbu */,
+/* i w s u h */ HI(45) /* sthu */,
+/* i w s u i */ HI(37) /* stwu */,
+
+/* i w s s w */ ARCH_DEPEND(HI(37) /* stwu */, HI(62) | ADDR_MODE2 | 0x1 /* stdu */),
+/* i w s s b */ HI(39) /* stbu */,
+/* i w s s h */ HI(45) /* sthu */,
+/* i w s s i */ HI(37) /* stwu */,
+
+/* i w l u w */ ARCH_DEPEND(HI(33) /* lwzu */, HI(58) | ADDR_MODE2 | 0x1 /* ldu */),
+/* i w l u b */ HI(35) /* lbzu */,
+/* i w l u h */ HI(41) /* lhzu */,
+/* i w l u i */ HI(33) /* lwzu */,
+
+/* i w l s w */ ARCH_DEPEND(HI(33) /* lwzu */, HI(58) | ADDR_MODE2 | 0x1 /* ldu */),
+/* i w l s b */ HI(35) /* lbzu */ /* EXTS_REQ */,
+/* i w l s h */ HI(43) /* lhau */,
+/* i w l s i */ ARCH_DEPEND(HI(33) /* lwzu */, HI(58) | ADDR_MODE2 | UPDATE_REQ | 0x2 /* lwa */),
+
+/* ---------- */
+/*  Indexed   */
+/* ---------- */
+
+/* No write-back. */
+
+/* x n s u w */ ARCH_DEPEND(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
+/* x n s u b */ HI(31) | LO(215) /* stbx */,
+/* x n s u h */ HI(31) | LO(407) /* sthx */,
+/* x n s u i */ HI(31) | LO(151) /* stwx */,
+
+/* x n s s w */ ARCH_DEPEND(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
+/* x n s s b */ HI(31) | LO(215) /* stbx */,
+/* x n s s h */ HI(31) | LO(407) /* sthx */,
+/* x n s s i */ HI(31) | LO(151) /* stwx */,
+
+/* x n l u w */ ARCH_DEPEND(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
+/* x n l u b */ HI(31) | LO(87) /* lbzx */,
+/* x n l u h */ HI(31) | LO(279) /* lhzx */,
+/* x n l u i */ HI(31) | LO(23) /* lwzx */,
+
+/* x n l s w */ ARCH_DEPEND(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
+/* x n l s b */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,
+/* x n l s h */ HI(31) | LO(343) /* lhax */,
+/* x n l s i */ ARCH_DEPEND(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),
+
+/* Write-back. */
+
+/* x w s u w */ ARCH_DEPEND(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
+/* x w s u b */ HI(31) | LO(247) /* stbux */,
+/* x w s u h */ HI(31) | LO(439) /* sthux */,
+/* x w s u i */ HI(31) | LO(183) /* stwux */,
+
+/* x w s s w */ ARCH_DEPEND(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
+/* x w s s b */ HI(31) | LO(247) /* stbux */,
+/* x w s s h */ HI(31) | LO(439) /* sthux */,
+/* x w s s i */ HI(31) | LO(183) /* stwux */,
+
+/* x w l u w */ ARCH_DEPEND(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
+/* x w l u b */ HI(31) | LO(119) /* lbzux */,
+/* x w l u h */ HI(31) | LO(311) /* lhzux */,
+/* x w l u i */ HI(31) | LO(55) /* lwzux */,
+
+/* x w l s w */ ARCH_DEPEND(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
+/* x w l s b */ HI(31) | LO(119) /* lbzux */ /* EXTS_REQ */,
+/* x w l s h */ HI(31) | LO(375) /* lhaux */,
+/* x w l s i */ ARCH_DEPEND(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */)
+
+};
+
+#undef ARCH_DEPEND
+
+/* Simple cases, (no caching is required). */
+static int getput_arg_fast(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw)
+{
+       sljit_ins inst;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+       int tmp_reg;
+#endif
+
+       SLJIT_ASSERT(arg & SLJIT_MEM);
+       if (!(arg & 0xf)) {
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+               if (argw <= SIMM_MAX && argw >= SIMM_MIN) {
+                       if (inp_flags & ARG_TEST)
+                               return 1;
+
+                       inst = data_transfer_insts[(inp_flags & ~WRITE_BACK) & MEM_MASK];
+                       SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
+                       push_inst(compiler, GET_INST_CODE(inst) | D(reg) | IMM(argw));
+                       return -1;
+               }
+#else
+               inst = data_transfer_insts[(inp_flags & ~WRITE_BACK) & MEM_MASK];
+               if (argw <= SIMM_MAX && argw >= SIMM_MIN &&
+                               (!(inst & ADDR_MODE2) || (argw & 0x3) == 0)) {
+                       if (inp_flags & ARG_TEST)
+                               return 1;
+
+                       push_inst(compiler, GET_INST_CODE(inst) | D(reg) | IMM(argw));
+                       return -1;
+               }
+#endif
+               return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
+       }
+
+       if (!(arg & 0xf0)) {
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+               if (argw <= SIMM_MAX && argw >= SIMM_MIN) {
+                       if (inp_flags & ARG_TEST)
+                               return 1;
+
+                       inst = data_transfer_insts[inp_flags & MEM_MASK];
+                       SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
+                       push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | IMM(argw));
+                       return -1;
+               }
+#else
+               inst = data_transfer_insts[inp_flags & MEM_MASK];
+               if (argw <= SIMM_MAX && argw >= SIMM_MIN && (!(inst & ADDR_MODE2) || (argw & 0x3) == 0)) {
+                       if (inp_flags & ARG_TEST)
+                               return 1;
+
+                       if ((inp_flags & WRITE_BACK) && (inst & UPDATE_REQ)) {
+                               tmp_reg = (inp_flags & LOAD_DATA) ? (arg & 0xf) : TMP_REG3;
+                               if (push_inst(compiler, ADDI | D(tmp_reg) | A(arg & 0xf) | IMM(argw)))
+                                       return -1;
+                               arg = tmp_reg | SLJIT_MEM;
+                               argw = 0;
+                       }
+                       push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | IMM(argw));
+                       return -1;
+               }
+#endif
+       }
+       else if (!(argw & 0x3)) {
+               if (inp_flags & ARG_TEST)
+                       return 1;
+               inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
+               SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
+               push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | B((arg >> 4) & 0xf));
+               return -1;
+       }
+       return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
+}
+
+/* See getput_arg below.
+   Note: can_cache is called only for binary operators. Those operator always
+   uses word arguments without write back. */
+static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+{
+       SLJIT_ASSERT(arg & SLJIT_MEM);
+       SLJIT_ASSERT(next_arg & SLJIT_MEM);
+
+       if (!(arg & 0xf)) {
+               if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= SIMM_MAX || (sljit_uw)next_argw - (sljit_uw)argw <= SIMM_MAX))
+                       return 1;
+               return 0;
+       }
+
+       if (arg & 0xf0)
+               return 0;
+
+       if (argw <= SIMM_MAX && argw >= SIMM_MIN) {
+               if (arg == next_arg && (next_argw >= SIMM_MAX && next_argw <= SIMM_MIN))
+                       return 1;
+       }
+
+       if (arg == next_arg && ((sljit_uw)argw - (sljit_uw)next_argw <= SIMM_MAX || (sljit_uw)next_argw - (sljit_uw)argw <= SIMM_MAX))
+               return 1;
+
+       return 0;
+}
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#define ADJUST_CACHED_IMM(imm) \
+       if ((inst & ADDR_MODE2) && (imm & 0x3)) { \
+               /* Adjust cached value. Fortunately this is really a rare case */ \
+               compiler->cache_argw += imm & 0x3; \
+               FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG3) | A(TMP_REG3) | (imm & 0x3))); \
+               imm &= ~0x3; \
+       }
+#else
+#define ADJUST_CACHED_IMM(imm)
+#endif
+
+/* Emit the necessary instructions. See can_cache above. */
+static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw, int next_arg, sljit_w next_argw)
+{
+       int tmp_r;
+       sljit_ins inst;
+
+       SLJIT_ASSERT(arg & SLJIT_MEM);
+
+       tmp_r = (inp_flags & LOAD_DATA) ? reg : TMP_REG3;
+       if ((arg & 0xf) == tmp_r) {
+               /* Special case for "mov reg, [reg, ... ]".
+                  Caching would not happen anyway. */
+               tmp_r = TMP_REG3;
+               compiler->cache_arg = 0;
+               compiler->cache_argw = 0;
+       }
+
+       if (!(arg & 0xf)) {
+               inst = data_transfer_insts[(inp_flags & ~WRITE_BACK) & MEM_MASK];
+               if ((compiler->cache_arg & SLJIT_IMM) && (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= SIMM_MAX || ((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= SIMM_MAX)) {
+                       argw = argw - compiler->cache_argw;
+                       ADJUST_CACHED_IMM(argw);
+                       SLJIT_ASSERT(!(inst & UPDATE_REQ));
+                       return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(TMP_REG3) | IMM(argw));
+               }
+
+               if ((next_arg & SLJIT_MEM) && (argw - next_argw <= SIMM_MAX || next_argw - argw <= SIMM_MAX)) {
+                       SLJIT_ASSERT(inp_flags & LOAD_DATA);
+
+                       compiler->cache_arg = SLJIT_IMM;
+                       compiler->cache_argw = argw;
+                       tmp_r = TMP_REG3;
+               }
+
+               FAIL_IF(load_immediate(compiler, tmp_r, argw));
+               return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(tmp_r));
+       }
+
+       if (SLJIT_UNLIKELY(arg & 0xf0)) {
+               argw &= 0x3;
+               /* Otherwise getput_arg_fast would capture it. */
+               SLJIT_ASSERT(argw);
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+               FAIL_IF(push_inst(compiler, RLWINM | S((arg >> 4) & 0xf) | A(tmp_r) | (argw << 11) | ((31 - argw) << 1)));
+#else
+               FAIL_IF(push_inst(compiler, RLDI(tmp_r, (arg >> 4) & 0xf, argw, 63 - argw, 1)));
+#endif
+               inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
+               SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
+               return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | B(tmp_r));
+       }
+
+       inst = data_transfer_insts[inp_flags & MEM_MASK];
+
+       if (compiler->cache_arg == arg && ((sljit_uw)argw - (sljit_uw)compiler->cache_argw <= SIMM_MAX || (sljit_uw)compiler->cache_argw - (sljit_uw)argw <= SIMM_MAX)) {
+               SLJIT_ASSERT(!(inp_flags & WRITE_BACK));
+               argw = argw - compiler->cache_argw;
+               ADJUST_CACHED_IMM(argw);
+               return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(TMP_REG3) | IMM(argw));
+       }
+
+       if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) {
+               inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
+               SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
+               return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | B(TMP_REG3));
+       }
+
+       if (argw == next_argw && (next_arg & SLJIT_MEM)) {
+               SLJIT_ASSERT(inp_flags & LOAD_DATA);
+               FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+
+               compiler->cache_arg = SLJIT_IMM;
+               compiler->cache_argw = argw;
+
+               inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
+               SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
+               return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | B(TMP_REG3));
+       }
+
+       if (arg == next_arg && !(inp_flags & WRITE_BACK) && ((sljit_uw)argw - (sljit_uw)next_argw <= SIMM_MAX || (sljit_uw)next_argw - (sljit_uw)argw <= SIMM_MAX)) {
+               SLJIT_ASSERT(inp_flags & LOAD_DATA);
+               FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+               FAIL_IF(push_inst(compiler, ADD | D(TMP_REG3) | A(TMP_REG3) | B(arg & 0xf)));
+
+               compiler->cache_arg = arg;
+               compiler->cache_argw = argw;
+
+               return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(TMP_REG3));
+       }
+
+       /* Get the indexed version instead of the normal one. */
+       inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
+       SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ)));
+       FAIL_IF(load_immediate(compiler, tmp_r, argw));
+       return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | B(tmp_r));
+}
+
+static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       /* arg1 goes to TMP_REG1 or src reg
+          arg2 goes to TMP_REG2, imm or src reg
+          TMP_REG3 can be used for caching
+          result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
+       int dst_r;
+       int src1_r;
+       int src2_r;
+       int sugg_src2_r = TMP_REG2;
+       int flags = inp_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_FORM6 | ALT_SIGN_EXT | ALT_SET_FLAGS);
+
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+
+       /* Destination check. */
+       if (dst >= SLJIT_TEMPORARY_REG1 && dst <= ZERO_REG) {
+               dst_r = dst;
+               flags |= REG_DEST;
+               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+                       sugg_src2_r = dst_r;
+       }
+       else if (dst == SLJIT_UNUSED) {
+               if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
+                       return SLJIT_SUCCESS;
+               dst_r = TMP_REG2;
+       }
+       else {
+               SLJIT_ASSERT(dst & SLJIT_MEM);
+               if (getput_arg_fast(compiler, inp_flags | ARG_TEST, TMP_REG2, dst, dstw)) {
+                       flags |= FAST_DEST;
+                       dst_r = TMP_REG2;
+               }
+               else {
+                       flags |= SLOW_DEST;
+                       dst_r = 0;
+               }
+       }
+
+       /* Source 1. */
+       if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= ZERO_REG) {
+               src1_r = src1;
+               flags |= REG1_SOURCE;
+       }
+       else if (src1 & SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+               if ((inp_flags & 0x3) == INT_DATA) {
+                       if (inp_flags & SIGNED_DATA)
+                               src1w = (signed int)src1w;
+                       else
+                               src1w = (unsigned int)src1w;
+               }
+#endif
+               FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
+               src1_r = TMP_REG1;
+       }
+       else if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w)) {
+               FAIL_IF(compiler->error);
+               src1_r = TMP_REG1;
+       }
+       else
+               src1_r = 0;
+
+       /* Source 2. */
+       if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= ZERO_REG) {
+               src2_r = src2;
+               flags |= REG2_SOURCE;
+               if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
+                       dst_r = src2_r;
+       }
+       else if (src2 & SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+               if ((inp_flags & 0x3) == INT_DATA) {
+                       if (inp_flags & SIGNED_DATA)
+                               src2w = (signed int)src2w;
+                       else
+                               src2w = (unsigned int)src2w;
+               }
+#endif
+               FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));
+               src2_r = sugg_src2_r;
+       }
+       else if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w)) {
+               FAIL_IF(compiler->error);
+               src2_r = sugg_src2_r;
+       }
+       else
+               src2_r = 0;
+
+       /* src1_r, src2_r and dst_r can be zero (=unprocessed).
+          All arguments are complex addressing modes, and it is a binary operator. */
+       if (src1_r == 0 && src2_r == 0 && dst_r == 0) {
+               if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
+                       FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
+                       FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
+               }
+               else {
+                       FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
+                       FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw));
+               }
+               src1_r = TMP_REG1;
+               src2_r = TMP_REG2;
+       }
+       else if (src1_r == 0 && src2_r == 0) {
+               FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
+               src1_r = TMP_REG1;
+       }
+       else if (src1_r == 0 && dst_r == 0) {
+               FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
+               src1_r = TMP_REG1;
+       }
+       else if (src2_r == 0 && dst_r == 0) {
+               FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw));
+               src2_r = sugg_src2_r;
+       }
+
+       if (dst_r == 0)
+               dst_r = TMP_REG2;
+
+       if (src1_r == 0) {
+               FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, 0, 0));
+               src1_r = TMP_REG1;
+       }
+
+       if (src2_r == 0) {
+               FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, 0, 0));
+               src2_r = sugg_src2_r;
+       }
+
+       FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
+
+       if (flags & (FAST_DEST | SLOW_DEST)) {
+               if (flags & FAST_DEST)
+                       FAIL_IF(getput_arg_fast(compiler, inp_flags, dst_r, dst, dstw));
+               else
+                       FAIL_IF(getput_arg(compiler, inp_flags, dst_r, dst, dstw, 0, 0));
+       }
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
+{
+       CHECK_ERROR();
+       check_sljit_emit_op0(compiler, op);
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_BREAKPOINT:
+       case SLJIT_NOP:
+               return push_inst(compiler, NOP);
+               break;
+       case SLJIT_UMUL:
+       case SLJIT_SMUL:
+               FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG1)));
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+               FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)));
+               return push_inst(compiler, (GET_OPCODE(op) == SLJIT_UMUL ? MULHDU : MULHD) | D(SLJIT_TEMPORARY_REG2) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2));
+#else
+               FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)));
+               return push_inst(compiler, (GET_OPCODE(op) == SLJIT_UMUL ? MULHWU : MULHW) | D(SLJIT_TEMPORARY_REG2) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2));
+#endif
+       case SLJIT_UDIV:
+       case SLJIT_SDIV:
+               FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG1)));
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+               if (op & SLJIT_INT_OP) {
+                       FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)));
+                       FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG1) | B(SLJIT_TEMPORARY_REG2)));
+                       return push_inst(compiler, SUBF | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG2) | B(TMP_REG1));
+               }
+               FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVDU : DIVD) | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)));
+               FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG1) | B(SLJIT_TEMPORARY_REG2)));
+               return push_inst(compiler, SUBF | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG2) | B(TMP_REG1));
+#else
+               FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)));
+               FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG1) | B(SLJIT_TEMPORARY_REG2)));
+               return push_inst(compiler, SUBF | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG2) | B(TMP_REG1));
+#endif
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       int inp_flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0;
+
+       CHECK_ERROR();
+       check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
+
+       if ((src & SLJIT_IMM) && srcw == 0)
+               src = ZERO_REG;
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+       if (op & SLJIT_INT_OP) {
+               inp_flags |= INT_DATA | SIGNED_DATA;
+               if (src & SLJIT_IMM)
+                       srcw = (int)srcw;
+       }
+#endif
+       if (op & SLJIT_SET_O)
+               FAIL_IF(push_inst(compiler, MTXER | S(ZERO_REG)));
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_MOV:
+               return emit_op(compiler, SLJIT_MOV, inp_flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_MOV_UI:
+               return emit_op(compiler, SLJIT_MOV_UI, inp_flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_MOV_SI:
+               return emit_op(compiler, SLJIT_MOV_SI, inp_flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_MOV_UB:
+               return emit_op(compiler, SLJIT_MOV_UB, inp_flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw);
+
+       case SLJIT_MOV_SB:
+               return emit_op(compiler, SLJIT_MOV_SB, inp_flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw);
+
+       case SLJIT_MOV_UH:
+               return emit_op(compiler, SLJIT_MOV_UH, inp_flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw);
+
+       case SLJIT_MOV_SH:
+               return emit_op(compiler, SLJIT_MOV_SH, inp_flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw);
+
+       case SLJIT_MOVU:
+               return emit_op(compiler, SLJIT_MOV, inp_flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_MOVU_UI:
+               return emit_op(compiler, SLJIT_MOV_UI, inp_flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_MOVU_SI:
+               return emit_op(compiler, SLJIT_MOV_SI, inp_flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_MOVU_UB:
+               return emit_op(compiler, SLJIT_MOV_UB, inp_flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw);
+
+       case SLJIT_MOVU_SB:
+               return emit_op(compiler, SLJIT_MOV_SB, inp_flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw);
+
+       case SLJIT_MOVU_UH:
+               return emit_op(compiler, SLJIT_MOV_UH, inp_flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw);
+
+       case SLJIT_MOVU_SH:
+               return emit_op(compiler, SLJIT_MOV_SH, inp_flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw);
+
+       case SLJIT_NOT:
+               return emit_op(compiler, SLJIT_NOT, inp_flags, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_NEG:
+               return emit_op(compiler, SLJIT_NEG, inp_flags, dst, dstw, TMP_REG1, 0, src, srcw);
+
+       case SLJIT_CLZ:
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+               return emit_op(compiler, SLJIT_CLZ, inp_flags | (!(op & SLJIT_INT_OP) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw);
+#else
+               return emit_op(compiler, SLJIT_CLZ, inp_flags, dst, dstw, TMP_REG1, 0, src, srcw);
+#endif
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+#define TEST_SL_IMM(src, srcw) \
+       (((src) & SLJIT_IMM) && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)
+
+#define TEST_UL_IMM(src, srcw) \
+       (((src) & SLJIT_IMM) && !((srcw) & ~0xffff))
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#define TEST_SH_IMM(src, srcw) \
+       (((src) & SLJIT_IMM) && !((srcw) & 0xffff) && (srcw) <= SLJIT_W(0x7fffffff) && (srcw) >= SLJIT_W(-0x80000000))
+#else
+#define TEST_SH_IMM(src, srcw) \
+       (((src) & SLJIT_IMM) && !((srcw) & 0xffff))
+#endif
+
+#define TEST_UH_IMM(src, srcw) \
+       (((src) & SLJIT_IMM) && !((srcw) & ~0xffff0000))
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#define TEST_ADD_IMM(src, srcw) \
+       (((src) & SLJIT_IMM) && (srcw) <= SLJIT_W(0x7fff7fff) && (srcw) >= SLJIT_W(-0x80000000))
+#else
+#define TEST_ADD_IMM(src, srcw) \
+       ((src) & SLJIT_IMM)
+#endif
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#define TEST_UI_IMM(src, srcw) \
+       (((src) & SLJIT_IMM) && !((srcw) & ~0xffffffff))
+#else
+#define TEST_UI_IMM(src, srcw) \
+       ((src) & SLJIT_IMM)
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       int inp_flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0;
+
+       CHECK_ERROR();
+       check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+
+       if ((src1 & SLJIT_IMM) && src1w == 0)
+               src1 = ZERO_REG;
+       if ((src2 & SLJIT_IMM) && src2w == 0)
+               src2 = ZERO_REG;
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+       if (op & SLJIT_INT_OP) {
+               inp_flags |= INT_DATA | SIGNED_DATA;
+               if (src1 & SLJIT_IMM)
+                       src1w = (src1w << 32) >> 32;
+               if (src2 & SLJIT_IMM)
+                       src2w = (src2w << 32) >> 32;
+               if (GET_FLAGS(op))
+                       inp_flags |= ALT_SIGN_EXT;
+       }
+#endif
+       if (op & SLJIT_SET_O)
+               FAIL_IF(push_inst(compiler, MTXER | S(ZERO_REG)));
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_ADD:
+               if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
+                       if (TEST_SL_IMM(src2, src2w)) {
+                               compiler->imm = src2w & 0xffff;
+                               return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+                       }
+                       if (TEST_SL_IMM(src1, src1w)) {
+                               compiler->imm = src1w & 0xffff;
+                               return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
+                       }
+                       if (TEST_SH_IMM(src2, src2w)) {
+                               compiler->imm = (src2w >> 16) & 0xffff;
+                               return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+                       }
+                       if (TEST_SH_IMM(src1, src1w)) {
+                               compiler->imm = (src1w >> 16) & 0xffff;
+                               return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
+                       }
+                       /* Range between -1 and -32768 is covered above. */
+                       if (TEST_ADD_IMM(src2, src2w)) {
+                               compiler->imm = src2w & 0xffffffff;
+                               return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
+                       }
+                       if (TEST_ADD_IMM(src1, src1w)) {
+                               compiler->imm = src1w & 0xffffffff;
+                               return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
+                       }
+               }
+               if (!(GET_FLAGS(op) & (SLJIT_SET_E | SLJIT_SET_O))) {
+                       if (TEST_SL_IMM(src2, src2w)) {
+                               compiler->imm = src2w & 0xffff;
+                               return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+                       }
+                       if (TEST_SL_IMM(src1, src1w)) {
+                               compiler->imm = src1w & 0xffff;
+                               return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
+                       }
+               }
+               return emit_op(compiler, SLJIT_ADD, inp_flags, dst, dstw, src1, src1w, src2, src2w);
+
+       case SLJIT_ADDC:
+               return emit_op(compiler, SLJIT_ADDC, inp_flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w);
+
+       case SLJIT_SUB:
+               if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
+                       if (TEST_SL_IMM(src2, -src2w)) {
+                               compiler->imm = (-src2w) & 0xffff;
+                               return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+                       }
+                       if (TEST_SL_IMM(src1, src1w)) {
+                               compiler->imm = src1w & 0xffff;
+                               return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
+                       }
+                       if (TEST_SH_IMM(src2, -src2w)) {
+                               compiler->imm = ((-src2w) >> 16) & 0xffff;
+                               return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+                       }
+                       /* Range between -1 and -32768 is covered above. */
+                       if (TEST_ADD_IMM(src2, -src2w)) {
+                               compiler->imm = -src2w & 0xffffffff;
+                               return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
+                       }
+               }
+               if (dst == SLJIT_UNUSED && (op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U)) && !(op & (SLJIT_SET_O | SLJIT_SET_C))) {
+                       if (!(op & SLJIT_SET_U)) {
+                               /* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */
+                               if (TEST_SL_IMM(src2, src2w)) {
+                                       compiler->imm = src2w & 0xffff;
+                                       return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+                               }
+                               if (GET_FLAGS(op) == SLJIT_SET_E && TEST_SL_IMM(src1, src1w)) {
+                                       compiler->imm = src1w & 0xffff;
+                                       return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
+                               }
+                       }
+                       if (!(op & (SLJIT_SET_E | SLJIT_SET_S))) {
+                               /* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */
+                               if (TEST_UL_IMM(src2, src2w)) {
+                                       compiler->imm = src2w & 0xffff;
+                                       return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+                               }
+                               return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
+                       }
+                       if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= 0x7fff) {
+                               compiler->imm = src2w;
+                               return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+                       }
+                       return emit_op(compiler, SLJIT_SUB, inp_flags | ((op & SLJIT_SET_U) ? ALT_FORM4 : 0) | ((op & (SLJIT_SET_E | SLJIT_SET_S)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
+               }
+               if (!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O))) {
+                       if (TEST_SL_IMM(src2, -src2w)) {
+                               compiler->imm = (-src2w) & 0xffff;
+                               return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+                       }
+               }
+               /* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */
+               return emit_op(compiler, SLJIT_SUB, inp_flags | (!(op & SLJIT_SET_U) ? 0 : ALT_FORM6), dst, dstw, src1, src1w, src2, src2w);
+
+       case SLJIT_SUBC:
+               return emit_op(compiler, SLJIT_SUBC, inp_flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w);
+
+       case SLJIT_MUL:
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+               if (op & SLJIT_INT_OP)
+                       inp_flags |= ALT_FORM2;
+#endif
+               if (!GET_FLAGS(op)) {
+                       if (TEST_SL_IMM(src2, src2w)) {
+                               compiler->imm = src2w & 0xffff;
+                               return emit_op(compiler, SLJIT_MUL, inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+                       }
+                       if (TEST_SL_IMM(src1, src1w)) {
+                               compiler->imm = src1w & 0xffff;
+                               return emit_op(compiler, SLJIT_MUL, inp_flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
+                       }
+               }
+               return emit_op(compiler, SLJIT_MUL, inp_flags, dst, dstw, src1, src1w, src2, src2w);
+
+       case SLJIT_AND:
+       case SLJIT_OR:
+       case SLJIT_XOR:
+               /* Commutative unsigned operations. */
+               if (!GET_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
+                       if (TEST_UL_IMM(src2, src2w)) {
+                               compiler->imm = src2w;
+                               return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+                       }
+                       if (TEST_UL_IMM(src1, src1w)) {
+                               compiler->imm = src1w;
+                               return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
+                       }
+                       if (TEST_UH_IMM(src2, src2w)) {
+                               compiler->imm = (src2w >> 16) & 0xffff;
+                               return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+                       }
+                       if (TEST_UH_IMM(src1, src1w)) {
+                               compiler->imm = (src1w >> 16) & 0xffff;
+                               return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
+                       }
+               }
+               if (!GET_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) {
+                       if (TEST_UI_IMM(src2, src2w)) {
+                               compiler->imm = src2w;
+                               return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+                       }
+                       if (TEST_UI_IMM(src1, src1w)) {
+                               compiler->imm = src1w;
+                               return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
+                       }
+               }
+               return emit_op(compiler, GET_OPCODE(op), inp_flags, dst, dstw, src1, src1w, src2, src2w);
+
+       case SLJIT_SHL:
+       case SLJIT_LSHR:
+       case SLJIT_ASHR:
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+               if (op & SLJIT_INT_OP)
+                       inp_flags |= ALT_FORM2;
+#endif
+               if (src2 & SLJIT_IMM) {
+                       compiler->imm = src2w;
+                       return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+               }
+               return emit_op(compiler, GET_OPCODE(op), inp_flags, dst, dstw, src1, src1w, src2, src2w);
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
+{
+       check_sljit_get_register_index(reg);
+       return reg_map[reg];
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, int size)
+{
+       CHECK_ERROR();
+       check_sljit_emit_op_custom(compiler, instruction, size);
+       SLJIT_ASSERT(size == 4);
+
+       return push_inst(compiler, *(sljit_ins*)instruction);
+}
+
+/* --------------------------------------------------------------------- */
+/*  Floating point operators                                             */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
+{
+       /* Always available. */
+       return 1;
+}
+
+static int emit_fpu_data_transfer(struct sljit_compiler *compiler, int fpu_reg, int load, int arg, sljit_w argw)
+{
+       SLJIT_ASSERT(arg & SLJIT_MEM);
+
+       /* Fast loads and stores. */
+       if (!(arg & 0xf0)) {
+               /* Both for (arg & 0xf) == SLJIT_UNUSED and (arg & 0xf) != SLJIT_UNUSED. */
+               if (argw <= SIMM_MAX && argw >= SIMM_MIN)
+                       return push_inst(compiler, (load ? LFD : STFD) | FD(fpu_reg) | A(arg & 0xf) | IMM(argw));
+       }
+
+       if (arg & 0xf0) {
+               argw &= 0x3;
+               if (argw) {
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+                       FAIL_IF(push_inst(compiler, RLWINM | S((arg >> 4) & 0xf) | A(TMP_REG2) | (argw << 11) | ((31 - argw) << 1)));
+#else
+                       FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, (arg >> 4) & 0xf, argw, 63 - argw, 1)));
+#endif
+                       return push_inst(compiler, (load ? LFDX : STFDX) | FD(fpu_reg) | A(arg & 0xf) | B(TMP_REG2));
+               }
+               return push_inst(compiler, (load ? LFDX : STFDX) | FD(fpu_reg) | A(arg & 0xf) | B((arg >> 4) & 0xf));
+       }
+
+       /* Use cache. */
+       if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)
+               return push_inst(compiler, (load ? LFD : STFD) | FD(fpu_reg) | A(TMP_REG3) | IMM(argw - compiler->cache_argw));
+
+       /* Put value to cache. */
+       compiler->cache_arg = arg;
+       compiler->cache_argw = argw;
+
+       FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+       if (!(arg & 0xf))
+               return push_inst(compiler, (load ? LFDX : STFDX) | FD(fpu_reg) | A(0) | B(TMP_REG3));
+       return push_inst(compiler, (load ? LFDUX : STFDUX) | FD(fpu_reg) | A(TMP_REG3) | B(arg & 0xf));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       int dst_fr;
+
+       CHECK_ERROR();
+       check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
+
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+
+       if (GET_OPCODE(op) == SLJIT_FCMP) {
+               if (dst > SLJIT_FLOAT_REG4) {
+                       FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, dst, dstw));
+                       dst = TMP_FREG1;
+               }
+               if (src > SLJIT_FLOAT_REG4) {
+                       FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src, srcw));
+                       src = TMP_FREG2;
+               }
+               return push_inst(compiler, FCMPU | CRD(4) | FA(dst) | FB(src));
+       }
+
+       dst_fr = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst;
+
+       if (src > SLJIT_FLOAT_REG4) {
+               FAIL_IF(emit_fpu_data_transfer(compiler, dst_fr, 1, src, srcw));
+               src = dst_fr;
+       }
+
+       switch (op) {
+               case SLJIT_FMOV:
+                       if (src != dst_fr && dst_fr != TMP_FREG1)
+                               FAIL_IF(push_inst(compiler, FMR | FD(dst_fr) | FB(src)));
+                       break;
+               case SLJIT_FNEG:
+                       FAIL_IF(push_inst(compiler, FNEG | FD(dst_fr) | FB(src)));
+                       break;
+               case SLJIT_FABS:
+                       FAIL_IF(push_inst(compiler, FABS | FD(dst_fr) | FB(src)));
+                       break;
+       }
+
+       if (dst_fr == TMP_FREG1)
+               FAIL_IF(emit_fpu_data_transfer(compiler, src, 0, dst, dstw));
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       int dst_fr;
+
+       CHECK_ERROR();
+       check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+
+       compiler->cache_arg = 0;
+       compiler->cache_argw = 0;
+
+       dst_fr = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst;
+
+       if (src2 > SLJIT_FLOAT_REG4) {
+               FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w));
+               src2 = TMP_FREG2;
+       }
+
+       if (src1 > SLJIT_FLOAT_REG4) {
+               FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w));
+               src1 = TMP_FREG1;
+       }
+
+       switch (op) {
+       case SLJIT_FADD:
+               FAIL_IF(push_inst(compiler, FADD | FD(dst_fr) | FA(src1) | FB(src2)));
+               break;
+
+       case SLJIT_FSUB:
+               FAIL_IF(push_inst(compiler, FSUB | FD(dst_fr) | FA(src1) | FB(src2)));
+               break;
+
+       case SLJIT_FMUL:
+               FAIL_IF(push_inst(compiler, FMUL | FD(dst_fr) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));
+               break;
+
+       case SLJIT_FDIV:
+               FAIL_IF(push_inst(compiler, FDIV | FD(dst_fr) | FA(src1) | FB(src2)));
+               break;
+       }
+
+       if (dst_fr == TMP_FREG1)
+               FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 0, dst, dstw));
+
+       return SLJIT_SUCCESS;
+}
+
+/* --------------------------------------------------------------------- */
+/*  Other instructions                                                   */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
+{
+       CHECK_ERROR();
+       check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+
+       compiler->has_locals = local_size > 0;
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+       compiler->local_size = (2 + saveds + 2) * sizeof(sljit_w) + local_size;
+#else
+       compiler->local_size = (2 + saveds + 7 + 8) * sizeof(sljit_w) + local_size;
+#endif
+       compiler->local_size = (compiler->local_size + 15) & ~0xf;
+
+       if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
+               return push_inst(compiler, MFLR | D(dst));
+       else if (dst & SLJIT_MEM) {
+               FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG2)));
+               return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+{
+       CHECK_ERROR();
+       check_sljit_emit_fast_return(compiler, src, srcw);
+
+       if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
+               FAIL_IF(push_inst(compiler, MTLR | S(src)));
+       else {
+               if (src & SLJIT_MEM)
+                       FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
+               else if (src & SLJIT_IMM)
+                       FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));
+               FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));
+       }
+       return push_inst(compiler, BLR);
+}
+
+/* --------------------------------------------------------------------- */
+/*  Conditional instructions                                             */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+       struct sljit_label *label;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_label(compiler);
+
+       if (compiler->last_label && compiler->last_label->size == compiler->size)
+               return compiler->last_label;
+
+       label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+       PTR_FAIL_IF(!label);
+       set_label(label, compiler);
+       return label;
+}
+
+static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, int type)
+{
+       switch (type) {
+       case SLJIT_C_EQUAL:
+               return (12 << 21) | (2 << 16);
+
+       case SLJIT_C_NOT_EQUAL:
+               return (4 << 21) | (2 << 16);
+
+       case SLJIT_C_LESS:
+       case SLJIT_C_FLOAT_LESS:
+               return (12 << 21) | ((4 + 0) << 16);
+
+       case SLJIT_C_GREATER_EQUAL:
+       case SLJIT_C_FLOAT_GREATER_EQUAL:
+               return (4 << 21) | ((4 + 0) << 16);
+
+       case SLJIT_C_GREATER:
+       case SLJIT_C_FLOAT_GREATER:
+               return (12 << 21) | ((4 + 1) << 16);
+
+       case SLJIT_C_LESS_EQUAL:
+       case SLJIT_C_FLOAT_LESS_EQUAL:
+               return (4 << 21) | ((4 + 1) << 16);
+
+       case SLJIT_C_SIG_LESS:
+               return (12 << 21) | (0 << 16);
+
+       case SLJIT_C_SIG_GREATER_EQUAL:
+               return (4 << 21) | (0 << 16);
+
+       case SLJIT_C_SIG_GREATER:
+               return (12 << 21) | (1 << 16);
+
+       case SLJIT_C_SIG_LESS_EQUAL:
+               return (4 << 21) | (1 << 16);
+
+       case SLJIT_C_OVERFLOW:
+       case SLJIT_C_MUL_OVERFLOW:
+               return (12 << 21) | (3 << 16);
+
+       case SLJIT_C_NOT_OVERFLOW:
+       case SLJIT_C_MUL_NOT_OVERFLOW:
+               return (4 << 21) | (3 << 16);
+
+       case SLJIT_C_FLOAT_EQUAL:
+               return (12 << 21) | ((4 + 2) << 16);
+
+       case SLJIT_C_FLOAT_NOT_EQUAL:
+               return (4 << 21) | ((4 + 2) << 16);
+
+       case SLJIT_C_FLOAT_NAN:
+               return (12 << 21) | ((4 + 3) << 16);
+
+       case SLJIT_C_FLOAT_NOT_NAN:
+               return (4 << 21) | ((4 + 3) << 16);
+
+       default:
+               SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL3);
+               return (20 << 21);
+       }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type)
+{
+       struct sljit_jump *jump;
+       sljit_ins bo_bi_flags;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_jump(compiler, type);
+
+       bo_bi_flags = get_bo_bi_flags(compiler, type & 0xff);
+       if (!bo_bi_flags)
+               return NULL;
+
+       jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+       PTR_FAIL_IF(!jump);
+       set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+       type &= 0xff;
+
+       /* In PPC, we don't need to touch the arguments. */
+       if (type >= SLJIT_JUMP)
+               jump->flags |= UNCOND_B;
+
+       PTR_FAIL_IF(emit_const(compiler, TMP_REG1, 0));
+       PTR_FAIL_IF(push_inst(compiler, MTCTR | S(TMP_REG1)));
+       jump->addr = compiler->size;
+       PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)));
+       return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
+{
+       sljit_ins bo_bi_flags;
+       struct sljit_jump *jump = NULL;
+       int src_r;
+
+       CHECK_ERROR();
+       check_sljit_emit_ijump(compiler, type, src, srcw);
+
+       bo_bi_flags = get_bo_bi_flags(compiler, type);
+       FAIL_IF(!bo_bi_flags);
+
+       if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)
+               src_r = src;
+       else if (src & SLJIT_IMM) {
+               jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+               FAIL_IF(!jump);
+               set_jump(jump, compiler, JUMP_ADDR | UNCOND_B);
+               jump->u.target = srcw;
+
+               FAIL_IF(emit_const(compiler, TMP_REG2, 0));
+               src_r = TMP_REG2;
+       }
+       else {
+               FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
+               src_r = TMP_REG2;
+       }
+
+       FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));
+       if (jump)
+               jump->addr = compiler->size;
+       return push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0));
+}
+
+/* Get a bit from CR, all other bits are zeroed. */
+#define GET_CR_BIT(bit, dst) \
+       FAIL_IF(push_inst(compiler, MFCR | D(dst))); \
+       FAIL_IF(push_inst(compiler, RLWINM | S(dst) | A(dst) | ((1 + (bit)) << 11) | (31 << 6) | (31 << 1)));
+
+#define INVERT_BIT(dst) \
+       FAIL_IF(push_inst(compiler, XORI | S(dst) | A(dst) | 0x1));
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type)
+{
+       int reg;
+
+       CHECK_ERROR();
+       check_sljit_emit_cond_value(compiler, op, dst, dstw, type);
+
+       if (dst == SLJIT_UNUSED)
+               return SLJIT_SUCCESS;
+
+       reg = (op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2;
+
+       switch (type) {
+       case SLJIT_C_EQUAL:
+               GET_CR_BIT(2, reg);
+               break;
+
+       case SLJIT_C_NOT_EQUAL:
+               GET_CR_BIT(2, reg);
+               INVERT_BIT(reg);
+               break;
+
+       case SLJIT_C_LESS:
+       case SLJIT_C_FLOAT_LESS:
+               GET_CR_BIT(4 + 0, reg);
+               break;
+
+       case SLJIT_C_GREATER_EQUAL:
+       case SLJIT_C_FLOAT_GREATER_EQUAL:
+               GET_CR_BIT(4 + 0, reg);
+               INVERT_BIT(reg);
+               break;
+
+       case SLJIT_C_GREATER:
+       case SLJIT_C_FLOAT_GREATER:
+               GET_CR_BIT(4 + 1, reg);
+               break;
+
+       case SLJIT_C_LESS_EQUAL:
+       case SLJIT_C_FLOAT_LESS_EQUAL:
+               GET_CR_BIT(4 + 1, reg);
+               INVERT_BIT(reg);
+               break;
+
+       case SLJIT_C_SIG_LESS:
+               GET_CR_BIT(0, reg);
+               break;
+
+       case SLJIT_C_SIG_GREATER_EQUAL:
+               GET_CR_BIT(0, reg);
+               INVERT_BIT(reg);
+               break;
+
+       case SLJIT_C_SIG_GREATER:
+               GET_CR_BIT(1, reg);
+               break;
+
+       case SLJIT_C_SIG_LESS_EQUAL:
+               GET_CR_BIT(1, reg);
+               INVERT_BIT(reg);
+               break;
+
+       case SLJIT_C_OVERFLOW:
+       case SLJIT_C_MUL_OVERFLOW:
+               GET_CR_BIT(3, reg);
+               break;
+
+       case SLJIT_C_NOT_OVERFLOW:
+       case SLJIT_C_MUL_NOT_OVERFLOW:
+               GET_CR_BIT(3, reg);
+               INVERT_BIT(reg);
+               break;
+
+       case SLJIT_C_FLOAT_EQUAL:
+               GET_CR_BIT(4 + 2, reg);
+               break;
+
+       case SLJIT_C_FLOAT_NOT_EQUAL:
+               GET_CR_BIT(4 + 2, reg);
+               INVERT_BIT(reg);
+               break;
+
+       case SLJIT_C_FLOAT_NAN:
+               GET_CR_BIT(4 + 3, reg);
+               break;
+
+       case SLJIT_C_FLOAT_NOT_NAN:
+               GET_CR_BIT(4 + 3, reg);
+               INVERT_BIT(reg);
+               break;
+
+       default:
+               SLJIT_ASSERT_STOP();
+               break;
+       }
+
+       if (GET_OPCODE(op) == SLJIT_OR)
+               return emit_op(compiler, GET_OPCODE(op), GET_FLAGS(op) ? ALT_SET_FLAGS : 0, dst, dstw, dst, dstw, TMP_REG2, 0);
+
+       if (reg == TMP_REG2)
+               return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value)
+{
+       struct sljit_const *const_;
+       int reg;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_const(compiler, dst, dstw, init_value);
+
+       const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+       PTR_FAIL_IF(!const_);
+       set_const(const_, compiler);
+
+       reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2;
+
+       PTR_FAIL_IF(emit_const(compiler, reg, init_value));
+
+       if (dst & SLJIT_MEM)
+               PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
+       return const_;
+}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_32.c b/src/3rdparty/pcre/sljit/sljitNativeX86_32.c
new file mode 100644 (file)
index 0000000..68bca84
--- /dev/null
@@ -0,0 +1,517 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+/* x86 32-bit arch dependent functions. */
+
+static int emit_do_imm(struct sljit_compiler *compiler, sljit_ub opcode, sljit_w imm)
+{
+       sljit_ub *buf;
+
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_w));
+       FAIL_IF(!buf);
+       INC_SIZE(1 + sizeof(sljit_w));
+       *buf++ = opcode;
+       *(sljit_w*)buf = imm;
+       return SLJIT_SUCCESS;
+}
+
+static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type)
+{
+       if (type == SLJIT_JUMP) {
+               *code_ptr++ = 0xe9;
+               jump->addr++;
+       }
+       else if (type >= SLJIT_FAST_CALL) {
+               *code_ptr++ = 0xe8;
+               jump->addr++;
+       }
+       else {
+               *code_ptr++ = 0x0f;
+               *code_ptr++ = get_jump_code(type);
+               jump->addr += 2;
+       }
+
+       if (jump->flags & JUMP_LABEL)
+               jump->flags |= PATCH_MW;
+       else
+               *(sljit_w*)code_ptr = jump->u.target - (jump->addr + 4);
+       code_ptr += 4;
+
+       return code_ptr;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       int size;
+       sljit_ub *buf;
+
+       CHECK_ERROR();
+       check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+       compiler->args = args;
+       compiler->flags_saved = 0;
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+       size = 1 + (saveds <= 3 ? saveds : 3) + (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0);
+#else
+       size = 1 + (saveds <= 3 ? saveds : 3) + (args > 0 ? (2 + args * 3) : 0);
+#endif
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
+       FAIL_IF(!buf);
+
+       INC_SIZE(size);
+       PUSH_REG(reg_map[TMP_REGISTER]);
+#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+       if (args > 0) {
+               *buf++ = 0x8b;
+               *buf++ = 0xc4 | (reg_map[TMP_REGISTER] << 3);
+       }
+#endif
+       if (saveds > 2)
+               PUSH_REG(reg_map[SLJIT_SAVED_REG3]);
+       if (saveds > 1)
+               PUSH_REG(reg_map[SLJIT_SAVED_REG2]);
+       if (saveds > 0)
+               PUSH_REG(reg_map[SLJIT_SAVED_REG1]);
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+       if (args > 0) {
+               *buf++ = 0x8b;
+               *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[SLJIT_TEMPORARY_REG3];
+       }
+       if (args > 1) {
+               *buf++ = 0x8b;
+               *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[SLJIT_TEMPORARY_REG2];
+       }
+       if (args > 2) {
+               *buf++ = 0x8b;
+               *buf++ = 0x44 | (reg_map[SLJIT_SAVED_REG3] << 3);
+               *buf++ = 0x24;
+               *buf++ = sizeof(sljit_w) * (3 + 2); /* saveds >= 3 as well. */
+       }
+#else
+       if (args > 0) {
+               *buf++ = 0x8b;
+               *buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[TMP_REGISTER];
+               *buf++ = sizeof(sljit_w) * 2;
+       }
+       if (args > 1) {
+               *buf++ = 0x8b;
+               *buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[TMP_REGISTER];
+               *buf++ = sizeof(sljit_w) * 3;
+       }
+       if (args > 2) {
+               *buf++ = 0x8b;
+               *buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG3] << 3) | reg_map[TMP_REGISTER];
+               *buf++ = sizeof(sljit_w) * 4;
+       }
+#endif
+
+       local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1);
+       compiler->temporaries_start = local_size;
+       if (temporaries > 3)
+               local_size += (temporaries - 3) * sizeof(sljit_uw);
+       compiler->saveds_start = local_size;
+       if (saveds > 3)
+               local_size += (saveds - 3) * sizeof(sljit_uw);
+
+#ifdef _WIN32
+       if (local_size > 1024) {
+               FAIL_IF(emit_do_imm(compiler, 0xb8 + reg_map[SLJIT_TEMPORARY_REG1], local_size));
+               FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_touch_stack)));
+       }
+#endif
+
+       compiler->local_size = local_size;
+       if (local_size > 0)
+               return emit_non_cum_binary(compiler, 0x2b, 0x29, 0x5 << 3, 0x2d,
+                       SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size);
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       CHECK_ERROR_VOID();
+       check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+       compiler->args = args;
+       compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1);
+       compiler->temporaries_start = compiler->local_size;
+       if (temporaries > 3)
+               compiler->local_size += (temporaries - 3) * sizeof(sljit_uw);
+       compiler->saveds_start = compiler->local_size;
+       if (saveds > 3)
+               compiler->local_size += (saveds - 3) * sizeof(sljit_uw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+{
+       int size;
+       sljit_ub *buf;
+
+       CHECK_ERROR();
+       check_sljit_emit_return(compiler, op, src, srcw);
+       SLJIT_ASSERT(compiler->args >= 0);
+
+       compiler->flags_saved = 0;
+       FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+
+       if (compiler->local_size > 0)
+               FAIL_IF(emit_cum_binary(compiler, 0x03, 0x01, 0x0 << 3, 0x05,
+                               SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size));
+
+       size = 2 + (compiler->saveds <= 3 ? compiler->saveds : 3);
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+       if (compiler->args > 2)
+               size += 2;
+#else
+       if (compiler->args > 0)
+               size += 2;
+#endif
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
+       FAIL_IF(!buf);
+
+       INC_SIZE(size);
+
+       if (compiler->saveds > 0)
+               POP_REG(reg_map[SLJIT_SAVED_REG1]);
+       if (compiler->saveds > 1)
+               POP_REG(reg_map[SLJIT_SAVED_REG2]);
+       if (compiler->saveds > 2)
+               POP_REG(reg_map[SLJIT_SAVED_REG3]);
+       POP_REG(reg_map[TMP_REGISTER]);
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+       if (compiler->args > 2)
+               RETN(sizeof(sljit_w));
+       else
+               RET();
+#else
+       if (compiler->args > 0)
+               RETN(compiler->args * sizeof(sljit_w));
+       else
+               RET();
+#endif
+
+       return SLJIT_SUCCESS;
+}
+
+/* --------------------------------------------------------------------- */
+/*  Operators                                                            */
+/* --------------------------------------------------------------------- */
+
+/* Size contains the flags as well. */
+static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
+       /* The register or immediate operand. */
+       int a, sljit_w imma,
+       /* The general operand (not immediate). */
+       int b, sljit_w immb)
+{
+       sljit_ub *buf;
+       sljit_ub *buf_ptr;
+       int flags = size & ~0xf;
+       int inst_size;
+
+       /* Both cannot be switched on. */
+       SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
+       /* Size flags not allowed for typed instructions. */
+       SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);
+       /* Both size flags cannot be switched on. */
+       SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+       /* SSE2 and immediate is not possible. */
+       SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
+#endif
+
+       size &= 0xf;
+       inst_size = size;
+
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+       if (flags & EX86_PREF_F2)
+               inst_size++;
+#endif
+       if (flags & EX86_PREF_66)
+               inst_size++;
+
+       /* Calculate size of b. */
+       inst_size += 1; /* mod r/m byte. */
+       if (b & SLJIT_MEM) {
+               if ((b & 0x0f) == SLJIT_UNUSED)
+                       inst_size += sizeof(sljit_w);
+               else if (immb != 0 && !(b & 0xf0)) {
+                       /* Immediate operand. */
+                       if (immb <= 127 && immb >= -128)
+                               inst_size += sizeof(sljit_b);
+                       else
+                               inst_size += sizeof(sljit_w);
+               }
+
+               if ((b & 0xf) == SLJIT_LOCALS_REG && !(b & 0xf0))
+                       b |= SLJIT_LOCALS_REG << 4;
+
+               if ((b & 0xf0) != SLJIT_UNUSED)
+                       inst_size += 1; /* SIB byte. */
+       }
+
+       /* Calculate size of a. */
+       if (a & SLJIT_IMM) {
+               if (flags & EX86_BIN_INS) {
+                       if (imma <= 127 && imma >= -128) {
+                               inst_size += 1;
+                               flags |= EX86_BYTE_ARG;
+                       } else
+                               inst_size += 4;
+               }
+               else if (flags & EX86_SHIFT_INS) {
+                       imma &= 0x1f;
+                       if (imma != 1) {
+                               inst_size ++;
+                               flags |= EX86_BYTE_ARG;
+                       }
+               } else if (flags & EX86_BYTE_ARG)
+                       inst_size++;
+               else if (flags & EX86_HALF_ARG)
+                       inst_size += sizeof(short);
+               else
+                       inst_size += sizeof(sljit_w);
+       }
+       else
+               SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
+
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
+       PTR_FAIL_IF(!buf);
+
+       /* Encoding the byte. */
+       INC_SIZE(inst_size);
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+       if (flags & EX86_PREF_F2)
+               *buf++ = 0xf2;
+#endif
+       if (flags & EX86_PREF_66)
+               *buf++ = 0x66;
+
+       buf_ptr = buf + size;
+
+       /* Encode mod/rm byte. */
+       if (!(flags & EX86_SHIFT_INS)) {
+               if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
+                       *buf = (flags & EX86_BYTE_ARG) ? 0x83 : 0x81;
+
+               if ((a & SLJIT_IMM) || (a == 0))
+                       *buf_ptr = 0;
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+               else if (!(flags & EX86_SSE2))
+                       *buf_ptr = reg_map[a] << 3;
+               else
+                       *buf_ptr = a << 3;
+#else
+               else
+                       *buf_ptr = reg_map[a] << 3;
+#endif
+       }
+       else {
+               if (a & SLJIT_IMM) {
+                       if (imma == 1)
+                               *buf = 0xd1;
+                       else
+                               *buf = 0xc1;
+               } else
+                       *buf = 0xd3;
+               *buf_ptr = 0;
+       }
+
+       if (!(b & SLJIT_MEM))
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+               *buf_ptr++ |= 0xc0 + ((!(flags & EX86_SSE2)) ? reg_map[b] : b);
+#else
+               *buf_ptr++ |= 0xc0 + reg_map[b];
+#endif
+       else if ((b & 0x0f) != SLJIT_UNUSED) {
+               if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) {
+                       if (immb != 0) {
+                               if (immb <= 127 && immb >= -128)
+                                       *buf_ptr |= 0x40;
+                               else
+                                       *buf_ptr |= 0x80;
+                       }
+
+                       if ((b & 0xf0) == SLJIT_UNUSED)
+                               *buf_ptr++ |= reg_map[b & 0x0f];
+                       else {
+                               *buf_ptr++ |= 0x04;
+                               *buf_ptr++ = reg_map[b & 0x0f] | (reg_map[(b >> 4) & 0x0f] << 3);
+                       }
+
+                       if (immb != 0) {
+                               if (immb <= 127 && immb >= -128)
+                                       *buf_ptr++ = immb; /* 8 bit displacement. */
+                               else {
+                                       *(sljit_w*)buf_ptr = immb; /* 32 bit displacement. */
+                                       buf_ptr += sizeof(sljit_w);
+                               }
+                       }
+               }
+               else {
+                       *buf_ptr++ |= 0x04;
+                       *buf_ptr++ = reg_map[b & 0x0f] | (reg_map[(b >> 4) & 0x0f] << 3) | (immb << 6);
+               }
+       }
+       else {
+               *buf_ptr++ |= 0x05;
+               *(sljit_w*)buf_ptr = immb; /* 32 bit displacement. */
+               buf_ptr += sizeof(sljit_w);
+       }
+
+       if (a & SLJIT_IMM) {
+               if (flags & EX86_BYTE_ARG)
+                       *buf_ptr = imma;
+               else if (flags & EX86_HALF_ARG)
+                       *(short*)buf_ptr = imma;
+               else if (!(flags & EX86_SHIFT_INS))
+                       *(sljit_w*)buf_ptr = imma;
+       }
+
+       return !(flags & EX86_SHIFT_INS) ? buf : (buf + 1);
+}
+
+/* --------------------------------------------------------------------- */
+/*  Call / return instructions                                           */
+/* --------------------------------------------------------------------- */
+
+static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type)
+{
+       sljit_ub *buf;
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+       buf = (sljit_ub*)ensure_buf(compiler, type >= SLJIT_CALL3 ? 1 + 2 + 1 : 1 + 2);
+       FAIL_IF(!buf);
+       INC_SIZE(type >= SLJIT_CALL3 ? 2 + 1 : 2);
+
+       if (type >= SLJIT_CALL3)
+               PUSH_REG(reg_map[SLJIT_TEMPORARY_REG3]);
+       *buf++ = 0x8b;
+       *buf++ = 0xc0 | (reg_map[SLJIT_TEMPORARY_REG3] << 3) | reg_map[SLJIT_TEMPORARY_REG1];
+#else
+       buf = (sljit_ub*)ensure_buf(compiler, type - SLJIT_CALL0 + 1);
+       FAIL_IF(!buf);
+       INC_SIZE(type - SLJIT_CALL0);
+       if (type >= SLJIT_CALL3)
+               PUSH_REG(reg_map[SLJIT_TEMPORARY_REG3]);
+       if (type >= SLJIT_CALL2)
+               PUSH_REG(reg_map[SLJIT_TEMPORARY_REG2]);
+       PUSH_REG(reg_map[SLJIT_TEMPORARY_REG1]);
+#endif
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
+{
+       sljit_ub *buf;
+
+       CHECK_ERROR();
+       check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+       compiler->args = args;
+       compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1);
+       compiler->temporaries_start = compiler->local_size;
+       if (temporaries > 3)
+               compiler->local_size += (temporaries - 3) * sizeof(sljit_uw);
+       compiler->saveds_start = compiler->local_size;
+       if (saveds > 3)
+               compiler->local_size += (saveds - 3) * sizeof(sljit_uw);
+
+       CHECK_EXTRA_REGS(dst, dstw, (void)0);
+
+       if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+               FAIL_IF(!buf);
+
+               INC_SIZE(1);
+               POP_REG(reg_map[dst]);
+               return SLJIT_SUCCESS;
+       }
+       else if (dst & SLJIT_MEM) {
+               buf = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+               FAIL_IF(!buf);
+               *buf++ = 0x8f;
+               return SLJIT_SUCCESS;
+       }
+
+       /* For UNUSED dst. Uncommon, but possible. */
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+       FAIL_IF(!buf);
+
+       INC_SIZE(1);
+       POP_REG(reg_map[TMP_REGISTER]);
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+{
+       sljit_ub *buf;
+
+       CHECK_ERROR();
+       check_sljit_emit_fast_return(compiler, src, srcw);
+
+       CHECK_EXTRA_REGS(src, srcw, (void)0);
+
+       if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) {
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
+               FAIL_IF(!buf);
+
+               INC_SIZE(1 + 1);
+               PUSH_REG(reg_map[src]);
+       }
+       else if (src & SLJIT_MEM) {
+               buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
+               FAIL_IF(!buf);
+               *buf++ = 0xff;
+               *buf |= 6 << 3;
+
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+               FAIL_IF(!buf);
+               INC_SIZE(1);
+       }
+       else {
+               /* SLJIT_IMM. */
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
+               FAIL_IF(!buf);
+
+               INC_SIZE(5 + 1);
+               *buf++ = 0x68;
+               *(sljit_w*)buf = srcw;
+               buf += sizeof(sljit_w);
+       }
+
+       RET();
+       return SLJIT_SUCCESS;
+}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_64.c b/src/3rdparty/pcre/sljit/sljitNativeX86_64.c
new file mode 100644 (file)
index 0000000..40d875b
--- /dev/null
@@ -0,0 +1,842 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+/* x86 64-bit arch dependent functions. */
+
+static int emit_load_imm64(struct sljit_compiler *compiler, int reg, sljit_w imm)
+{
+       sljit_ub *buf;
+
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_w));
+       FAIL_IF(!buf);
+       INC_SIZE(2 + sizeof(sljit_w));
+       *buf++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);
+       *buf++ = 0xb8 + (reg_map[reg] & 0x7);
+       *(sljit_w*)buf = imm;
+       return SLJIT_SUCCESS;
+}
+
+static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type)
+{
+       if (type < SLJIT_JUMP) {
+               *code_ptr++ = get_jump_code(type ^ 0x1) - 0x10;
+               *code_ptr++ = 10 + 3;
+       }
+
+       SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_first);
+       *code_ptr++ = REX_W | REX_B;
+       *code_ptr++ = 0xb8 + 1;
+       jump->addr = (sljit_uw)code_ptr;
+
+       if (jump->flags & JUMP_LABEL)
+               jump->flags |= PATCH_MD;
+       else
+               *(sljit_w*)code_ptr = jump->u.target;
+
+       code_ptr += sizeof(sljit_w);
+       *code_ptr++ = REX_B;
+       *code_ptr++ = 0xff;
+       *code_ptr++ = (type >= SLJIT_FAST_CALL) ? 0xd1 /* call */ : 0xe1 /* jmp */;
+
+       return code_ptr;
+}
+
+static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_w addr, int type)
+{
+       sljit_w delta = addr - ((sljit_w)code_ptr + 1 + sizeof(sljit_hw));
+
+       if (delta <= SLJIT_W(0x7fffffff) && delta >= SLJIT_W(-0x80000000)) {
+               *code_ptr++ = (type == 2) ? 0xe8 /* call */ : 0xe9 /* jmp */;
+               *(sljit_w*)code_ptr = delta;
+       }
+       else {
+               SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_second);
+               *code_ptr++ = REX_W | REX_B;
+               *code_ptr++ = 0xb8 + 1;
+               *(sljit_w*)code_ptr = addr;
+               code_ptr += sizeof(sljit_w);
+               *code_ptr++ = REX_B;
+               *code_ptr++ = 0xff;
+               *code_ptr++ = (type == 2) ? 0xd1 /* call */ : 0xe1 /* jmp */;
+       }
+
+       return code_ptr;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       int size, pushed_size;
+       sljit_ub *buf;
+
+       CHECK_ERROR();
+       check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+       compiler->flags_saved = 0;
+
+       size = saveds;
+       /* Including the return address saved by the call instruction. */
+       pushed_size = (saveds + 1) * sizeof(sljit_w);
+#ifndef _WIN64
+       if (saveds >= 2)
+               size += saveds - 1;
+#else
+       /* Saving the virtual stack pointer. */
+       compiler->has_locals = local_size > 0;
+       if (local_size > 0) {
+               size += 2;
+               pushed_size += sizeof(sljit_w);
+       }
+       if (saveds >= 4)
+               size += saveds - 3;
+       if (temporaries >= 5) {
+               size += (5 - 4) * 2;
+               pushed_size += sizeof(sljit_w);
+       }
+#endif
+       size += args * 3;
+       if (size > 0) {
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
+               FAIL_IF(!buf);
+
+               INC_SIZE(size);
+               if (saveds >= 5) {
+                       SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG2] >= 8, saved_ereg2_is_hireg);
+                       *buf++ = REX_B;
+                       PUSH_REG(reg_lmap[SLJIT_SAVED_EREG2]);
+               }
+               if (saveds >= 4) {
+                       SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG1] >= 8, saved_ereg1_is_hireg);
+                       *buf++ = REX_B;
+                       PUSH_REG(reg_lmap[SLJIT_SAVED_EREG1]);
+               }
+               if (saveds >= 3) {
+#ifndef _WIN64
+                       SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] >= 8, saved_reg3_is_hireg);
+                       *buf++ = REX_B;
+#else
+                       SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] < 8, saved_reg3_is_loreg);
+#endif
+                       PUSH_REG(reg_lmap[SLJIT_SAVED_REG3]);
+               }
+               if (saveds >= 2) {
+#ifndef _WIN64
+                       SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] >= 8, saved_reg2_is_hireg);
+                       *buf++ = REX_B;
+#else
+                       SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] < 8, saved_reg2_is_loreg);
+#endif
+                       PUSH_REG(reg_lmap[SLJIT_SAVED_REG2]);
+               }
+               if (saveds >= 1) {
+                       SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG1] < 8, saved_reg1_is_loreg);
+                       PUSH_REG(reg_lmap[SLJIT_SAVED_REG1]);
+               }
+#ifdef _WIN64
+               if (temporaries >= 5) {
+                       SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_EREG2] >= 8, temporary_ereg2_is_hireg);
+                       *buf++ = REX_B;
+                       PUSH_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
+               }
+               if (local_size > 0) {
+                       SLJIT_COMPILE_ASSERT(reg_map[SLJIT_LOCALS_REG] >= 8, locals_reg_is_hireg);
+                       *buf++ = REX_B;
+                       PUSH_REG(reg_lmap[SLJIT_LOCALS_REG]);
+               }
+#endif
+
+#ifndef _WIN64
+               if (args > 0) {
+                       *buf++ = REX_W;
+                       *buf++ = 0x8b;
+                       *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x7;
+               }
+               if (args > 1) {
+                       *buf++ = REX_W | REX_R;
+                       *buf++ = 0x8b;
+                       *buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG2] << 3) | 0x6;
+               }
+               if (args > 2) {
+                       *buf++ = REX_W | REX_R;
+                       *buf++ = 0x8b;
+                       *buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG3] << 3) | 0x2;
+               }
+#else
+               if (args > 0) {
+                       *buf++ = REX_W;
+                       *buf++ = 0x8b;
+                       *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x1;
+               }
+               if (args > 1) {
+                       *buf++ = REX_W;
+                       *buf++ = 0x8b;
+                       *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG2] << 3) | 0x2;
+               }
+               if (args > 2) {
+                       *buf++ = REX_W | REX_B;
+                       *buf++ = 0x8b;
+                       *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x0;
+               }
+#endif
+       }
+
+       local_size = ((local_size + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
+#ifdef _WIN64
+       local_size += 4 * sizeof(sljit_w);
+       compiler->local_size = local_size;
+       if (local_size > 1024) {
+               /* Allocate the stack for the function itself. */
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+               FAIL_IF(!buf);
+               INC_SIZE(4);
+               *buf++ = REX_W;
+               *buf++ = 0x83;
+               *buf++ = 0xc0 | (5 << 3) | 4;
+               /* Pushed size must be divisible by 8. */
+               SLJIT_ASSERT(!(pushed_size & 0x7));
+               if (pushed_size & 0x8) {
+                       *buf++ = 5 * sizeof(sljit_w);
+                       local_size -= 5 * sizeof(sljit_w);
+               } else {
+                       *buf++ = 4 * sizeof(sljit_w);
+                       local_size -= 4 * sizeof(sljit_w);
+               }
+               FAIL_IF(emit_load_imm64(compiler, SLJIT_TEMPORARY_REG1, local_size));
+               FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_touch_stack)));
+       }
+#else
+       compiler->local_size = local_size;
+       if (local_size > 0) {
+#endif
+               /* In case of Win64, local_size is always > 4 * sizeof(sljit_w) */
+               if (local_size <= 127) {
+                       buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+                       FAIL_IF(!buf);
+                       INC_SIZE(4);
+                       *buf++ = REX_W;
+                       *buf++ = 0x83;
+                       *buf++ = 0xc0 | (5 << 3) | 4;
+                       *buf++ = local_size;
+               }
+               else {
+                       buf = (sljit_ub*)ensure_buf(compiler, 1 + 7);
+                       FAIL_IF(!buf);
+                       INC_SIZE(7);
+                       *buf++ = REX_W;
+                       *buf++ = 0x81;
+                       *buf++ = 0xc0 | (5 << 3) | 4;
+                       *(sljit_hw*)buf = local_size;
+                       buf += sizeof(sljit_hw);
+               }
+#ifndef _WIN64
+       }
+#endif
+
+#ifdef _WIN64
+       if (compiler->has_locals) {
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 5);
+               FAIL_IF(!buf);
+               INC_SIZE(5);
+               *buf++ = REX_W | REX_R;
+               *buf++ = 0x8d;
+               *buf++ = 0x40 | (reg_lmap[SLJIT_LOCALS_REG] << 3) | 0x4;
+               *buf++ = 0x24;
+               *buf = 4 * sizeof(sljit_w);
+       }
+#endif
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
+{
+       int pushed_size;
+
+       CHECK_ERROR_VOID();
+       check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+       /* Including the return address saved by the call instruction. */
+       pushed_size = (saveds + 1) * sizeof(sljit_w);
+#ifdef _WIN64
+       compiler->has_locals = local_size > 0;
+       if (local_size > 0)
+               pushed_size += sizeof(sljit_w);
+       if (temporaries >= 5)
+               pushed_size += sizeof(sljit_w);
+#endif
+       compiler->local_size = ((local_size + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
+#ifdef _WIN64
+       compiler->local_size += 4 * sizeof(sljit_w);
+#endif
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
+{
+       int size;
+       sljit_ub *buf;
+
+       CHECK_ERROR();
+       check_sljit_emit_return(compiler, op, src, srcw);
+
+       compiler->flags_saved = 0;
+       FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+
+       if (compiler->local_size > 0) {
+               if (compiler->local_size <= 127) {
+                       buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+                       FAIL_IF(!buf);
+                       INC_SIZE(4);
+                       *buf++ = REX_W;
+                       *buf++ = 0x83;
+                       *buf++ = 0xc0 | (0 << 3) | 4;
+                       *buf = compiler->local_size;
+               }
+               else {
+                       buf = (sljit_ub*)ensure_buf(compiler, 1 + 7);
+                       FAIL_IF(!buf);
+                       INC_SIZE(7);
+                       *buf++ = REX_W;
+                       *buf++ = 0x81;
+                       *buf++ = 0xc0 | (0 << 3) | 4;
+                       *(sljit_hw*)buf = compiler->local_size;
+               }
+       }
+
+       size = 1 + compiler->saveds;
+#ifndef _WIN64
+       if (compiler->saveds >= 2)
+               size += compiler->saveds - 1;
+#else
+       if (compiler->has_locals)
+               size += 2;
+       if (compiler->saveds >= 4)
+               size += compiler->saveds - 3;
+       if (compiler->temporaries >= 5)
+               size += (5 - 4) * 2;
+#endif
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
+       FAIL_IF(!buf);
+
+       INC_SIZE(size);
+
+#ifdef _WIN64
+       if (compiler->has_locals) {
+               *buf++ = REX_B;
+               POP_REG(reg_lmap[SLJIT_LOCALS_REG]);
+       }
+       if (compiler->temporaries >= 5) {
+               *buf++ = REX_B;
+               POP_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
+       }
+#endif
+       if (compiler->saveds >= 1)
+               POP_REG(reg_map[SLJIT_SAVED_REG1]);
+       if (compiler->saveds >= 2) {
+#ifndef _WIN64
+               *buf++ = REX_B;
+#endif
+               POP_REG(reg_lmap[SLJIT_SAVED_REG2]);
+       }
+       if (compiler->saveds >= 3) {
+#ifndef _WIN64
+               *buf++ = REX_B;
+#endif
+               POP_REG(reg_lmap[SLJIT_SAVED_REG3]);
+       }
+       if (compiler->saveds >= 4) {
+               *buf++ = REX_B;
+               POP_REG(reg_lmap[SLJIT_SAVED_EREG1]);
+       }
+       if (compiler->saveds >= 5) {
+               *buf++ = REX_B;
+               POP_REG(reg_lmap[SLJIT_SAVED_EREG2]);
+       }
+
+       RET();
+       return SLJIT_SUCCESS;
+}
+
+/* --------------------------------------------------------------------- */
+/*  Operators                                                            */
+/* --------------------------------------------------------------------- */
+
+static int emit_do_imm32(struct sljit_compiler *compiler, sljit_ub rex, sljit_ub opcode, sljit_w imm)
+{
+       sljit_ub *buf;
+
+       if (rex != 0) {
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_hw));
+               FAIL_IF(!buf);
+               INC_SIZE(2 + sizeof(sljit_hw));
+               *buf++ = rex;
+               *buf++ = opcode;
+               *(sljit_hw*)buf = imm;
+       }
+       else {
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_hw));
+               FAIL_IF(!buf);
+               INC_SIZE(1 + sizeof(sljit_hw));
+               *buf++ = opcode;
+               *(sljit_hw*)buf = imm;
+       }
+       return SLJIT_SUCCESS;
+}
+
+static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
+       /* The register or immediate operand. */
+       int a, sljit_w imma,
+       /* The general operand (not immediate). */
+       int b, sljit_w immb)
+{
+       sljit_ub *buf;
+       sljit_ub *buf_ptr;
+       sljit_ub rex = 0;
+       int flags = size & ~0xf;
+       int inst_size;
+
+       /* The immediate operand must be 32 bit. */
+       SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma));
+       /* Both cannot be switched on. */
+       SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
+       /* Size flags not allowed for typed instructions. */
+       SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);
+       /* Both size flags cannot be switched on. */
+       SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+       /* SSE2 and immediate is not possible. */
+       SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
+#endif
+
+       size &= 0xf;
+       inst_size = size;
+
+       if ((b & SLJIT_MEM) && !(b & 0xf0) && NOT_HALFWORD(immb)) {
+               if (emit_load_imm64(compiler, TMP_REG3, immb))
+                       return NULL;
+               immb = 0;
+               if (b & 0xf)
+                       b |= TMP_REG3 << 4;
+               else
+                       b |= TMP_REG3;
+       }
+
+       if (!compiler->mode32 && !(flags & EX86_NO_REXW))
+               rex |= REX_W;
+       else if (flags & EX86_REX)
+               rex |= REX;
+
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+       if (flags & EX86_PREF_F2)
+               inst_size++;
+#endif
+       if (flags & EX86_PREF_66)
+               inst_size++;
+
+       /* Calculate size of b. */
+       inst_size += 1; /* mod r/m byte. */
+       if (b & SLJIT_MEM) {
+               if ((b & 0x0f) == SLJIT_UNUSED)
+                       inst_size += 1 + sizeof(sljit_hw); /* SIB byte required to avoid RIP based addressing. */
+               else {
+                       if (reg_map[b & 0x0f] >= 8)
+                               rex |= REX_B;
+                       if (immb != 0 && !(b & 0xf0)) {
+                               /* Immediate operand. */
+                               if (immb <= 127 && immb >= -128)
+                                       inst_size += sizeof(sljit_b);
+                               else
+                                       inst_size += sizeof(sljit_hw);
+                       }
+               }
+
+#ifndef _WIN64
+               if ((b & 0xf) == SLJIT_LOCALS_REG && (b & 0xf0) == 0)
+                       b |= SLJIT_LOCALS_REG << 4;
+#endif
+
+               if ((b & 0xf0) != SLJIT_UNUSED) {
+                       inst_size += 1; /* SIB byte. */
+                       if (reg_map[(b >> 4) & 0x0f] >= 8)
+                               rex |= REX_X;
+               }
+       }
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+       else if (!(flags & EX86_SSE2) && reg_map[b] >= 8)
+               rex |= REX_B;
+#else
+       else if (reg_map[b] >= 8)
+               rex |= REX_B;
+#endif
+
+       if (a & SLJIT_IMM) {
+               if (flags & EX86_BIN_INS) {
+                       if (imma <= 127 && imma >= -128) {
+                               inst_size += 1;
+                               flags |= EX86_BYTE_ARG;
+                       } else
+                               inst_size += 4;
+               }
+               else if (flags & EX86_SHIFT_INS) {
+                       imma &= compiler->mode32 ? 0x1f : 0x3f;
+                       if (imma != 1) {
+                               inst_size ++;
+                               flags |= EX86_BYTE_ARG;
+                       }
+               } else if (flags & EX86_BYTE_ARG)
+                       inst_size++;
+               else if (flags & EX86_HALF_ARG)
+                       inst_size += sizeof(short);
+               else
+                       inst_size += sizeof(sljit_hw);
+       }
+       else {
+               SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
+               /* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+               if (!(flags & EX86_SSE2) && reg_map[a] >= 8)
+                       rex |= REX_R;
+#else
+               if (reg_map[a] >= 8)
+                       rex |= REX_R;
+#endif
+       }
+
+       if (rex)
+               inst_size++;
+
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
+       PTR_FAIL_IF(!buf);
+
+       /* Encoding the byte. */
+       INC_SIZE(inst_size);
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+       if (flags & EX86_PREF_F2)
+               *buf++ = 0xf2;
+#endif
+       if (flags & EX86_PREF_66)
+               *buf++ = 0x66;
+       if (rex)
+               *buf++ = rex;
+       buf_ptr = buf + size;
+
+       /* Encode mod/rm byte. */
+       if (!(flags & EX86_SHIFT_INS)) {
+               if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
+                       *buf = (flags & EX86_BYTE_ARG) ? 0x83 : 0x81;
+
+               if ((a & SLJIT_IMM) || (a == 0))
+                       *buf_ptr = 0;
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+               else if (!(flags & EX86_SSE2))
+                       *buf_ptr = reg_lmap[a] << 3;
+               else
+                       *buf_ptr = a << 3;
+#else
+               else
+                       *buf_ptr = reg_lmap[a] << 3;
+#endif
+       }
+       else {
+               if (a & SLJIT_IMM) {
+                       if (imma == 1)
+                               *buf = 0xd1;
+                       else
+                               *buf = 0xc1;
+               } else
+                       *buf = 0xd3;
+               *buf_ptr = 0;
+       }
+
+       if (!(b & SLJIT_MEM))
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+               *buf_ptr++ |= 0xc0 + ((!(flags & EX86_SSE2)) ? reg_lmap[b] : b);
+#else
+               *buf_ptr++ |= 0xc0 + reg_lmap[b];
+#endif
+       else if ((b & 0x0f) != SLJIT_UNUSED) {
+#ifdef _WIN64
+               SLJIT_ASSERT((b & 0xf0) != (SLJIT_LOCALS_REG << 4));
+#endif
+               if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) {
+                       if (immb != 0) {
+                               if (immb <= 127 && immb >= -128)
+                                       *buf_ptr |= 0x40;
+                               else
+                                       *buf_ptr |= 0x80;
+                       }
+
+                       if ((b & 0xf0) == SLJIT_UNUSED)
+                               *buf_ptr++ |= reg_lmap[b & 0x0f];
+                       else {
+                               *buf_ptr++ |= 0x04;
+                               *buf_ptr++ = reg_lmap[b & 0x0f] | (reg_lmap[(b >> 4) & 0x0f] << 3);
+                       }
+
+                       if (immb != 0) {
+                               if (immb <= 127 && immb >= -128)
+                                       *buf_ptr++ = immb; /* 8 bit displacement. */
+                               else {
+                                       *(sljit_hw*)buf_ptr = immb; /* 32 bit displacement. */
+                                       buf_ptr += sizeof(sljit_hw);
+                               }
+                       }
+               }
+               else {
+                       *buf_ptr++ |= 0x04;
+                       *buf_ptr++ = reg_lmap[b & 0x0f] | (reg_lmap[(b >> 4) & 0x0f] << 3) | (immb << 6);
+               }
+       }
+       else {
+               *buf_ptr++ |= 0x04;
+               *buf_ptr++ = 0x25;
+               *(sljit_hw*)buf_ptr = immb; /* 32 bit displacement. */
+               buf_ptr += sizeof(sljit_hw);
+       }
+
+       if (a & SLJIT_IMM) {
+               if (flags & EX86_BYTE_ARG)
+                       *buf_ptr = imma;
+               else if (flags & EX86_HALF_ARG)
+                       *(short*)buf_ptr = imma;
+               else if (!(flags & EX86_SHIFT_INS))
+                       *(sljit_hw*)buf_ptr = imma;
+       }
+
+       return !(flags & EX86_SHIFT_INS) ? buf : (buf + 1);
+}
+
+/* --------------------------------------------------------------------- */
+/*  Call / return instructions                                           */
+/* --------------------------------------------------------------------- */
+
+static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type)
+{
+       sljit_ub *buf;
+
+#ifndef _WIN64
+       SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 6 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8, args_registers);
+
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
+       FAIL_IF(!buf);
+       INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
+       if (type >= SLJIT_CALL3) {
+               *buf++ = REX_W;
+               *buf++ = 0x8b;
+               *buf++ = 0xc0 | (0x2 << 3) | reg_lmap[SLJIT_TEMPORARY_REG3];
+       }
+       *buf++ = REX_W;
+       *buf++ = 0x8b;
+       *buf++ = 0xc0 | (0x7 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1];
+#else
+       SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 2 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8, args_registers);
+
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
+       FAIL_IF(!buf);
+       INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
+       if (type >= SLJIT_CALL3) {
+               *buf++ = REX_W | REX_R;
+               *buf++ = 0x8b;
+               *buf++ = 0xc0 | (0x0 << 3) | reg_lmap[SLJIT_TEMPORARY_REG3];
+       }
+       *buf++ = REX_W;
+       *buf++ = 0x8b;
+       *buf++ = 0xc0 | (0x1 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1];
+#endif
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size)
+{
+       sljit_ub *buf;
+
+       CHECK_ERROR();
+       check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size);
+
+       compiler->temporaries = temporaries;
+       compiler->saveds = saveds;
+       compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1);
+#ifdef _WIN64
+       compiler->local_size += 4 * sizeof(sljit_w);
+#endif
+
+       /* For UNUSED dst. Uncommon, but possible. */
+       if (dst == SLJIT_UNUSED)
+               dst = TMP_REGISTER;
+
+       if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) {
+               if (reg_map[dst] < 8) {
+                       buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+                       FAIL_IF(!buf);
+
+                       INC_SIZE(1);
+                       POP_REG(reg_lmap[dst]);
+               }
+               else {
+                       buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
+                       FAIL_IF(!buf);
+
+                       INC_SIZE(2);
+                       *buf++ = REX_B;
+                       POP_REG(reg_lmap[dst]);
+               }
+       }
+       else if (dst & SLJIT_MEM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+               /* REX_W is not necessary (src is not immediate). */
+               compiler->mode32 = 1;
+#endif
+               buf = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+               FAIL_IF(!buf);
+               *buf++ = 0x8f;
+       }
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
+{
+       sljit_ub *buf;
+
+       CHECK_ERROR();
+       check_sljit_emit_fast_return(compiler, src, srcw);
+
+       CHECK_EXTRA_REGS(src, srcw, (void)0);
+
+       if ((src & SLJIT_IMM) && NOT_HALFWORD(srcw)) {
+               FAIL_IF(emit_load_imm64(compiler, TMP_REGISTER, srcw));
+               src = TMP_REGISTER;
+       }
+
+       if (src >= SLJIT_TEMPORARY_REG1 && src <= TMP_REGISTER) {
+               if (reg_map[src] < 8) {
+                       buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
+                       FAIL_IF(!buf);
+
+                       INC_SIZE(1 + 1);
+                       PUSH_REG(reg_lmap[src]);
+               }
+               else {
+                       buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 1);
+                       FAIL_IF(!buf);
+
+                       INC_SIZE(2 + 1);
+                       *buf++ = REX_B;
+                       PUSH_REG(reg_lmap[src]);
+               }
+       }
+       else if (src & SLJIT_MEM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+               /* REX_W is not necessary (src is not immediate). */
+               compiler->mode32 = 1;
+#endif
+               buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
+               FAIL_IF(!buf);
+               *buf++ = 0xff;
+               *buf |= 6 << 3;
+
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+               FAIL_IF(!buf);
+               INC_SIZE(1);
+       }
+       else {
+               SLJIT_ASSERT(IS_HALFWORD(srcw));
+               /* SLJIT_IMM. */
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
+               FAIL_IF(!buf);
+
+               INC_SIZE(5 + 1);
+               *buf++ = 0x68;
+               *(sljit_hw*)buf = srcw;
+               buf += sizeof(sljit_hw);
+       }
+
+       RET();
+       return SLJIT_SUCCESS;
+}
+
+
+/* --------------------------------------------------------------------- */
+/*  Extend input                                                         */
+/* --------------------------------------------------------------------- */
+
+static int emit_mov_int(struct sljit_compiler *compiler, int sign,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       sljit_ub* code;
+       int dst_r;
+
+       compiler->mode32 = 0;
+
+       if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM))
+               return SLJIT_SUCCESS; /* Empty instruction. */
+
+       if (src & SLJIT_IMM) {
+               if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+                       if (sign || ((sljit_uw)srcw <= 0x7fffffff)) {
+                               code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw);
+                               FAIL_IF(!code);
+                               *code = 0xc7;
+                               return SLJIT_SUCCESS;
+                       }
+                       return emit_load_imm64(compiler, dst, srcw);
+               }
+               compiler->mode32 = 1;
+               code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw);
+               FAIL_IF(!code);
+               *code = 0xc7;
+               compiler->mode32 = 0;
+               return SLJIT_SUCCESS;
+       }
+
+       dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_SAVED_REG3) ? dst : TMP_REGISTER;
+
+       if ((dst & SLJIT_MEM) && (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_SAVED_REG3))
+               dst_r = src;
+       else {
+               if (sign) {
+                       code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
+                       FAIL_IF(!code);
+                       *code++ = 0x63;
+               } else {
+                       compiler->mode32 = 1;
+                       FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw));
+                       compiler->mode32 = 0;
+               }
+       }
+
+       if (dst & SLJIT_MEM) {
+               compiler->mode32 = 1;
+               code = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
+               FAIL_IF(!code);
+               *code = 0x89;
+               compiler->mode32 = 0;
+       }
+
+       return SLJIT_SUCCESS;
+}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
new file mode 100644 (file)
index 0000000..0a44163
--- /dev/null
@@ -0,0 +1,2858 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name()
+{
+       return "x86" SLJIT_CPUINFO;
+}
+
+/*
+   32b register indexes:
+     0 - EAX
+     1 - ECX
+     2 - EDX
+     3 - EBX
+     4 - none
+     5 - EBP
+     6 - ESI
+     7 - EDI
+*/
+
+/*
+   64b register indexes:
+     0 - RAX
+     1 - RCX
+     2 - RDX
+     3 - RBX
+     4 - none
+     5 - RBP
+     6 - RSI
+     7 - RDI
+     8 - R8   - From now on REX prefix is required
+     9 - R9
+    10 - R10
+    11 - R11
+    12 - R12
+    13 - R13
+    14 - R14
+    15 - R15
+*/
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+
+/* Last register + 1. */
+#define TMP_REGISTER   (SLJIT_NO_REGISTERS + 1)
+
+static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 2] = {
+  0, 0, 2, 1, 0, 0, 3, 6, 7, 0, 0, 4, 5
+};
+
+#define CHECK_EXTRA_REGS(p, w, do) \
+       if (p >= SLJIT_TEMPORARY_EREG1 && p <= SLJIT_TEMPORARY_EREG2) { \
+               w = compiler->temporaries_start + (p - SLJIT_TEMPORARY_EREG1) * sizeof(sljit_w); \
+               p = SLJIT_MEM1(SLJIT_LOCALS_REG); \
+               do; \
+       } \
+       else if (p >= SLJIT_SAVED_EREG1 && p <= SLJIT_SAVED_EREG2) { \
+               w = compiler->saveds_start + (p - SLJIT_SAVED_EREG1) * sizeof(sljit_w); \
+               p = SLJIT_MEM1(SLJIT_LOCALS_REG); \
+               do; \
+       }
+
+#else /* SLJIT_CONFIG_X86_32 */
+
+/* Last register + 1. */
+#define TMP_REGISTER   (SLJIT_NO_REGISTERS + 1)
+#define TMP_REG2       (SLJIT_NO_REGISTERS + 2)
+#define TMP_REG3       (SLJIT_NO_REGISTERS + 3)
+
+/* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present
+   Note: avoid to use r12 and r13 for memory addessing
+   therefore r12 is better for SAVED_EREG than SAVED_REG. */
+#ifndef _WIN64
+/* 1st passed in rdi, 2nd argument passed in rsi, 3rd in rdx. */
+static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
+  0, 0, 6, 1, 8, 11, 3, 15, 14, 13, 12, 4, 2, 7, 9
+};
+/* low-map. reg_map & 0x7. */
+static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = {
+  0, 0, 6, 1, 0, 3,  3, 7,  6,  5,  4,  4, 2, 7, 1
+};
+#else
+/* 1st passed in rcx, 2nd argument passed in rdx, 3rd in r8. */
+static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
+  0, 0, 2, 1, 11, 13, 3, 6, 7, 14, 12, 15, 10, 8, 9
+};
+/* low-map. reg_map & 0x7. */
+static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = {
+  0, 0, 2, 1, 3,  5,  3, 6, 7,  6,  4,  7, 2,  0, 1
+};
+#endif
+
+#define REX_W          0x48
+#define REX_R          0x44
+#define REX_X          0x42
+#define REX_B          0x41
+#define REX            0x40
+
+typedef unsigned int sljit_uhw;
+typedef int sljit_hw;
+
+#define IS_HALFWORD(x)         ((x) <= 0x7fffffffll && (x) >= -0x80000000ll)
+#define NOT_HALFWORD(x)                ((x) > 0x7fffffffll || (x) < -0x80000000ll)
+
+#define CHECK_EXTRA_REGS(p, w, do)
+
+#endif /* SLJIT_CONFIG_X86_32 */
+
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+#define TMP_FREG       (SLJIT_FLOAT_REG4 + 1)
+#endif
+
+/* Size flags for emit_x86_instruction: */
+#define EX86_BIN_INS           0x0010
+#define EX86_SHIFT_INS         0x0020
+#define EX86_REX               0x0040
+#define EX86_NO_REXW           0x0080
+#define EX86_BYTE_ARG          0x0100
+#define EX86_HALF_ARG          0x0200
+#define EX86_PREF_66           0x0400
+
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+#define EX86_PREF_F2           0x0800
+#define EX86_SSE2              0x1000
+#endif
+
+#define INC_SIZE(s)                    (*buf++ = (s), compiler->size += (s))
+#define INC_CSIZE(s)                   (*code++ = (s), compiler->size += (s))
+
+#define PUSH_REG(r)                    (*buf++ = (0x50 + (r)))
+#define POP_REG(r)                     (*buf++ = (0x58 + (r)))
+#define RET()                          (*buf++ = (0xc3))
+#define RETN(n)                                (*buf++ = (0xc2), *buf++ = n, *buf++ = 0)
+/* r32, r/m32 */
+#define MOV_RM(mod, reg, rm)           (*buf++ = (0x8b), *buf++ = (mod) << 6 | (reg) << 3 | (rm))
+
+static sljit_ub get_jump_code(int type)
+{
+       switch (type) {
+       case SLJIT_C_EQUAL:
+       case SLJIT_C_FLOAT_EQUAL:
+               return 0x84;
+
+       case SLJIT_C_NOT_EQUAL:
+       case SLJIT_C_FLOAT_NOT_EQUAL:
+               return 0x85;
+
+       case SLJIT_C_LESS:
+       case SLJIT_C_FLOAT_LESS:
+               return 0x82;
+
+       case SLJIT_C_GREATER_EQUAL:
+       case SLJIT_C_FLOAT_GREATER_EQUAL:
+               return 0x83;
+
+       case SLJIT_C_GREATER:
+       case SLJIT_C_FLOAT_GREATER:
+               return 0x87;
+
+       case SLJIT_C_LESS_EQUAL:
+       case SLJIT_C_FLOAT_LESS_EQUAL:
+               return 0x86;
+
+       case SLJIT_C_SIG_LESS:
+               return 0x8c;
+
+       case SLJIT_C_SIG_GREATER_EQUAL:
+               return 0x8d;
+
+       case SLJIT_C_SIG_GREATER:
+               return 0x8f;
+
+       case SLJIT_C_SIG_LESS_EQUAL:
+               return 0x8e;
+
+       case SLJIT_C_OVERFLOW:
+       case SLJIT_C_MUL_OVERFLOW:
+               return 0x80;
+
+       case SLJIT_C_NOT_OVERFLOW:
+       case SLJIT_C_MUL_NOT_OVERFLOW:
+               return 0x81;
+
+       case SLJIT_C_FLOAT_NAN:
+               return 0x8a;
+
+       case SLJIT_C_FLOAT_NOT_NAN:
+               return 0x8b;
+       }
+       return 0;
+}
+
+static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_w addr, int type);
+#endif
+
+static sljit_ub* generate_near_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_ub *code, int type)
+{
+       int short_jump;
+       sljit_uw label_addr;
+
+       if (jump->flags & JUMP_LABEL)
+               label_addr = (sljit_uw)(code + jump->u.label->size);
+       else
+               label_addr = jump->u.target;
+       short_jump = (sljit_w)(label_addr - (jump->addr + 2)) >= -128 && (sljit_w)(label_addr - (jump->addr + 2)) <= 127;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       if ((sljit_w)(label_addr - (jump->addr + 1)) > 0x7fffffffll || (sljit_w)(label_addr - (jump->addr + 1)) < -0x80000000ll)
+               return generate_far_jump_code(jump, code_ptr, type);
+#endif
+
+       if (type == SLJIT_JUMP) {
+               if (short_jump)
+                       *code_ptr++ = 0xeb;
+               else
+                       *code_ptr++ = 0xe9;
+               jump->addr++;
+       }
+       else if (type >= SLJIT_FAST_CALL) {
+               short_jump = 0;
+               *code_ptr++ = 0xe8;
+               jump->addr++;
+       }
+       else if (short_jump) {
+               *code_ptr++ = get_jump_code(type) - 0x10;
+               jump->addr++;
+       }
+       else {
+               *code_ptr++ = 0x0f;
+               *code_ptr++ = get_jump_code(type);
+               jump->addr += 2;
+       }
+
+       if (short_jump) {
+               jump->flags |= PATCH_MB;
+               code_ptr += sizeof(sljit_b);
+       } else {
+               jump->flags |= PATCH_MW;
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+               code_ptr += sizeof(sljit_w);
+#else
+               code_ptr += sizeof(sljit_hw);
+#endif
+       }
+
+       return code_ptr;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
+{
+       struct sljit_memory_fragment *buf;
+       sljit_ub *code;
+       sljit_ub *code_ptr;
+       sljit_ub *buf_ptr;
+       sljit_ub *buf_end;
+       sljit_ub len;
+
+       struct sljit_label *label;
+       struct sljit_jump *jump;
+       struct sljit_const *const_;
+
+       CHECK_ERROR_PTR();
+       check_sljit_generate_code(compiler);
+       reverse_buf(compiler);
+
+       /* Second code generation pass. */
+       code = (sljit_ub*)SLJIT_MALLOC_EXEC(compiler->size);
+       PTR_FAIL_WITH_EXEC_IF(code);
+       buf = compiler->buf;
+
+       code_ptr = code;
+       label = compiler->labels;
+       jump = compiler->jumps;
+       const_ = compiler->consts;
+       do {
+               buf_ptr = buf->memory;
+               buf_end = buf_ptr + buf->used_size;
+               do {
+                       len = *buf_ptr++;
+                       if (len > 0) {
+                               /* The code is already generated. */
+                               SLJIT_MEMMOVE(code_ptr, buf_ptr, len);
+                               code_ptr += len;
+                               buf_ptr += len;
+                       }
+                       else {
+                               if (*buf_ptr >= 4) {
+                                       jump->addr = (sljit_uw)code_ptr;
+                                       if (!(jump->flags & SLJIT_REWRITABLE_JUMP))
+                                               code_ptr = generate_near_jump_code(jump, code_ptr, code, *buf_ptr - 4);
+                                       else
+                                               code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 4);
+                                       jump = jump->next;
+                               }
+                               else if (*buf_ptr == 0) {
+                                       label->addr = (sljit_uw)code_ptr;
+                                       label->size = code_ptr - code;
+                                       label = label->next;
+                               }
+                               else if (*buf_ptr == 1) {
+                                       const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_w);
+                                       const_ = const_->next;
+                               }
+                               else {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+                                       *code_ptr++ = (*buf_ptr == 2) ? 0xe8 /* call */ : 0xe9 /* jmp */;
+                                       buf_ptr++;
+                                       *(sljit_w*)code_ptr = *(sljit_w*)buf_ptr - ((sljit_w)code_ptr + sizeof(sljit_w));
+                                       code_ptr += sizeof(sljit_w);
+                                       buf_ptr += sizeof(sljit_w) - 1;
+#else
+                                       code_ptr = generate_fixed_jump(code_ptr, *(sljit_w*)(buf_ptr + 1), *buf_ptr);
+                                       buf_ptr += sizeof(sljit_w);
+#endif
+                               }
+                               buf_ptr++;
+                       }
+               } while (buf_ptr < buf_end);
+               SLJIT_ASSERT(buf_ptr == buf_end);
+               buf = buf->next;
+       } while (buf);
+
+       SLJIT_ASSERT(!label);
+       SLJIT_ASSERT(!jump);
+       SLJIT_ASSERT(!const_);
+
+       jump = compiler->jumps;
+       while (jump) {
+               if (jump->flags & PATCH_MB) {
+                       SLJIT_ASSERT((sljit_w)(jump->u.label->addr - (jump->addr + sizeof(sljit_b))) >= -128 && (sljit_w)(jump->u.label->addr - (jump->addr + sizeof(sljit_b))) <= 127);
+                       *(sljit_ub*)jump->addr = (sljit_ub)(jump->u.label->addr - (jump->addr + sizeof(sljit_b)));
+               } else if (jump->flags & PATCH_MW) {
+                       if (jump->flags & JUMP_LABEL) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+                               *(sljit_w*)jump->addr = (sljit_w)(jump->u.label->addr - (jump->addr + sizeof(sljit_w)));
+#else
+                               SLJIT_ASSERT((sljit_w)(jump->u.label->addr - (jump->addr + sizeof(sljit_hw))) >= -0x80000000ll && (sljit_w)(jump->u.label->addr - (jump->addr + sizeof(sljit_hw))) <= 0x7fffffffll);
+                               *(sljit_hw*)jump->addr = (sljit_hw)(jump->u.label->addr - (jump->addr + sizeof(sljit_hw)));
+#endif
+                       }
+                       else {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+                               *(sljit_w*)jump->addr = (sljit_w)(jump->u.target - (jump->addr + sizeof(sljit_w)));
+#else
+                               SLJIT_ASSERT((sljit_w)(jump->u.target - (jump->addr + sizeof(sljit_hw))) >= -0x80000000ll && (sljit_w)(jump->u.target - (jump->addr + sizeof(sljit_hw))) <= 0x7fffffffll);
+                               *(sljit_hw*)jump->addr = (sljit_hw)(jump->u.target - (jump->addr + sizeof(sljit_hw)));
+#endif
+                       }
+               }
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+               else if (jump->flags & PATCH_MD)
+                       *(sljit_w*)jump->addr = jump->u.label->addr;
+#endif
+
+               jump = jump->next;
+       }
+
+       /* Maybe we waste some space because of short jumps. */
+       SLJIT_ASSERT(code_ptr <= code + compiler->size);
+       compiler->error = SLJIT_ERR_COMPILED;
+       compiler->executable_size = compiler->size;
+       return (void*)code;
+}
+
+/* --------------------------------------------------------------------- */
+/*  Operators                                                            */
+/* --------------------------------------------------------------------- */
+
+static int emit_cum_binary(struct sljit_compiler *compiler,
+       sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w);
+
+static int emit_non_cum_binary(struct sljit_compiler *compiler,
+       sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w);
+
+static int emit_mov(struct sljit_compiler *compiler,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw);
+
+static SLJIT_INLINE int emit_save_flags(struct sljit_compiler *compiler)
+{
+       sljit_ub *buf;
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + 5);
+       FAIL_IF(!buf);
+       INC_SIZE(5);
+       *buf++ = 0x9c; /* pushfd */
+#else
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + 6);
+       FAIL_IF(!buf);
+       INC_SIZE(6);
+       *buf++ = 0x9c; /* pushfq */
+       *buf++ = 0x48;
+#endif
+       *buf++ = 0x8d; /* lea esp/rsp, [esp/rsp + sizeof(sljit_w)] */
+       *buf++ = 0x64;
+       *buf++ = 0x24;
+       *buf++ = sizeof(sljit_w);
+       compiler->flags_saved = 1;
+       return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE int emit_restore_flags(struct sljit_compiler *compiler, int keep_flags)
+{
+       sljit_ub *buf;
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + 5);
+       FAIL_IF(!buf);
+       INC_SIZE(5);
+#else
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + 6);
+       FAIL_IF(!buf);
+       INC_SIZE(6);
+       *buf++ = 0x48;
+#endif
+       *buf++ = 0x8d; /* lea esp/rsp, [esp/rsp - sizeof(sljit_w)] */
+       *buf++ = 0x64;
+       *buf++ = 0x24;
+       *buf++ = (sljit_ub)-(int)sizeof(sljit_w);
+       *buf++ = 0x9d; /* popfd / popfq */
+       compiler->flags_saved = keep_flags;
+       return SLJIT_SUCCESS;
+}
+
+#ifdef _WIN32
+#include <malloc.h>
+
+static void SLJIT_CALL sljit_touch_stack(sljit_w local_size)
+{
+       /* Workaround for calling _chkstk. */
+       alloca(local_size);
+}
+#endif
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+#include "sljitNativeX86_32.c"
+#else
+#include "sljitNativeX86_64.c"
+#endif
+
+static int emit_mov(struct sljit_compiler *compiler,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       sljit_ub* code;
+
+       if (dst == SLJIT_UNUSED) {
+               /* No destination, doesn't need to setup flags. */
+               if (src & SLJIT_MEM) {
+                       code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src, srcw);
+                       FAIL_IF(!code);
+                       *code = 0x8b;
+               }
+               return SLJIT_SUCCESS;
+       }
+       if (src >= SLJIT_TEMPORARY_REG1 && src <= TMP_REGISTER) {
+               code = emit_x86_instruction(compiler, 1, src, 0, dst, dstw);
+               FAIL_IF(!code);
+               *code = 0x89;
+               return SLJIT_SUCCESS;
+       }
+       if (src & SLJIT_IMM) {
+               if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+                       return emit_do_imm(compiler, 0xb8 + reg_map[dst], srcw);
+#else
+                       if (!compiler->mode32) {
+                               if (NOT_HALFWORD(srcw))
+                                       return emit_load_imm64(compiler, dst, srcw);
+                       }
+                       else
+                               return emit_do_imm32(compiler, (reg_map[dst] >= 8) ? REX_B : 0, 0xb8 + reg_lmap[dst], srcw);
+#endif
+               }
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+               if (!compiler->mode32 && NOT_HALFWORD(srcw)) {
+                       FAIL_IF(emit_load_imm64(compiler, TMP_REG2, srcw));
+                       code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, dst, dstw);
+                       FAIL_IF(!code);
+                       *code = 0x89;
+                       return SLJIT_SUCCESS;
+               }
+#endif
+               code = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, dstw);
+               FAIL_IF(!code);
+               *code = 0xc7;
+               return SLJIT_SUCCESS;
+       }
+       if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) {
+               code = emit_x86_instruction(compiler, 1, dst, 0, src, srcw);
+               FAIL_IF(!code);
+               *code = 0x8b;
+               return SLJIT_SUCCESS;
+       }
+
+       /* Memory to memory move. Requires two instruction. */
+       code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src, srcw);
+       FAIL_IF(!code);
+       *code = 0x8b;
+       code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
+       FAIL_IF(!code);
+       *code = 0x89;
+       return SLJIT_SUCCESS;
+}
+
+#define EMIT_MOV(compiler, dst, dstw, src, srcw) \
+       FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op)
+{
+       sljit_ub *buf;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       int size;
+#endif
+
+       CHECK_ERROR();
+       check_sljit_emit_op0(compiler, op);
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_BREAKPOINT:
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+               FAIL_IF(!buf);
+               INC_SIZE(1);
+               *buf = 0xcc;
+               break;
+       case SLJIT_NOP:
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+               FAIL_IF(!buf);
+               INC_SIZE(1);
+               *buf = 0x90;
+               break;
+       case SLJIT_UMUL:
+       case SLJIT_SMUL:
+       case SLJIT_UDIV:
+       case SLJIT_SDIV:
+               compiler->flags_saved = 0;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+#ifdef _WIN64
+               SLJIT_COMPILE_ASSERT(
+                       reg_map[SLJIT_TEMPORARY_REG1] == 0
+                       && reg_map[SLJIT_TEMPORARY_REG2] == 2
+                       && reg_map[TMP_REGISTER] > 7,
+                       invalid_register_assignment_for_div_mul);
+#else
+               SLJIT_COMPILE_ASSERT(
+                       reg_map[SLJIT_TEMPORARY_REG1] == 0
+                       && reg_map[SLJIT_TEMPORARY_REG2] < 7
+                       && reg_map[TMP_REGISTER] == 2,
+                       invalid_register_assignment_for_div_mul);
+#endif
+               compiler->mode32 = op & SLJIT_INT_OP;
+#endif
+
+               op = GET_OPCODE(op);
+               if (op == SLJIT_UDIV) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
+                       EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG2, 0);
+                       buf = emit_x86_instruction(compiler, 1, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0);
+#else
+                       buf = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
+#endif
+                       FAIL_IF(!buf);
+                       *buf = 0x33;
+               }
+
+               if (op == SLJIT_SDIV) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
+                       EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG2, 0);
+#endif
+
+                       /* CDQ instruction */
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+                       buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+                       FAIL_IF(!buf);
+                       INC_SIZE(1);
+                       *buf = 0x99;
+#else
+                       if (compiler->mode32) {
+                               buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+                               FAIL_IF(!buf);
+                               INC_SIZE(1);
+                               *buf = 0x99;
+                       } else {
+                               buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
+                               FAIL_IF(!buf);
+                               INC_SIZE(2);
+                               *buf++ = REX_W;
+                               *buf = 0x99;
+                       }
+#endif
+               }
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
+               FAIL_IF(!buf);
+               INC_SIZE(2);
+               *buf++ = 0xf7;
+               *buf = 0xc0 | ((op >= SLJIT_UDIV) ? reg_map[TMP_REGISTER] : reg_map[SLJIT_TEMPORARY_REG2]);
+#else
+#ifdef _WIN64
+               size = (!compiler->mode32 || op >= SLJIT_UDIV) ? 3 : 2;
+#else
+               size = (!compiler->mode32) ? 3 : 2;
+#endif
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
+               FAIL_IF(!buf);
+               INC_SIZE(size);
+#ifdef _WIN64
+               if (!compiler->mode32)
+                       *buf++ = REX_W | ((op >= SLJIT_UDIV) ? REX_B : 0);
+               else if (op >= SLJIT_UDIV)
+                       *buf++ = REX_B;
+               *buf++ = 0xf7;
+               *buf = 0xc0 | ((op >= SLJIT_UDIV) ? reg_lmap[TMP_REGISTER] : reg_lmap[SLJIT_TEMPORARY_REG2]);
+#else
+               if (!compiler->mode32)
+                       *buf++ = REX_W;
+               *buf++ = 0xf7;
+               *buf = 0xc0 | reg_map[SLJIT_TEMPORARY_REG2];
+#endif
+#endif
+               switch (op) {
+               case SLJIT_UMUL:
+                       *buf |= 4 << 3;
+                       break;
+               case SLJIT_SMUL:
+                       *buf |= 5 << 3;
+                       break;
+               case SLJIT_UDIV:
+                       *buf |= 6 << 3;
+                       break;
+               case SLJIT_SDIV:
+                       *buf |= 7 << 3;
+                       break;
+               }
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64)
+               EMIT_MOV(compiler, SLJIT_TEMPORARY_REG2, 0, TMP_REGISTER, 0);
+#endif
+               break;
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+#define ENCODE_PREFIX(prefix) \
+       do { \
+               code = (sljit_ub*)ensure_buf(compiler, 1 + 1); \
+               FAIL_IF(!code); \
+               INC_CSIZE(1); \
+               *code = (prefix); \
+       } while (0)
+
+static int emit_mov_byte(struct sljit_compiler *compiler, int sign,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       sljit_ub* code;
+       int dst_r;
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       int work_r;
+#endif
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       compiler->mode32 = 0;
+#endif
+
+       if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM))
+               return SLJIT_SUCCESS; /* Empty instruction. */
+
+       if (src & SLJIT_IMM) {
+               if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+                       return emit_do_imm(compiler, 0xb8 + reg_map[dst], srcw);
+#else
+                       return emit_load_imm64(compiler, dst, srcw);
+#endif
+               }
+               code = emit_x86_instruction(compiler, 1 | EX86_BYTE_ARG | EX86_NO_REXW, SLJIT_IMM, srcw, dst, dstw);
+               FAIL_IF(!code);
+               *code = 0xc6;
+               return SLJIT_SUCCESS;
+       }
+
+       dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
+
+       if ((dst & SLJIT_MEM) && src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+               if (reg_map[src] >= 4) {
+                       SLJIT_ASSERT(dst_r == TMP_REGISTER);
+                       EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0);
+               } else
+                       dst_r = src;
+#else
+               dst_r = src;
+#endif
+       }
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       else if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS && reg_map[src] >= 4) {
+               /* src, dst are registers. */
+               SLJIT_ASSERT(dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER);
+               if (reg_map[dst] < 4) {
+                       if (dst != src)
+                               EMIT_MOV(compiler, dst, 0, src, 0);
+                       code = emit_x86_instruction(compiler, 2, dst, 0, dst, 0);
+                       FAIL_IF(!code);
+                       *code++ = 0x0f;
+                       *code = sign ? 0xbe : 0xb6;
+               }
+               else {
+                       if (dst != src)
+                               EMIT_MOV(compiler, dst, 0, src, 0);
+                       if (sign) {
+                               /* shl reg, 24 */
+                               code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0);
+                               FAIL_IF(!code);
+                               *code |= 0x4 << 3;
+                               code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0);
+                               FAIL_IF(!code);
+                               /* shr/sar reg, 24 */
+                               *code |= 0x7 << 3;
+                       }
+                       else {
+                               /* and dst, 0xff */
+                               code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 255, dst, 0);
+                               FAIL_IF(!code);
+                               *(code + 1) |= 0x4 << 3;
+                       }
+               }
+               return SLJIT_SUCCESS;
+       }
+#endif
+       else {
+               /* src can be memory addr or reg_map[src] < 4 on x86_32 architectures. */
+               code = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);
+               FAIL_IF(!code);
+               *code++ = 0x0f;
+               *code = sign ? 0xbe : 0xb6;
+       }
+
+       if (dst & SLJIT_MEM) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+               if (dst_r == TMP_REGISTER) {
+                       /* Find a non-used register, whose reg_map[src] < 4. */
+                       if ((dst & 0xf) == SLJIT_TEMPORARY_REG1) {
+                               if ((dst & 0xf0) == (SLJIT_TEMPORARY_REG2 << 4))
+                                       work_r = SLJIT_TEMPORARY_REG3;
+                               else
+                                       work_r = SLJIT_TEMPORARY_REG2;
+                       }
+                       else {
+                               if ((dst & 0xf0) != (SLJIT_TEMPORARY_REG1 << 4))
+                                       work_r = SLJIT_TEMPORARY_REG1;
+                               else if ((dst & 0xf) == SLJIT_TEMPORARY_REG2)
+                                       work_r = SLJIT_TEMPORARY_REG3;
+                               else
+                                       work_r = SLJIT_TEMPORARY_REG2;
+                       }
+
+                       if (work_r == SLJIT_TEMPORARY_REG1) {
+                               ENCODE_PREFIX(0x90 + reg_map[TMP_REGISTER]);
+                       }
+                       else {
+                               code = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);
+                               FAIL_IF(!code);
+                               *code = 0x87;
+                       }
+
+                       code = emit_x86_instruction(compiler, 1, work_r, 0, dst, dstw);
+                       FAIL_IF(!code);
+                       *code = 0x88;
+
+                       if (work_r == SLJIT_TEMPORARY_REG1) {
+                               ENCODE_PREFIX(0x90 + reg_map[TMP_REGISTER]);
+                       }
+                       else {
+                               code = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);
+                               FAIL_IF(!code);
+                               *code = 0x87;
+                       }
+               }
+               else {
+                       code = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
+                       FAIL_IF(!code);
+                       *code = 0x88;
+               }
+#else
+               code = emit_x86_instruction(compiler, 1 | EX86_REX | EX86_NO_REXW, dst_r, 0, dst, dstw);
+               FAIL_IF(!code);
+               *code = 0x88;
+#endif
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+static int emit_mov_half(struct sljit_compiler *compiler, int sign,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       sljit_ub* code;
+       int dst_r;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       compiler->mode32 = 0;
+#endif
+
+       if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM))
+               return SLJIT_SUCCESS; /* Empty instruction. */
+
+       if (src & SLJIT_IMM) {
+               if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+                       return emit_do_imm(compiler, 0xb8 + reg_map[dst], srcw);
+#else
+                       return emit_load_imm64(compiler, dst, srcw);
+#endif
+               }
+               code = emit_x86_instruction(compiler, 1 | EX86_HALF_ARG | EX86_NO_REXW | EX86_PREF_66, SLJIT_IMM, srcw, dst, dstw);
+               FAIL_IF(!code);
+               *code = 0xc7;
+               return SLJIT_SUCCESS;
+       }
+
+       dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
+
+       if ((dst & SLJIT_MEM) && (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS))
+               dst_r = src;
+       else {
+               code = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);
+               FAIL_IF(!code);
+               *code++ = 0x0f;
+               *code = sign ? 0xbf : 0xb7;
+       }
+
+       if (dst & SLJIT_MEM) {
+               code = emit_x86_instruction(compiler, 1 | EX86_NO_REXW | EX86_PREF_66, dst_r, 0, dst, dstw);
+               FAIL_IF(!code);
+               *code = 0x89;
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+static int emit_unary(struct sljit_compiler *compiler, int un_index,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       sljit_ub* code;
+
+       if (dst == SLJIT_UNUSED) {
+               EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
+               code = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
+               FAIL_IF(!code);
+               *code++ = 0xf7;
+               *code |= (un_index) << 3;
+               return SLJIT_SUCCESS;
+       }
+       if (dst == src && dstw == srcw) {
+               /* Same input and output */
+               code = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+               FAIL_IF(!code);
+               *code++ = 0xf7;
+               *code |= (un_index) << 3;
+               return SLJIT_SUCCESS;
+       }
+       if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+               EMIT_MOV(compiler, dst, 0, src, srcw);
+               code = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+               FAIL_IF(!code);
+               *code++ = 0xf7;
+               *code |= (un_index) << 3;
+               return SLJIT_SUCCESS;
+       }
+       EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
+       code = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
+       FAIL_IF(!code);
+       *code++ = 0xf7;
+       *code |= (un_index) << 3;
+       EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
+       return SLJIT_SUCCESS;
+}
+
+static int emit_not_with_flags(struct sljit_compiler *compiler,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       sljit_ub* code;
+
+       if (dst == SLJIT_UNUSED) {
+               EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
+               code = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
+               FAIL_IF(!code);
+               *code++ = 0xf7;
+               *code |= 0x2 << 3;
+               code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
+               FAIL_IF(!code);
+               *code = 0x0b;
+               return SLJIT_SUCCESS;
+       }
+       if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+               EMIT_MOV(compiler, dst, 0, src, srcw);
+               code = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+               FAIL_IF(!code);
+               *code++ = 0xf7;
+               *code |= 0x2 << 3;
+               code = emit_x86_instruction(compiler, 1, dst, 0, dst, 0);
+               FAIL_IF(!code);
+               *code = 0x0b;
+               return SLJIT_SUCCESS;
+       }
+       EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
+       code = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
+       FAIL_IF(!code);
+       *code++ = 0xf7;
+       *code |= 0x2 << 3;
+       code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
+       FAIL_IF(!code);
+       *code = 0x0b;
+       EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
+       return SLJIT_SUCCESS;
+}
+
+static int emit_clz(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       sljit_ub* code;
+       int dst_r;
+
+       SLJIT_UNUSED_ARG(op);
+       if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
+               /* Just set the zero flag. */
+               EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
+               code = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
+               FAIL_IF(!code);
+               *code++ = 0xf7;
+               *code |= 0x2 << 3;
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+               code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 31, TMP_REGISTER, 0);
+#else
+               code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, !(op & SLJIT_INT_OP) ? 63 : 31, TMP_REGISTER, 0);
+#endif
+               FAIL_IF(!code);
+               *code |= 0x5 << 3;
+               return SLJIT_SUCCESS;
+       }
+
+       if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
+               EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
+               src = TMP_REGISTER;
+               srcw = 0;
+       }
+
+       code = emit_x86_instruction(compiler, 2, TMP_REGISTER, 0, src, srcw);
+       FAIL_IF(!code);
+       *code++ = 0x0f;
+       *code = 0xbd;
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER)
+               dst_r = dst;
+       else {
+               /* Find an unused temporary register. */
+               if ((dst & 0xf) != SLJIT_TEMPORARY_REG1 && (dst & 0xf0) != (SLJIT_TEMPORARY_REG1 << 4))
+                       dst_r = SLJIT_TEMPORARY_REG1;
+               else if ((dst & 0xf) != SLJIT_TEMPORARY_REG2 && (dst & 0xf0) != (SLJIT_TEMPORARY_REG2 << 4))
+                       dst_r = SLJIT_TEMPORARY_REG2;
+               else
+                       dst_r = SLJIT_TEMPORARY_REG3;
+               EMIT_MOV(compiler, dst, dstw, dst_r, 0);
+       }
+       EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, 32 + 31);
+#else
+       dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) ? dst : TMP_REG2;
+       compiler->mode32 = 0;
+       EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, !(op & SLJIT_INT_OP) ? 64 + 63 : 32 + 31);
+       compiler->mode32 = op & SLJIT_INT_OP;
+#endif
+
+       code = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REGISTER, 0);
+       FAIL_IF(!code);
+       *code++ = 0x0f;
+       *code = 0x45;
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0);
+#else
+       code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op & SLJIT_INT_OP) ? 63 : 31, dst_r, 0);
+#endif
+       FAIL_IF(!code);
+       *(code + 1) |= 0x6 << 3;
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       if (dst & SLJIT_MEM) {
+               code = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
+               FAIL_IF(!code);
+               *code = 0x87;
+       }
+#else
+       if (dst & SLJIT_MEM)
+               EMIT_MOV(compiler, dst, dstw, TMP_REG2, 0);
+#endif
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       sljit_ub* code;
+       int update = 0;
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       int dst_is_ereg = 0;
+       int src_is_ereg = 0;
+#else
+       #define src_is_ereg 0
+#endif
+
+       CHECK_ERROR();
+       check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       compiler->mode32 = op & SLJIT_INT_OP;
+#endif
+       CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1);
+       CHECK_EXTRA_REGS(src, srcw, src_is_ereg = 1);
+
+       if (GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI) {
+               op = GET_OPCODE(op);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+               compiler->mode32 = 0;
+#endif
+
+               SLJIT_COMPILE_ASSERT(SLJIT_MOV + 7 == SLJIT_MOVU, movu_offset);
+               if (op >= SLJIT_MOVU) {
+                       update = 1;
+                       op -= 7;
+               }
+
+               if (src & SLJIT_IMM) {
+                       switch (op) {
+                       case SLJIT_MOV_UB:
+                               srcw = (unsigned char)srcw;
+                               break;
+                       case SLJIT_MOV_SB:
+                               srcw = (signed char)srcw;
+                               break;
+                       case SLJIT_MOV_UH:
+                               srcw = (unsigned short)srcw;
+                               break;
+                       case SLJIT_MOV_SH:
+                               srcw = (signed short)srcw;
+                               break;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+                       case SLJIT_MOV_UI:
+                               srcw = (unsigned int)srcw;
+                               break;
+                       case SLJIT_MOV_SI:
+                               srcw = (signed int)srcw;
+                               break;
+#endif
+                       }
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+                       if (SLJIT_UNLIKELY(dst_is_ereg))
+                               return emit_mov(compiler, dst, dstw, src, srcw);
+#endif
+               }
+
+               if (SLJIT_UNLIKELY(update) && (src & SLJIT_MEM) && !src_is_ereg && (src & 0xf) && (srcw != 0 || (src & 0xf0) != 0)) {
+                       code = emit_x86_instruction(compiler, 1, src & 0xf, 0, src, srcw);
+                       FAIL_IF(!code);
+                       *code = 0x8d;
+                       src &= SLJIT_MEM | 0xf;
+                       srcw = 0;
+               }
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+               if (SLJIT_UNLIKELY(dst_is_ereg) && (!(op == SLJIT_MOV || op == SLJIT_MOV_UI || op == SLJIT_MOV_SI) || (src & SLJIT_MEM))) {
+                       SLJIT_ASSERT(dst == SLJIT_MEM1(SLJIT_LOCALS_REG));
+                       dst = TMP_REGISTER;
+               }
+#endif
+
+               switch (op) {
+               case SLJIT_MOV:
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+               case SLJIT_MOV_UI:
+               case SLJIT_MOV_SI:
+#endif
+                       FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
+                       break;
+               case SLJIT_MOV_UB:
+                       FAIL_IF(emit_mov_byte(compiler, 0, dst, dstw, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw));
+                       break;
+               case SLJIT_MOV_SB:
+                       FAIL_IF(emit_mov_byte(compiler, 1, dst, dstw, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw));
+                       break;
+               case SLJIT_MOV_UH:
+                       FAIL_IF(emit_mov_half(compiler, 0, dst, dstw, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw));
+                       break;
+               case SLJIT_MOV_SH:
+                       FAIL_IF(emit_mov_half(compiler, 1, dst, dstw, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw));
+                       break;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+               case SLJIT_MOV_UI:
+                       FAIL_IF(emit_mov_int(compiler, 0, dst, dstw, src, (src & SLJIT_IMM) ? (unsigned int)srcw : srcw));
+                       break;
+               case SLJIT_MOV_SI:
+                       FAIL_IF(emit_mov_int(compiler, 1, dst, dstw, src, (src & SLJIT_IMM) ? (signed int)srcw : srcw));
+                       break;
+#endif
+               }
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+               if (SLJIT_UNLIKELY(dst_is_ereg) && dst == TMP_REGISTER)
+                       return emit_mov(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), dstw, TMP_REGISTER, 0);
+#endif
+
+               if (SLJIT_UNLIKELY(update) && (dst & SLJIT_MEM) && (dst & 0xf) && (dstw != 0 || (dst & 0xf0) != 0)) {
+                       code = emit_x86_instruction(compiler, 1, dst & 0xf, 0, dst, dstw);
+                       FAIL_IF(!code);
+                       *code = 0x8d;
+               }
+               return SLJIT_SUCCESS;
+       }
+
+       if (SLJIT_UNLIKELY(GET_FLAGS(op)))
+               compiler->flags_saved = 0;
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_NOT:
+               if (SLJIT_UNLIKELY(op & SLJIT_SET_E))
+                       return emit_not_with_flags(compiler, dst, dstw, src, srcw);
+               return emit_unary(compiler, 0x2, dst, dstw, src, srcw);
+
+       case SLJIT_NEG:
+               if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
+                       FAIL_IF(emit_save_flags(compiler));
+               return emit_unary(compiler, 0x3, dst, dstw, src, srcw);
+
+       case SLJIT_CLZ:
+               if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
+                       FAIL_IF(emit_save_flags(compiler));
+               return emit_clz(compiler, op, dst, dstw, src, srcw);
+       }
+
+       return SLJIT_SUCCESS;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       #undef src_is_ereg
+#endif
+}
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+
+#define BINARY_IMM(_op_imm_, _op_mr_, immw, arg, argw) \
+       if (IS_HALFWORD(immw) || compiler->mode32) { \
+               code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
+               FAIL_IF(!code); \
+               *(code + 1) |= (_op_imm_); \
+       } \
+       else { \
+               FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immw)); \
+               code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, arg, argw); \
+               FAIL_IF(!code); \
+               *code = (_op_mr_); \
+       }
+
+#define BINARY_EAX_IMM(_op_eax_imm_, immw) \
+       FAIL_IF(emit_do_imm32(compiler, (!compiler->mode32) ? REX_W : 0, (_op_eax_imm_), immw))
+
+#else
+
+#define BINARY_IMM(_op_imm_, _op_mr_, immw, arg, argw) \
+       code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
+       FAIL_IF(!code); \
+       *(code + 1) |= (_op_imm_);
+
+#define BINARY_EAX_IMM(_op_eax_imm_, immw) \
+       FAIL_IF(emit_do_imm(compiler, (_op_eax_imm_), immw))
+
+#endif
+
+static int emit_cum_binary(struct sljit_compiler *compiler,
+       sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       sljit_ub* code;
+
+       if (dst == SLJIT_UNUSED) {
+               EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+               if (src2 & SLJIT_IMM) {
+                       BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
+               }
+               else {
+                       code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+                       FAIL_IF(!code);
+                       *code = op_rm;
+               }
+               return SLJIT_SUCCESS;
+       }
+
+       if (dst == src1 && dstw == src1w) {
+               if (src2 & SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+                       if ((dst == SLJIT_TEMPORARY_REG1) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
+#else
+                       if ((dst == SLJIT_TEMPORARY_REG1) && (src2w > 127 || src2w < -128)) {
+#endif
+                               BINARY_EAX_IMM(op_eax_imm, src2w);
+                       }
+                       else {
+                               BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);
+                       }
+               }
+               else if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+                       code = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);
+                       FAIL_IF(!code);
+                       *code = op_rm;
+               }
+               else if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REGISTER) {
+                       /* Special exception for sljit_emit_cond_value. */
+                       code = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);
+                       FAIL_IF(!code);
+                       *code = op_mr;
+               }
+               else {
+                       EMIT_MOV(compiler, TMP_REGISTER, 0, src2, src2w);
+                       code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
+                       FAIL_IF(!code);
+                       *code = op_mr;
+               }
+               return SLJIT_SUCCESS;
+       }
+
+       /* Only for cumulative operations. */
+       if (dst == src2 && dstw == src2w) {
+               if (src1 & SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+                       if ((dst == SLJIT_TEMPORARY_REG1) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
+#else
+                       if ((dst == SLJIT_TEMPORARY_REG1) && (src1w > 127 || src1w < -128)) {
+#endif
+                               BINARY_EAX_IMM(op_eax_imm, src1w);
+                       }
+                       else {
+                               BINARY_IMM(op_imm, op_mr, src1w, dst, dstw);
+                       }
+               }
+               else if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+                       code = emit_x86_instruction(compiler, 1, dst, dstw, src1, src1w);
+                       FAIL_IF(!code);
+                       *code = op_rm;
+               }
+               else if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= SLJIT_NO_REGISTERS) {
+                       code = emit_x86_instruction(compiler, 1, src1, src1w, dst, dstw);
+                       FAIL_IF(!code);
+                       *code = op_mr;
+               }
+               else {
+                       EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+                       code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
+                       FAIL_IF(!code);
+                       *code = op_mr;
+               }
+               return SLJIT_SUCCESS;
+       }
+
+       /* General version. */
+       if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+               EMIT_MOV(compiler, dst, 0, src1, src1w);
+               if (src2 & SLJIT_IMM) {
+                       BINARY_IMM(op_imm, op_mr, src2w, dst, 0);
+               }
+               else {
+                       code = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);
+                       FAIL_IF(!code);
+                       *code = op_rm;
+               }
+       }
+       else {
+               /* This version requires less memory writing. */
+               EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+               if (src2 & SLJIT_IMM) {
+                       BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
+               }
+               else {
+                       code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+                       FAIL_IF(!code);
+                       *code = op_rm;
+               }
+               EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+static int emit_non_cum_binary(struct sljit_compiler *compiler,
+       sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       sljit_ub* code;
+
+       if (dst == SLJIT_UNUSED) {
+               EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+               if (src2 & SLJIT_IMM) {
+                       BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
+               }
+               else {
+                       code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+                       FAIL_IF(!code);
+                       *code = op_rm;
+               }
+               return SLJIT_SUCCESS;
+       }
+
+       if (dst == src1 && dstw == src1w) {
+               if (src2 & SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+                       if ((dst == SLJIT_TEMPORARY_REG1) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
+#else
+                       if ((dst == SLJIT_TEMPORARY_REG1) && (src2w > 127 || src2w < -128)) {
+#endif
+                               BINARY_EAX_IMM(op_eax_imm, src2w);
+                       }
+                       else {
+                               BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);
+                       }
+               }
+               else if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+                       code = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);
+                       FAIL_IF(!code);
+                       *code = op_rm;
+               }
+               else if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS) {
+                       code = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);
+                       FAIL_IF(!code);
+                       *code = op_mr;
+               }
+               else {
+                       EMIT_MOV(compiler, TMP_REGISTER, 0, src2, src2w);
+                       code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
+                       FAIL_IF(!code);
+                       *code = op_mr;
+               }
+               return SLJIT_SUCCESS;
+       }
+
+       /* General version. */
+       if ((dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) && dst != src2) {
+               EMIT_MOV(compiler, dst, 0, src1, src1w);
+               if (src2 & SLJIT_IMM) {
+                       BINARY_IMM(op_imm, op_mr, src2w, dst, 0);
+               }
+               else {
+                       code = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);
+                       FAIL_IF(!code);
+                       *code = op_rm;
+               }
+       }
+       else {
+               /* This version requires less memory writing. */
+               EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+               if (src2 & SLJIT_IMM) {
+                       BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
+               }
+               else {
+                       code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+                       FAIL_IF(!code);
+                       *code = op_rm;
+               }
+               EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+static int emit_mul(struct sljit_compiler *compiler,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       sljit_ub* code;
+       int dst_r;
+
+       dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REGISTER;
+
+       /* Register destination. */
+       if (dst_r == src1 && !(src2 & SLJIT_IMM)) {
+               code = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w);
+               FAIL_IF(!code);
+               *code++ = 0x0f;
+               *code = 0xaf;
+       }
+       else if (dst_r == src2 && !(src1 & SLJIT_IMM)) {
+               code = emit_x86_instruction(compiler, 2, dst_r, 0, src1, src1w);
+               FAIL_IF(!code);
+               *code++ = 0x0f;
+               *code = 0xaf;
+       }
+       else if (src1 & SLJIT_IMM) {
+               if (src2 & SLJIT_IMM) {
+                       EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, src2w);
+                       src2 = dst_r;
+                       src2w = 0;
+               }
+
+               if (src1w <= 127 && src1w >= -128) {
+                       code = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
+                       FAIL_IF(!code);
+                       *code = 0x6b;
+                       code = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+                       FAIL_IF(!code);
+                       INC_CSIZE(1);
+                       *code = (sljit_b)src1w;
+               }
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+               else {
+                       code = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
+                       FAIL_IF(!code);
+                       *code = 0x69;
+                       code = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+                       FAIL_IF(!code);
+                       INC_CSIZE(4);
+                       *(sljit_w*)code = src1w;
+               }
+#else
+               else if (IS_HALFWORD(src1w)) {
+                       code = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
+                       FAIL_IF(!code);
+                       *code = 0x69;
+                       code = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+                       FAIL_IF(!code);
+                       INC_CSIZE(4);
+                       *(sljit_hw*)code = (sljit_hw)src1w;
+               }
+               else {
+                       EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src1w);
+                       if (dst_r != src2)
+                               EMIT_MOV(compiler, dst_r, 0, src2, src2w);
+                       code = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);
+                       FAIL_IF(!code);
+                       *code++ = 0x0f;
+                       *code = 0xaf;
+               }
+#endif
+       }
+       else if (src2 & SLJIT_IMM) {
+               /* Note: src1 is NOT immediate. */
+
+               if (src2w <= 127 && src2w >= -128) {
+                       code = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
+                       FAIL_IF(!code);
+                       *code = 0x6b;
+                       code = (sljit_ub*)ensure_buf(compiler, 1 + 1);
+                       FAIL_IF(!code);
+                       INC_CSIZE(1);
+                       *code = (sljit_b)src2w;
+               }
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+               else {
+                       code = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
+                       FAIL_IF(!code);
+                       *code = 0x69;
+                       code = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+                       FAIL_IF(!code);
+                       INC_CSIZE(4);
+                       *(sljit_w*)code = src2w;
+               }
+#else
+               else if (IS_HALFWORD(src2w)) {
+                       code = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
+                       FAIL_IF(!code);
+                       *code = 0x69;
+                       code = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+                       FAIL_IF(!code);
+                       INC_CSIZE(4);
+                       *(sljit_hw*)code = (sljit_hw)src2w;
+               }
+               else {
+                       EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src1w);
+                       if (dst_r != src1)
+                               EMIT_MOV(compiler, dst_r, 0, src1, src1w);
+                       code = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);
+                       FAIL_IF(!code);
+                       *code++ = 0x0f;
+                       *code = 0xaf;
+               }
+#endif
+       }
+       else {
+               /* Neither argument is immediate. */
+               if (ADDRESSING_DEPENDS_ON(src2, dst_r))
+                       dst_r = TMP_REGISTER;
+               EMIT_MOV(compiler, dst_r, 0, src1, src1w);
+               code = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w);
+               FAIL_IF(!code);
+               *code++ = 0x0f;
+               *code = 0xaf;
+       }
+
+       if (dst_r == TMP_REGISTER)
+               EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
+
+       return SLJIT_SUCCESS;
+}
+
+static int emit_lea_binary(struct sljit_compiler *compiler,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       sljit_ub* code;
+       int dst_r, done = 0;
+
+       /* These cases better be left to handled by normal way. */
+       if (dst == src1 && dstw == src1w)
+               return SLJIT_ERR_UNSUPPORTED;
+       if (dst == src2 && dstw == src2w)
+               return SLJIT_ERR_UNSUPPORTED;
+
+       dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REGISTER;
+
+       if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= SLJIT_NO_REGISTERS) {
+               if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS) {
+                       /* It is not possible to be both SLJIT_LOCALS_REG. */
+                       if (src1 != SLJIT_LOCALS_REG || src2 != SLJIT_LOCALS_REG) {
+                               code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), 0);
+                               FAIL_IF(!code);
+                               *code = 0x8d;
+                               done = 1;
+                       }
+               }
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+               if ((src2 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src2w))) {
+                       code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), (int)src2w);
+#else
+               if (src2 & SLJIT_IMM) {
+                       code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), src2w);
+#endif
+                       FAIL_IF(!code);
+                       *code = 0x8d;
+                       done = 1;
+               }
+       }
+       else if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+               if ((src1 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src1w))) {
+                       code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), (int)src1w);
+#else
+               if (src1 & SLJIT_IMM) {
+                       code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), src1w);
+#endif
+                       FAIL_IF(!code);
+                       *code = 0x8d;
+                       done = 1;
+               }
+       }
+
+       if (done) {
+               if (dst_r == TMP_REGISTER)
+                       return emit_mov(compiler, dst, dstw, TMP_REGISTER, 0);
+               return SLJIT_SUCCESS;
+       }
+       return SLJIT_ERR_UNSUPPORTED;
+}
+
+static int emit_cmp_binary(struct sljit_compiler *compiler,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       sljit_ub* code;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       if (src1 == SLJIT_TEMPORARY_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
+#else
+       if (src1 == SLJIT_TEMPORARY_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {
+#endif
+               BINARY_EAX_IMM(0x3d, src2w);
+               return SLJIT_SUCCESS;
+       }
+
+       if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= SLJIT_NO_REGISTERS) {
+               if (src2 & SLJIT_IMM) {
+                       BINARY_IMM(0x7 << 3, 0x39, src2w, src1, 0);
+               }
+               else {
+                       code = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);
+                       FAIL_IF(!code);
+                       *code = 0x3b;
+               }
+               return SLJIT_SUCCESS;
+       }
+
+       if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS && !(src1 & SLJIT_IMM)) {
+               code = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);
+               FAIL_IF(!code);
+               *code = 0x39;
+               return SLJIT_SUCCESS;
+       }
+
+       if (src2 & SLJIT_IMM) {
+               if (src1 & SLJIT_IMM) {
+                       EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+                       src1 = TMP_REGISTER;
+                       src1w = 0;
+               }
+               BINARY_IMM(0x7 << 3, 0x39, src2w, src1, src1w);
+       }
+       else {
+               EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+               code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+               FAIL_IF(!code);
+               *code = 0x3b;
+       }
+       return SLJIT_SUCCESS;
+}
+
+static int emit_test_binary(struct sljit_compiler *compiler,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       sljit_ub* code;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       if (src1 == SLJIT_TEMPORARY_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
+#else
+       if (src1 == SLJIT_TEMPORARY_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {
+#endif
+               BINARY_EAX_IMM(0xa9, src2w);
+               return SLJIT_SUCCESS;
+       }
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       if (src2 == SLJIT_TEMPORARY_REG1 && (src2 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
+#else
+       if (src2 == SLJIT_TEMPORARY_REG1 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128)) {
+#endif
+               BINARY_EAX_IMM(0xa9, src1w);
+               return SLJIT_SUCCESS;
+       }
+
+       if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= SLJIT_NO_REGISTERS) {
+               if (src2 & SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+                       if (IS_HALFWORD(src2w) || compiler->mode32) {
+                               code = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0);
+                               FAIL_IF(!code);
+                               *code = 0xf7;
+                       }
+                       else {
+                               FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
+                               code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, 0);
+                               FAIL_IF(!code);
+                               *code = 0x85;
+                       }
+#else
+                       code = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0);
+                       FAIL_IF(!code);
+                       *code = 0xf7;
+#endif
+               }
+               else {
+                       code = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);
+                       FAIL_IF(!code);
+                       *code = 0x85;
+               }
+               return SLJIT_SUCCESS;
+       }
+
+       if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS) {
+               if (src1 & SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+                       if (IS_HALFWORD(src1w) || compiler->mode32) {
+                               code = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, 0);
+                               FAIL_IF(!code);
+                               *code = 0xf7;
+                       }
+                       else {
+                               FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w));
+                               code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, 0);
+                               FAIL_IF(!code);
+                               *code = 0x85;
+                       }
+#else
+                       code = emit_x86_instruction(compiler, 1, src1, src1w, src2, 0);
+                       FAIL_IF(!code);
+                       *code = 0xf7;
+#endif
+               }
+               else {
+                       code = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);
+                       FAIL_IF(!code);
+                       *code = 0x85;
+               }
+               return SLJIT_SUCCESS;
+       }
+
+       EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+       if (src2 & SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+               if (IS_HALFWORD(src2w) || compiler->mode32) {
+                       code = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REGISTER, 0);
+                       FAIL_IF(!code);
+                       *code = 0xf7;
+               }
+               else {
+                       FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
+                       code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, TMP_REGISTER, 0);
+                       FAIL_IF(!code);
+                       *code = 0x85;
+               }
+#else
+               code = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REGISTER, 0);
+               FAIL_IF(!code);
+               *code = 0xf7;
+#endif
+       }
+       else {
+               code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
+               FAIL_IF(!code);
+               *code = 0x85;
+       }
+       return SLJIT_SUCCESS;
+}
+
+static int emit_shift(struct sljit_compiler *compiler,
+       sljit_ub mode,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       sljit_ub* code;
+
+       if ((src2 & SLJIT_IMM) || (src2 == SLJIT_PREF_SHIFT_REG)) {
+               if (dst == src1 && dstw == src1w) {
+                       code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, dstw);
+                       FAIL_IF(!code);
+                       *code |= mode;
+                       return SLJIT_SUCCESS;
+               }
+               if (dst == SLJIT_UNUSED) {
+                       EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+                       code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REGISTER, 0);
+                       FAIL_IF(!code);
+                       *code |= mode;
+                       return SLJIT_SUCCESS;
+               }
+               if (dst == SLJIT_PREF_SHIFT_REG && src2 == SLJIT_PREF_SHIFT_REG) {
+                       EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+                       code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
+                       FAIL_IF(!code);
+                       *code |= mode;
+                       EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
+                       return SLJIT_SUCCESS;
+               }
+               if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+                       EMIT_MOV(compiler, dst, 0, src1, src1w);
+                       code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, 0);
+                       FAIL_IF(!code);
+                       *code |= mode;
+                       return SLJIT_SUCCESS;
+               }
+
+               EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+               code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REGISTER, 0);
+               FAIL_IF(!code);
+               *code |= mode;
+               EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
+               return SLJIT_SUCCESS;
+       }
+
+       if (dst == SLJIT_PREF_SHIFT_REG) {
+               EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+               EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
+               code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
+               FAIL_IF(!code);
+               *code |= mode;
+               EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
+       }
+       else if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS && dst != src2 && !ADDRESSING_DEPENDS_ON(src2, dst)) {
+               if (src1 != dst)
+                       EMIT_MOV(compiler, dst, 0, src1, src1w);
+               EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_PREF_SHIFT_REG, 0);
+               EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
+               code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, dst, 0);
+               FAIL_IF(!code);
+               *code |= mode;
+               EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
+       }
+       else {
+               /* This case is really difficult, since ecx itself may used for
+                  addressing, and we must ensure to work even in that case. */
+               EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+               EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0);
+#else
+               /* [esp - 4] is reserved for eflags. */
+               EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), -(int)(2 * sizeof(sljit_w)), SLJIT_PREF_SHIFT_REG, 0);
+#endif
+               EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
+               code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
+               FAIL_IF(!code);
+               *code |= mode;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+               EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0);
+#else
+               /* [esp - 4] is reserved for eflags. */
+               EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), -(int)(2 * sizeof(sljit_w)));
+#endif
+               EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+static int emit_shift_with_flags(struct sljit_compiler *compiler,
+       sljit_ub mode, int set_flags,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       /* The CPU does not set flags if the shift count is 0. */
+       if (src2 & SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+               if ((src2w & 0x3f) != 0 || (compiler->mode32 && (src2w & 0x1f) != 0))
+                       return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);
+#else
+               if ((src2w & 0x1f) != 0)
+                       return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);
+#endif
+               if (!set_flags)
+                       return emit_mov(compiler, dst, dstw, src1, src1w);
+               /* OR dst, src, 0 */
+               return emit_cum_binary(compiler, 0x0b, 0x09, 0x1 << 3, 0x0d,
+                       dst, dstw, src1, src1w, SLJIT_IMM, 0);
+       }
+
+       if (!set_flags)
+               return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);
+
+       if (!(dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS))
+               FAIL_IF(emit_cmp_binary(compiler, src1, src1w, SLJIT_IMM, 0));
+
+       FAIL_IF(emit_shift(compiler,mode, dst, dstw, src1, src1w, src2, src2w));
+
+       if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
+               return emit_cmp_binary(compiler, dst, dstw, SLJIT_IMM, 0);
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       CHECK_ERROR();
+       check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       compiler->mode32 = op & SLJIT_INT_OP;
+#endif
+       CHECK_EXTRA_REGS(dst, dstw, (void)0);
+       CHECK_EXTRA_REGS(src1, src1w, (void)0);
+       CHECK_EXTRA_REGS(src2, src2w, (void)0);
+
+       if (GET_OPCODE(op) >= SLJIT_MUL) {
+               if (SLJIT_UNLIKELY(GET_FLAGS(op)))
+                       compiler->flags_saved = 0;
+               else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
+                       FAIL_IF(emit_save_flags(compiler));
+       }
+
+       switch (GET_OPCODE(op)) {
+       case SLJIT_ADD:
+               if (!GET_FLAGS(op)) {
+                       if (emit_lea_binary(compiler, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED)
+                               return compiler->error;
+               } 
+               else
+                       compiler->flags_saved = 0;
+               if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
+                       FAIL_IF(emit_save_flags(compiler));
+               return emit_cum_binary(compiler, 0x03, 0x01, 0x0 << 3, 0x05,
+                       dst, dstw, src1, src1w, src2, src2w);
+       case SLJIT_ADDC:
+               if (SLJIT_UNLIKELY(compiler->flags_saved)) /* C flag must be restored. */
+                       FAIL_IF(emit_restore_flags(compiler, 1));
+               else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS))
+                       FAIL_IF(emit_save_flags(compiler));
+               if (SLJIT_UNLIKELY(GET_FLAGS(op)))
+                       compiler->flags_saved = 0;
+               return emit_cum_binary(compiler, 0x13, 0x11, 0x2 << 3, 0x15,
+                       dst, dstw, src1, src1w, src2, src2w);
+       case SLJIT_SUB:
+               if (!GET_FLAGS(op)) {
+                       if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED)
+                               return compiler->error;
+               }
+               else
+                       compiler->flags_saved = 0;
+               if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
+                       FAIL_IF(emit_save_flags(compiler));
+               if (dst == SLJIT_UNUSED)
+                       return emit_cmp_binary(compiler, src1, src1w, src2, src2w);
+               return emit_non_cum_binary(compiler, 0x2b, 0x29, 0x5 << 3, 0x2d,
+                       dst, dstw, src1, src1w, src2, src2w);
+       case SLJIT_SUBC:
+               if (SLJIT_UNLIKELY(compiler->flags_saved)) /* C flag must be restored. */
+                       FAIL_IF(emit_restore_flags(compiler, 1));
+               else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS))
+                       FAIL_IF(emit_save_flags(compiler));
+               if (SLJIT_UNLIKELY(GET_FLAGS(op)))
+                       compiler->flags_saved = 0;
+               return emit_non_cum_binary(compiler, 0x1b, 0x19, 0x3 << 3, 0x1d,
+                       dst, dstw, src1, src1w, src2, src2w);
+       case SLJIT_MUL:
+               return emit_mul(compiler, dst, dstw, src1, src1w, src2, src2w);
+       case SLJIT_AND:
+               if (dst == SLJIT_UNUSED)
+                       return emit_test_binary(compiler, src1, src1w, src2, src2w);
+               return emit_cum_binary(compiler, 0x23, 0x21, 0x4 << 3, 0x25,
+                       dst, dstw, src1, src1w, src2, src2w);
+       case SLJIT_OR:
+               return emit_cum_binary(compiler, 0x0b, 0x09, 0x1 << 3, 0x0d,
+                       dst, dstw, src1, src1w, src2, src2w);
+       case SLJIT_XOR:
+               return emit_cum_binary(compiler, 0x33, 0x31, 0x6 << 3, 0x35,
+                       dst, dstw, src1, src1w, src2, src2w);
+       case SLJIT_SHL:
+               return emit_shift_with_flags(compiler, 0x4 << 3, GET_FLAGS(op),
+                       dst, dstw, src1, src1w, src2, src2w);
+       case SLJIT_LSHR:
+               return emit_shift_with_flags(compiler, 0x5 << 3, GET_FLAGS(op),
+                       dst, dstw, src1, src1w, src2, src2w);
+       case SLJIT_ASHR:
+               return emit_shift_with_flags(compiler, 0x7 << 3, GET_FLAGS(op),
+                       dst, dstw, src1, src1w, src2, src2w);
+       }
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg)
+{
+       check_sljit_get_register_index(reg);
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       if (reg == SLJIT_TEMPORARY_EREG1 || reg == SLJIT_TEMPORARY_EREG2
+                       || reg == SLJIT_SAVED_EREG1 || reg == SLJIT_SAVED_EREG2)
+               return -1;
+#endif
+       return reg_map[reg];
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
+       void *instruction, int size)
+{
+       sljit_ub *buf;
+
+       CHECK_ERROR();
+       check_sljit_emit_op_custom(compiler, instruction, size);
+       SLJIT_ASSERT(size > 0 && size < 16);
+
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
+       FAIL_IF(!buf);
+       INC_SIZE(size);
+       SLJIT_MEMMOVE(buf, instruction, size);
+       return SLJIT_SUCCESS;
+}
+
+/* --------------------------------------------------------------------- */
+/*  Floating point operators                                             */
+/* --------------------------------------------------------------------- */
+
+#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
+static int sse2_available = 0;
+#endif
+
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+
+/* Alignment + 2 * 16 bytes. */
+static sljit_i sse2_data[3 + 4 + 4];
+static sljit_i *sse2_buffer;
+
+static void init_compiler()
+{
+#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
+       int features = 0;
+#endif
+
+       sse2_buffer = (sljit_i*)(((sljit_uw)sse2_data + 15) & ~0xf);
+       sse2_buffer[0] = 0;
+       sse2_buffer[1] = 0x80000000;
+       sse2_buffer[4] = 0xffffffff;
+       sse2_buffer[5] = 0x7fffffff;
+
+#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
+#ifdef __GNUC__
+       /* AT&T syntax. */
+       asm (
+               "pushl %%ebx\n"
+               "movl $0x1, %%eax\n"
+               "cpuid\n"
+               "popl %%ebx\n"
+               "movl %%edx, %0\n"
+               : "=g" (features)
+               :
+               : "%eax", "%ecx", "%edx"
+       );
+#elif defined(_MSC_VER) || defined(__BORLANDC__)
+       /* Intel syntax. */
+       __asm {
+               mov eax, 1
+               push ebx
+               cpuid
+               pop ebx
+               mov features, edx
+       }
+#else
+       #error "SLJIT_SSE2_AUTO is not implemented for this C compiler"
+#endif
+       sse2_available = (features >> 26) & 0x1;
+#endif
+}
+
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void)
+{
+       /* Always available. */
+       return 1;
+}
+
+#if (defined SLJIT_SSE2 && SLJIT_SSE2)
+
+static int emit_sse2(struct sljit_compiler *compiler, sljit_ub opcode,
+       int xmm1, int xmm2, sljit_w xmm2w)
+{
+       sljit_ub *buf;
+
+       buf = emit_x86_instruction(compiler, 2 | EX86_PREF_F2 | EX86_SSE2, xmm1, 0, xmm2, xmm2w);
+       FAIL_IF(!buf);
+       *buf++ = 0x0f;
+       *buf = opcode;
+       return SLJIT_SUCCESS;
+}
+
+static int emit_sse2_logic(struct sljit_compiler *compiler, sljit_ub opcode,
+       int xmm1, int xmm2, sljit_w xmm2w)
+{
+       sljit_ub *buf;
+
+       buf = emit_x86_instruction(compiler, 2 | EX86_PREF_66 | EX86_SSE2, xmm1, 0, xmm2, xmm2w);
+       FAIL_IF(!buf);
+       *buf++ = 0x0f;
+       *buf = opcode;
+       return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE int emit_sse2_load(struct sljit_compiler *compiler,
+       int dst, int src, sljit_w srcw)
+{
+       return emit_sse2(compiler, 0x10, dst, src, srcw);
+}
+
+static SLJIT_INLINE int emit_sse2_store(struct sljit_compiler *compiler,
+       int dst, sljit_w dstw, int src)
+{
+       return emit_sse2(compiler, 0x11, src, dst, dstw);
+}
+
+#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
+#else
+static int sljit_emit_sse2_fop1(struct sljit_compiler *compiler, int op,
+#endif
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       int dst_r;
+
+       CHECK_ERROR();
+       check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       compiler->mode32 = 1;
+#endif
+
+       if (GET_OPCODE(op) == SLJIT_FCMP) {
+               compiler->flags_saved = 0;
+               if (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4)
+                       dst_r = dst;
+               else {
+                       dst_r = TMP_FREG;
+                       FAIL_IF(emit_sse2_load(compiler, dst_r, dst, dstw));
+               }
+               return emit_sse2_logic(compiler, 0x2e, dst_r, src, srcw);
+       }
+
+       if (op == SLJIT_FMOV) {
+               if (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4)
+                       return emit_sse2_load(compiler, dst, src, srcw);
+               if (src >= SLJIT_FLOAT_REG1 && src <= SLJIT_FLOAT_REG4)
+                       return emit_sse2_store(compiler, dst, dstw, src);
+               FAIL_IF(emit_sse2_load(compiler, TMP_FREG, src, srcw));
+               return emit_sse2_store(compiler, dst, dstw, TMP_FREG);
+       }
+
+       if (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) {
+               dst_r = dst;
+               if (dst != src)
+                       FAIL_IF(emit_sse2_load(compiler, dst_r, src, srcw));
+       }
+       else {
+               dst_r = TMP_FREG;
+               FAIL_IF(emit_sse2_load(compiler, dst_r, src, srcw));
+       }
+
+       switch (op) {
+       case SLJIT_FNEG:
+               FAIL_IF(emit_sse2_logic(compiler, 0x57, dst_r, SLJIT_MEM0(), (sljit_w)sse2_buffer));
+               break;
+
+       case SLJIT_FABS:
+               FAIL_IF(emit_sse2_logic(compiler, 0x54, dst_r, SLJIT_MEM0(), (sljit_w)(sse2_buffer + 4)));
+               break;
+       }
+
+       if (dst_r == TMP_FREG)
+               return emit_sse2_store(compiler, dst, dstw, TMP_FREG);
+       return SLJIT_SUCCESS;
+}
+
+#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
+#else
+static int sljit_emit_sse2_fop2(struct sljit_compiler *compiler, int op,
+#endif
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       int dst_r;
+
+       CHECK_ERROR();
+       check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       compiler->mode32 = 1;
+#endif
+
+       if (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) {
+               dst_r = dst;
+               if (dst == src1)
+                       ; /* Do nothing here. */
+               else if (dst == src2 && (op == SLJIT_FADD || op == SLJIT_FMUL)) {
+                       /* Swap arguments. */
+                       src2 = src1;
+                       src2w = src1w;
+               }
+               else if (dst != src2)
+                       FAIL_IF(emit_sse2_load(compiler, dst_r, src1, src1w));
+               else {
+                       dst_r = TMP_FREG;
+                       FAIL_IF(emit_sse2_load(compiler, TMP_FREG, src1, src1w));
+               }
+       }
+       else {
+               dst_r = TMP_FREG;
+               FAIL_IF(emit_sse2_load(compiler, TMP_FREG, src1, src1w));
+       }
+
+       switch (op) {
+       case SLJIT_FADD:
+               FAIL_IF(emit_sse2(compiler, 0x58, dst_r, src2, src2w));
+               break;
+
+       case SLJIT_FSUB:
+               FAIL_IF(emit_sse2(compiler, 0x5c, dst_r, src2, src2w));
+               break;
+
+       case SLJIT_FMUL:
+               FAIL_IF(emit_sse2(compiler, 0x59, dst_r, src2, src2w));
+               break;
+
+       case SLJIT_FDIV:
+               FAIL_IF(emit_sse2(compiler, 0x5e, dst_r, src2, src2w));
+               break;
+       }
+
+       if (dst_r == TMP_FREG)
+               return emit_sse2_store(compiler, dst, dstw, TMP_FREG);
+       return SLJIT_SUCCESS;
+}
+
+#endif
+
+#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) || !(defined SLJIT_SSE2 && SLJIT_SSE2)
+
+static int emit_fld(struct sljit_compiler *compiler,
+       int src, sljit_w srcw)
+{
+       sljit_ub *buf;
+
+       if (src >= SLJIT_FLOAT_REG1 && src <= SLJIT_FLOAT_REG4) {
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
+               FAIL_IF(!buf);
+               INC_SIZE(2);
+               *buf++ = 0xd9;
+               *buf = 0xc0 + src - 1;
+               return SLJIT_SUCCESS;
+       }
+
+       buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
+       FAIL_IF(!buf);
+       *buf = 0xdd;
+       return SLJIT_SUCCESS;
+}
+
+static int emit_fop(struct sljit_compiler *compiler,
+       sljit_ub st_arg, sljit_ub st_arg2,
+       sljit_ub m64fp_arg, sljit_ub m64fp_arg2,
+       int src, sljit_w srcw)
+{
+       sljit_ub *buf;
+
+       if (src >= SLJIT_FLOAT_REG1 && src <= SLJIT_FLOAT_REG4) {
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
+               FAIL_IF(!buf);
+               INC_SIZE(2);
+               *buf++ = st_arg;
+               *buf = st_arg2 + src;
+               return SLJIT_SUCCESS;
+       }
+
+       buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
+       FAIL_IF(!buf);
+       *buf++ = m64fp_arg;
+       *buf |= m64fp_arg2;
+       return SLJIT_SUCCESS;
+}
+
+static int emit_fop_regs(struct sljit_compiler *compiler,
+       sljit_ub st_arg, sljit_ub st_arg2,
+       int src)
+{
+       sljit_ub *buf;
+
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
+       FAIL_IF(!buf);
+       INC_SIZE(2);
+       *buf++ = st_arg;
+       *buf = st_arg2 + src;
+       return SLJIT_SUCCESS;
+}
+
+#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
+#else
+static int sljit_emit_fpu_fop1(struct sljit_compiler *compiler, int op,
+#endif
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+#if !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       sljit_ub *buf;
+#endif
+
+       CHECK_ERROR();
+       check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       compiler->mode32 = 1;
+#endif
+
+       if (GET_OPCODE(op) == SLJIT_FCMP) {
+               compiler->flags_saved = 0;
+#if !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+               FAIL_IF(emit_fld(compiler, dst, dstw));
+               FAIL_IF(emit_fop(compiler, 0xd8, 0xd8, 0xdc, 0x3 << 3, src, srcw));
+
+               /* Copy flags. */
+               EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG1, 0);
+               buf = (sljit_ub*)ensure_buf(compiler, 1 + 3);
+               FAIL_IF(!buf);
+               INC_SIZE(3);
+               *buf++ = 0xdf;
+               *buf++ = 0xe0;
+               /* Note: lahf is not supported on all x86-64 architectures. */
+               *buf++ = 0x9e;
+               EMIT_MOV(compiler, SLJIT_TEMPORARY_REG1, 0, TMP_REGISTER, 0);
+#else
+               if (src >= SLJIT_FLOAT_REG1 && src <= SLJIT_FLOAT_REG4) {
+                       FAIL_IF(emit_fld(compiler, dst, dstw));
+                       FAIL_IF(emit_fop_regs(compiler, 0xdf, 0xe8, src));
+               } else {
+                       FAIL_IF(emit_fld(compiler, src, srcw));
+                       FAIL_IF(emit_fld(compiler, dst + ((dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) ? 1 : 0), dstw));
+                       FAIL_IF(emit_fop_regs(compiler, 0xdf, 0xe8, src));
+                       FAIL_IF(emit_fop_regs(compiler, 0xdd, 0xd8, 0));
+               }
+#endif
+               return SLJIT_SUCCESS;
+       }
+
+       FAIL_IF(emit_fld(compiler, src, srcw));
+
+       switch (op) {
+       case SLJIT_FNEG:
+               FAIL_IF(emit_fop_regs(compiler, 0xd9, 0xe0, 0));
+               break;
+       case SLJIT_FABS:
+               FAIL_IF(emit_fop_regs(compiler, 0xd9, 0xe1, 0));
+               break;
+       }
+
+       FAIL_IF(emit_fop(compiler, 0xdd, 0xd8, 0xdd, 0x3 << 3, dst, dstw));
+
+       return SLJIT_SUCCESS;
+}
+
+#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
+#else
+static int sljit_emit_fpu_fop2(struct sljit_compiler *compiler, int op,
+#endif
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       CHECK_ERROR();
+       check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       compiler->mode32 = 1;
+#endif
+
+       if (src1 >= SLJIT_FLOAT_REG1 && src1 <= SLJIT_FLOAT_REG4 && dst == src1) {
+               FAIL_IF(emit_fld(compiler, src2, src2w));
+
+               switch (op) {
+               case SLJIT_FADD:
+                       FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc0, src1));
+                       break;
+               case SLJIT_FSUB:
+                       FAIL_IF(emit_fop_regs(compiler, 0xde, 0xe8, src1));
+                       break;
+               case SLJIT_FMUL:
+                       FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc8, src1));
+                       break;
+               case SLJIT_FDIV:
+                       FAIL_IF(emit_fop_regs(compiler, 0xde, 0xf8, src1));
+                       break;
+               }
+               return SLJIT_SUCCESS;
+       }
+
+       FAIL_IF(emit_fld(compiler, src1, src1w));
+
+       if (src2 >= SLJIT_FLOAT_REG1 && src2 <= SLJIT_FLOAT_REG4 && dst == src2) {
+               switch (op) {
+               case SLJIT_FADD:
+                       FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc0, src2));
+                       break;
+               case SLJIT_FSUB:
+                       FAIL_IF(emit_fop_regs(compiler, 0xde, 0xe0, src2));
+                       break;
+               case SLJIT_FMUL:
+                       FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc8, src2));
+                       break;
+               case SLJIT_FDIV:
+                       FAIL_IF(emit_fop_regs(compiler, 0xde, 0xf0, src2));
+                       break;
+               }
+               return SLJIT_SUCCESS;
+       }
+
+       switch (op) {
+       case SLJIT_FADD:
+               FAIL_IF(emit_fop(compiler, 0xd8, 0xc0, 0xdc, 0x0 << 3, src2, src2w));
+               break;
+       case SLJIT_FSUB:
+               FAIL_IF(emit_fop(compiler, 0xd8, 0xe0, 0xdc, 0x4 << 3, src2, src2w));
+               break;
+       case SLJIT_FMUL:
+               FAIL_IF(emit_fop(compiler, 0xd8, 0xc8, 0xdc, 0x1 << 3, src2, src2w));
+               break;
+       case SLJIT_FDIV:
+               FAIL_IF(emit_fop(compiler, 0xd8, 0xf0, 0xdc, 0x6 << 3, src2, src2w));
+               break;
+       }
+
+       FAIL_IF(emit_fop(compiler, 0xdd, 0xd8, 0xdd, 0x3 << 3, dst, dstw));
+
+       return SLJIT_SUCCESS;
+}
+#endif
+
+#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO)
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src, sljit_w srcw)
+{
+       if (sse2_available)
+               return sljit_emit_sse2_fop1(compiler, op, dst, dstw, src, srcw);
+       else
+               return sljit_emit_fpu_fop1(compiler, op, dst, dstw, src, srcw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
+       int dst, sljit_w dstw,
+       int src1, sljit_w src1w,
+       int src2, sljit_w src2w)
+{
+       if (sse2_available)
+               return sljit_emit_sse2_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+       else
+               return sljit_emit_fpu_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+}
+
+#endif
+
+/* --------------------------------------------------------------------- */
+/*  Conditional instructions                                             */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+       sljit_ub *buf;
+       struct sljit_label *label;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_label(compiler);
+
+       /* We should restore the flags before the label,
+          since other taken jumps has their own flags as well. */
+       if (SLJIT_UNLIKELY(compiler->flags_saved))
+               PTR_FAIL_IF(emit_restore_flags(compiler, 0));
+
+       if (compiler->last_label && compiler->last_label->size == compiler->size)
+               return compiler->last_label;
+
+       label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+       PTR_FAIL_IF(!label);
+       set_label(label, compiler);
+
+       buf = (sljit_ub*)ensure_buf(compiler, 2);
+       PTR_FAIL_IF(!buf);
+
+       *buf++ = 0;
+       *buf++ = 0;
+
+       return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type)
+{
+       sljit_ub *buf;
+       struct sljit_jump *jump;
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_jump(compiler, type);
+
+       if (SLJIT_UNLIKELY(compiler->flags_saved)) {
+               if ((type & 0xff) <= SLJIT_JUMP)
+                       PTR_FAIL_IF(emit_restore_flags(compiler, 0));
+               compiler->flags_saved = 0;
+       }
+
+       jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+       PTR_FAIL_IF_NULL(jump);
+       set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+       type &= 0xff;
+
+       if (type >= SLJIT_CALL1)
+               PTR_FAIL_IF(call_with_args(compiler, type));
+
+       /* Worst case size. */
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       compiler->size += (type >= SLJIT_JUMP) ? 5 : 6;
+#else
+       compiler->size += (type >= SLJIT_JUMP) ? (10 + 3) : (2 + 10 + 3);
+#endif
+
+       buf = (sljit_ub*)ensure_buf(compiler, 2);
+       PTR_FAIL_IF_NULL(buf);
+
+       *buf++ = 0;
+       *buf++ = type + 4;
+       return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
+{
+       sljit_ub *code;
+       struct sljit_jump *jump;
+
+       CHECK_ERROR();
+       check_sljit_emit_ijump(compiler, type, src, srcw);
+
+       CHECK_EXTRA_REGS(src, srcw, (void)0);
+       if (SLJIT_UNLIKELY(compiler->flags_saved)) {
+               if (type <= SLJIT_JUMP)
+                       FAIL_IF(emit_restore_flags(compiler, 0));
+               compiler->flags_saved = 0;
+       }
+
+       if (type >= SLJIT_CALL1) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+               if (src == SLJIT_TEMPORARY_REG3) {
+                       EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0);
+                       src = TMP_REGISTER;
+               }
+               if ((src & SLJIT_MEM) && (src & 0xf) == SLJIT_LOCALS_REG && type >= SLJIT_CALL3) {
+                       if (src & 0xf0) {
+                               EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
+                               src = TMP_REGISTER;
+                       }
+                       else
+                               srcw += sizeof(sljit_w);
+               }
+#else
+               if ((src & SLJIT_MEM) && (src & 0xf) == SLJIT_LOCALS_REG) {
+                       if (src & 0xf0) {
+                               EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
+                               src = TMP_REGISTER;
+                       }
+                       else
+                               srcw += sizeof(sljit_w) * (type - SLJIT_CALL0);
+               }
+#endif
+#endif
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && defined(_WIN64)
+               if (src == SLJIT_TEMPORARY_REG3) {
+                       EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0);
+                       src = TMP_REGISTER;
+               }
+#endif
+               FAIL_IF(call_with_args(compiler, type));
+       }
+
+       if (src == SLJIT_IMM) {
+               jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+               FAIL_IF_NULL(jump);
+               set_jump(jump, compiler, JUMP_ADDR);
+               jump->u.target = srcw;
+
+               /* Worst case size. */
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+               compiler->size += 5;
+#else
+               compiler->size += 10 + 3;
+#endif
+
+               code = (sljit_ub*)ensure_buf(compiler, 2);
+               FAIL_IF_NULL(code);
+
+               *code++ = 0;
+               *code++ = type + 4;
+       }
+       else {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+               /* REX_W is not necessary (src is not immediate). */
+               compiler->mode32 = 1;
+#endif
+               code = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
+               FAIL_IF(!code);
+               *code++ = 0xff;
+               *code |= (type >= SLJIT_FAST_CALL) ? (2 << 3) : (4 << 3);
+       }
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type)
+{
+       sljit_ub *buf;
+       sljit_ub cond_set = 0;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       int reg;
+#endif
+
+       CHECK_ERROR();
+       check_sljit_emit_cond_value(compiler, op, dst, dstw, type);
+
+       if (dst == SLJIT_UNUSED)
+               return SLJIT_SUCCESS;
+
+       CHECK_EXTRA_REGS(dst, dstw, (void)0);
+       if (SLJIT_UNLIKELY(compiler->flags_saved))
+               FAIL_IF(emit_restore_flags(compiler, 0));
+
+       switch (type) {
+       case SLJIT_C_EQUAL:
+       case SLJIT_C_FLOAT_EQUAL:
+               cond_set = 0x94;
+               break;
+
+       case SLJIT_C_NOT_EQUAL:
+       case SLJIT_C_FLOAT_NOT_EQUAL:
+               cond_set = 0x95;
+               break;
+
+       case SLJIT_C_LESS:
+       case SLJIT_C_FLOAT_LESS:
+               cond_set = 0x92;
+               break;
+
+       case SLJIT_C_GREATER_EQUAL:
+       case SLJIT_C_FLOAT_GREATER_EQUAL:
+               cond_set = 0x93;
+               break;
+
+       case SLJIT_C_GREATER:
+       case SLJIT_C_FLOAT_GREATER:
+               cond_set = 0x97;
+               break;
+
+       case SLJIT_C_LESS_EQUAL:
+       case SLJIT_C_FLOAT_LESS_EQUAL:
+               cond_set = 0x96;
+               break;
+
+       case SLJIT_C_SIG_LESS:
+               cond_set = 0x9c;
+               break;
+
+       case SLJIT_C_SIG_GREATER_EQUAL:
+               cond_set = 0x9d;
+               break;
+
+       case SLJIT_C_SIG_GREATER:
+               cond_set = 0x9f;
+               break;
+
+       case SLJIT_C_SIG_LESS_EQUAL:
+               cond_set = 0x9e;
+               break;
+
+       case SLJIT_C_OVERFLOW:
+       case SLJIT_C_MUL_OVERFLOW:
+               cond_set = 0x90;
+               break;
+
+       case SLJIT_C_NOT_OVERFLOW:
+       case SLJIT_C_MUL_NOT_OVERFLOW:
+               cond_set = 0x91;
+               break;
+
+       case SLJIT_C_FLOAT_NAN:
+               cond_set = 0x9a;
+               break;
+
+       case SLJIT_C_FLOAT_NOT_NAN:
+               cond_set = 0x9b;
+               break;
+       }
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       reg = (op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REGISTER;
+
+       buf = (sljit_ub*)ensure_buf(compiler, 1 + 4 + 4);
+       FAIL_IF(!buf);
+       INC_SIZE(4 + 4);
+       /* Set low register to conditional flag. */
+       *buf++ = (reg_map[reg] <= 7) ? 0x40 : REX_B;
+       *buf++ = 0x0f;
+       *buf++ = cond_set;
+       *buf++ = 0xC0 | reg_lmap[reg];
+       *buf++ = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R));
+       *buf++ = 0x0f;
+       *buf++ = 0xb6;
+       *buf = 0xC0 | (reg_lmap[reg] << 3) | reg_lmap[reg];
+
+       if (reg == TMP_REGISTER) {
+               if (op == SLJIT_MOV) {
+                       compiler->mode32 = 0;
+                       EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
+               }
+               else {
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+                       compiler->skip_checks = 1;
+#endif
+                       return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REGISTER, 0);
+               }
+       }
+#else
+       if (op == SLJIT_MOV) {
+               if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_TEMPORARY_REG3) {
+                       buf = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3);
+                       FAIL_IF(!buf);
+                       INC_SIZE(3 + 3);
+                       /* Set low byte to conditional flag. */
+                       *buf++ = 0x0f;
+                       *buf++ = cond_set;
+                       *buf++ = 0xC0 | reg_map[dst];
+
+                       *buf++ = 0x0f;
+                       *buf++ = 0xb6;
+                       *buf = 0xC0 | (reg_map[dst] << 3) | reg_map[dst];
+               }
+               else {
+                       EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG1, 0);
+
+                       buf = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3);
+                       FAIL_IF(!buf);
+                       INC_SIZE(3 + 3);
+                       /* Set al to conditional flag. */
+                       *buf++ = 0x0f;
+                       *buf++ = cond_set;
+                       *buf++ = 0xC0;
+
+                       *buf++ = 0x0f;
+                       *buf++ = 0xb6;
+                       if (dst >= SLJIT_SAVED_REG1 && dst <= SLJIT_NO_REGISTERS)
+                               *buf = 0xC0 | (reg_map[dst] << 3);
+                       else {
+                               *buf = 0xC0;
+                               EMIT_MOV(compiler, dst, dstw, SLJIT_TEMPORARY_REG1, 0);
+                       }
+
+                       EMIT_MOV(compiler, SLJIT_TEMPORARY_REG1, 0, TMP_REGISTER, 0);
+               }
+       }
+       else {
+               if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_TEMPORARY_REG3) {
+                       EMIT_MOV(compiler, TMP_REGISTER, 0, dst, 0);
+                       buf = (sljit_ub*)ensure_buf(compiler, 1 + 3);
+                       FAIL_IF(!buf);
+                       INC_SIZE(3);
+
+                       *buf++ = 0x0f;
+                       *buf++ = cond_set;
+                       *buf++ = 0xC0 | reg_map[dst];
+               }
+               else {
+                       EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG1, 0);
+
+                       buf = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3 + 1);
+                       FAIL_IF(!buf);
+                       INC_SIZE(3 + 3 + 1);
+                       /* Set al to conditional flag. */
+                       *buf++ = 0x0f;
+                       *buf++ = cond_set;
+                       *buf++ = 0xC0;
+
+                       *buf++ = 0x0f;
+                       *buf++ = 0xb6;
+                       *buf++ = 0xC0;
+
+                       *buf++ = 0x90 + reg_map[TMP_REGISTER];
+               }
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+               compiler->skip_checks = 1;
+#endif
+               return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REGISTER, 0);
+       }
+#endif
+
+       return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value)
+{
+       sljit_ub *buf;
+       struct sljit_const *const_;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       int reg;
+#endif
+
+       CHECK_ERROR_PTR();
+       check_sljit_emit_const(compiler, dst, dstw, init_value);
+
+       CHECK_EXTRA_REGS(dst, dstw, (void)0);
+
+       const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+       PTR_FAIL_IF(!const_);
+       set_const(const_, compiler);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       compiler->mode32 = 0;
+       reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REGISTER;
+
+       if (emit_load_imm64(compiler, reg, init_value))
+               return NULL;
+#else
+       if (dst == SLJIT_UNUSED)
+               dst = TMP_REGISTER;
+
+       if (emit_mov(compiler, dst, dstw, SLJIT_IMM, init_value))
+               return NULL;
+#endif
+
+       buf = (sljit_ub*)ensure_buf(compiler, 2);
+       PTR_FAIL_IF(!buf);
+
+       *buf++ = 0;
+       *buf++ = 1;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+       if (reg == TMP_REGISTER && dst != SLJIT_UNUSED)
+               if (emit_mov(compiler, dst, dstw, TMP_REGISTER, 0))
+                       return NULL;
+#endif
+
+       return const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
+{
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+       *(sljit_w*)addr = new_addr - (addr + 4);
+#else
+       *(sljit_uw*)addr = new_addr;
+#endif
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
+{
+       *(sljit_w*)addr = new_constant;
+}
diff --git a/src/3rdparty/pcre/sljit/sljitUtils.c b/src/3rdparty/pcre/sljit/sljitUtils.c
new file mode 100644 (file)
index 0000000..98beaa0
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.
+ */
+
+/* ------------------------------------------------------------------------ */
+/*  Locks                                                                   */
+/* ------------------------------------------------------------------------ */
+
+#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) || (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
+
+#ifdef _WIN32
+
+#include "windows.h"
+
+#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
+
+static HANDLE allocator_mutex = 0;
+
+static SLJIT_INLINE void allocator_grab_lock(void)
+{
+       /* No idea what to do if an error occures. Static mutexes should never fail... */
+       if (!allocator_mutex)
+               allocator_mutex = CreateMutex(NULL, TRUE, NULL);
+       else
+               WaitForSingleObject(allocator_mutex, INFINITE);
+}
+
+static SLJIT_INLINE void allocator_release_lock(void)
+{
+       ReleaseMutex(allocator_mutex);
+}
+
+#endif /* SLJIT_EXECUTABLE_ALLOCATOR */
+
+#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
+
+static HANDLE global_mutex = 0;
+
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
+{
+       /* No idea what to do if an error occures. Static mutexes should never fail... */
+       if (!global_mutex)
+               global_mutex = CreateMutex(NULL, TRUE, NULL);
+       else
+               WaitForSingleObject(global_mutex, INFINITE);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
+{
+       ReleaseMutex(global_mutex);
+}
+
+#endif /* SLJIT_UTIL_GLOBAL_LOCK */
+
+#else /* _WIN32 */
+
+#include "pthread.h"
+
+#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
+
+static pthread_mutex_t allocator_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static SLJIT_INLINE void allocator_grab_lock(void)
+{
+       pthread_mutex_lock(&allocator_mutex);
+}
+
+static SLJIT_INLINE void allocator_release_lock(void)
+{
+       pthread_mutex_unlock(&allocator_mutex);
+}
+
+#endif /* SLJIT_EXECUTABLE_ALLOCATOR */
+
+#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
+
+static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
+{
+       pthread_mutex_lock(&global_mutex);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
+{
+       pthread_mutex_unlock(&global_mutex);
+}
+
+#endif /* SLJIT_UTIL_GLOBAL_LOCK */
+
+#endif /* _WIN32 */
+
+/* ------------------------------------------------------------------------ */
+/*  Stack                                                                   */
+/* ------------------------------------------------------------------------ */
+
+#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
+
+#ifdef _WIN32
+#include "windows.h"
+#else
+#include <sys/mman.h>
+#include <unistd.h>
+#endif
+
+/* Planning to make it even more clever in the future. */
+static sljit_w sljit_page_align = 0;
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit)
+{
+       struct sljit_stack *stack;
+       union {
+               void *ptr;
+               sljit_uw uw;
+       } base;
+#ifdef _WIN32
+       SYSTEM_INFO si;
+#endif
+
+       if (limit > max_limit || limit < 1)
+               return NULL;
+
+#ifdef _WIN32
+       if (!sljit_page_align) {
+               GetSystemInfo(&si);
+               sljit_page_align = si.dwPageSize - 1;
+       }
+#else
+       if (!sljit_page_align) {
+               sljit_page_align = sysconf(_SC_PAGESIZE);
+               /* Should never happen. */
+               if (sljit_page_align < 0)
+                       sljit_page_align = 4096;
+               sljit_page_align--;
+       }
+#endif
+
+       /* Align limit and max_limit. */
+       max_limit = (max_limit + sljit_page_align) & ~sljit_page_align;
+
+       stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack));
+       if (!stack)
+               return NULL;
+
+#ifdef _WIN32
+       base.ptr = VirtualAlloc(0, max_limit, MEM_RESERVE, PAGE_READWRITE);
+       if (!base.ptr) {
+               SLJIT_FREE(stack);
+               return NULL;
+       }
+       stack->base = base.uw;
+       stack->limit = stack->base;
+       stack->max_limit = stack->base + max_limit;
+       if (sljit_stack_resize(stack, stack->base + limit)) {
+               sljit_free_stack(stack);
+               return NULL;
+       }
+#else
+       base.ptr = mmap(0, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+       if (base.ptr == MAP_FAILED) {
+               SLJIT_FREE(stack);
+               return NULL;
+       }
+       stack->base = base.uw;
+       stack->limit = stack->base + limit;
+       stack->max_limit = stack->base + max_limit;
+#endif
+       stack->top = stack->base;
+       return stack;
+}
+
+#undef PAGE_ALIGN
+
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* stack)
+{
+#ifdef _WIN32
+       VirtualFree((void*)stack->base, 0, MEM_RELEASE);
+#else
+       munmap((void*)stack->base, stack->max_limit - stack->base);
+#endif
+       SLJIT_FREE(stack);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_w SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit)
+{
+       sljit_uw aligned_old_limit;
+       sljit_uw aligned_new_limit;
+
+       if ((new_limit > stack->max_limit) || (new_limit < stack->base))
+               return -1;
+#ifdef _WIN32
+       aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align;
+       aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align;
+       if (aligned_new_limit != aligned_old_limit) {
+               if (aligned_new_limit > aligned_old_limit) {
+                       if (!VirtualAlloc((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MEM_COMMIT, PAGE_READWRITE))
+                               return -1;
+               }
+               else {
+                       if (!VirtualFree((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MEM_DECOMMIT))
+                               return -1;
+               }
+       }
+       stack->limit = new_limit;
+       return 0;
+#else
+       if (new_limit >= stack->limit) {
+               stack->limit = new_limit;
+               return 0;
+       }
+       aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align;
+       aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align;
+       if (aligned_new_limit < aligned_old_limit)
+               madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MADV_DONTNEED);
+       stack->limit = new_limit;
+       return 0;
+#endif
+}
+
+#endif /* SLJIT_UTIL_STACK */
+
+#endif
diff --git a/src/3rdparty/pcre/ucp.h b/src/3rdparty/pcre/ucp.h
new file mode 100644 (file)
index 0000000..34077fe
--- /dev/null
@@ -0,0 +1,165 @@
+/*************************************************
+*          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. */
+
+/* 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 types. */
+
+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 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
+};
+
+#endif
+
+/* End of ucp.h */