diff --git a/Library/pcre-8.10/AUTHORS b/Library/pcre-8.10/AUTHORS new file mode 100644 index 00000000..88db849d --- /dev/null +++ b/Library/pcre-8.10/AUTHORS @@ -0,0 +1,23 @@ +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-2010 University of Cambridge +All rights reserved + + +THE C++ WRAPPER LIBRARY +----------------------- + +Written by: Google Inc. + +Copyright (c) 2007-2010 Google Inc +All rights reserved + +#### diff --git a/Library/pcre-8.10/LICENCE b/Library/pcre-8.10/LICENCE new file mode 100644 index 00000000..0dd22571 --- /dev/null +++ b/Library/pcre-8.10/LICENCE @@ -0,0 +1,68 @@ +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. + + +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-2010 University of Cambridge +All rights reserved. + + +THE C++ WRAPPER FUNCTIONS +------------------------- + +Contributed by: Google Inc. + +Copyright (c) 2007-2010, 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/Library/pcre-8.10/config.h b/Library/pcre-8.10/config.h new file mode 100644 index 00000000..73ab0258 --- /dev/null +++ b/Library/pcre-8.10/config.h @@ -0,0 +1,329 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + + +/* On Unix-like systems config.h.in is converted by "configure" into config.h. +Some other environments also support the use of "configure". PCRE is written in +Standard C, but there are a few non-standard things it can cope with, allowing +it to run on SunOS4 and other "close to standard" systems. + +If you are going to build PCRE "by hand" on a system without "configure" you +should copy the distributed config.h.generic to config.h, and then set up the +macro definitions the way you need them. You must then add -DHAVE_CONFIG_H to +all of your compile commands, so that config.h is included at the start of +every source. + +Alternatively, you can avoid editing by using -D on the compiler command line +to set the macro values. In this case, you do not have to set -DHAVE_CONFIG_H. + +PCRE uses memmove() if HAVE_MEMMOVE is set to 1; otherwise it uses bcopy() if +HAVE_BCOPY is set to 1. If your system has neither bcopy() nor memmove(), set +them both to 0; an emulation function will be used. */ + +/* By default, the \R escape sequence matches any Unicode line ending + character or sequence of characters. If BSR_ANYCRLF is defined, this is + changed so that backslash-R matches only CR, LF, or CRLF. The build- time + default can be overridden by the user of PCRE at runtime. On systems that + support it, "configure" can be used to override the default. */ +/* #undef BSR_ANYCRLF */ + +/* If you are compiling for a system that uses EBCDIC instead of ASCII + character codes, define this macro as 1. On systems that can use + "configure", this can be done via --enable-ebcdic. PCRE will then assume + that all input strings are in EBCDIC. If you do not define this macro, PCRE + will assume input strings are ASCII or UTF-8 Unicode. It is not possible to + build a version of PCRE that supports both EBCDIC and UTF-8. */ +/* #undef EBCDIC */ + +/* Define to 1 if you have the `bcopy' function. */ +#ifndef HAVE_BCOPY +#define HAVE_BCOPY 0 +#endif + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_BITS_TYPE_TRAITS_H */ + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_BZLIB_H +#define HAVE_BZLIB_H 0 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_DIRENT_H +#define HAVE_DIRENT_H 0 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_DLFCN_H +#define HAVE_DLFCN_H 0 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_INTTYPES_H +#define HAVE_INTTYPES_H 0 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_LIMITS_H +#define HAVE_LIMITS_H 1 +#endif + +/* Define to 1 if the system has the type `long long'. */ +#ifndef HAVE_LONG_LONG +#define HAVE_LONG_LONG 1 +#endif + +/* Define to 1 if you have the `memmove' function. */ +#ifndef HAVE_MEMMOVE +#define HAVE_MEMMOVE 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_MEMORY_H +#define HAVE_MEMORY_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_READLINE_HISTORY_H +#define HAVE_READLINE_HISTORY_H 0 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_READLINE_READLINE_H +#define HAVE_READLINE_READLINE_H 0 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_STDINT_H +#define HAVE_STDINT_H 0 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_STDLIB_H +#define HAVE_STDLIB_H 1 +#endif + +/* Define to 1 if you have the `strerror' function. */ +#ifndef HAVE_STRERROR +#define HAVE_STRERROR 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_STRING +#define HAVE_STRING 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_STRINGS_H +#define HAVE_STRINGS_H 0 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_STRING_H +#define HAVE_STRING_H 1 +#endif + +/* Define to 1 if you have `strtoimax'. */ +/* #undef HAVE_STRTOIMAX */ + +/* Define to 1 if you have `strtoll'. */ +/* #undef HAVE_STRTOLL */ + +/* Define to 1 if you have `strtoq'. */ +#ifndef HAVE_STRTOQ +#define HAVE_STRTOQ 0 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_SYS_STAT_H +#define HAVE_SYS_STAT_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_SYS_TYPES_H +#define HAVE_SYS_TYPES_H 1 +#endif + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TYPE_TRAITS_H */ + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_UNISTD_H +#define HAVE_UNISTD_H 0 +#endif + +/* Define to 1 if the system has the type `unsigned long long'. */ +#ifndef HAVE_UNSIGNED_LONG_LONG +#define HAVE_UNSIGNED_LONG_LONG 1 +#endif + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the header file. */ +#ifndef HAVE_ZLIB_H +#define HAVE_ZLIB_H 0 +#endif + +/* Define to 1 if you have `_strtoi64'. */ +/* #undef HAVE__STRTOI64 */ + +/* The value of LINK_SIZE determines the number of bytes used to store links + as offsets within the compiled regex. The default is 2, which allows for + compiled patterns up to 64K long. This covers the vast majority of cases. + However, PCRE can also be compiled to use 3 or 4 bytes instead. This allows + for longer patterns in extreme cases. On systems that support it, + "configure" can be used to override this default. */ +#ifndef LINK_SIZE +#define LINK_SIZE 2 +#endif + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#ifndef LT_OBJDIR +#define LT_OBJDIR ".libs/" +#endif + +/* The value of MATCH_LIMIT determines the default number of times the + internal match() function can be called during a single execution of + pcre_exec(). There is a runtime interface for setting a different limit. + The limit exists in order to catch runaway regular expressions that take + for ever to determine that they do not match. The default is set very large + so that it does not accidentally catch legitimate cases. On systems that + support it, "configure" can be used to override this default default. */ +#ifndef MATCH_LIMIT +#define MATCH_LIMIT 10000000 +#endif + +/* The above limit applies to all calls of match(), whether or not they + increase the recursion depth. In some environments it is desirable to limit + the depth of recursive calls of match() more strictly, in order to restrict + the maximum amount of stack (or heap, if NO_RECURSE is defined) that is + used. The value of MATCH_LIMIT_RECURSION applies only to recursive calls of + match(). To have any useful effect, it must be less than the value of + MATCH_LIMIT. The default is to use the same value as MATCH_LIMIT. There is + a runtime method for setting a different limit. On systems that support it, + "configure" can be used to override the default. */ +#ifndef MATCH_LIMIT_RECURSION +#define MATCH_LIMIT_RECURSION MATCH_LIMIT +#endif + +/* This limit is parameterized just in case anybody ever wants to change it. + Care must be taken if it is increased, because it guards against integer + overflow caused by enormously large patterns. */ +#ifndef MAX_NAME_COUNT +#define MAX_NAME_COUNT 10000 +#endif + +/* This limit is parameterized just in case anybody ever wants to change it. + Care must be taken if it is increased, because it guards against integer + overflow caused by enormously large patterns. */ +#ifndef MAX_NAME_SIZE +#define MAX_NAME_SIZE 32 +#endif + +/* The value of NEWLINE determines the newline character sequence. On systems + that support it, "configure" can be used to override the default, which is + 10. The possible values are 10 (LF), 13 (CR), 3338 (CRLF), -1 (ANY), or -2 + (ANYCRLF). */ +#ifndef NEWLINE +#define NEWLINE 10 +#endif + +/* PCRE uses recursive function calls to handle backtracking while matching. + This can sometimes be a problem on systems that have stacks of limited + size. Define NO_RECURSE to get a version that doesn't use recursion in the + match() function; instead it creates its own stack by steam using + pcre_recurse_malloc() to obtain memory from the heap. For more detail, see + the comments and other stuff just above the match() function. On systems + that support it, "configure" can be used to set this in the Makefile (use + --disable-stack-for-recursion). */ +/* #undef NO_RECURSE */ + +/* Name of package */ +#define PACKAGE "pcre" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "PCRE" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "PCRE 8.10" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "pcre" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "8.10" + + +/* If you are compiling for a system other than a Unix-like system or + Win32, and it needs some magic to be inserted before the definition + of a function that is exported by the library, define this macro to + contain the relevant magic. If you do not define this macro, it + defaults to "extern" for a C compiler and "extern C" for a C++ + compiler on non-Win32 systems. This macro apears at the start of + every exported function that is part of the external API. It does + not appear on functions that are "external" in the C sense, but + which are internal to the library. */ +/* #undef PCRE_EXP_DEFN */ + +/* Define if linking statically (TODO: make nice with Libtool) */ +/* #undef PCRE_STATIC */ + +/* When calling PCRE via the POSIX interface, additional working storage is + required for holding the pointers to capturing substrings because PCRE + requires three integers per substring, whereas the POSIX interface provides + only two. If the number of expected substrings is small, the wrapper + function uses space on the stack, because this is faster than using + malloc() for each call. The threshold above which the stack is no longer + used is defined by POSIX_MALLOC_THRESHOLD. On systems that support it, + "configure" can be used to override this default. */ +#ifndef POSIX_MALLOC_THRESHOLD +#define POSIX_MALLOC_THRESHOLD 10 +#endif + +/* Define to 1 if you have the ANSI C header files. */ +#ifndef STDC_HEADERS +#define STDC_HEADERS 1 +#endif + +/* Define to allow pcregrep to be linked with libbz2, so that it is able to + handle .bz2 files. */ +/* #undef SUPPORT_LIBBZ2 */ + +/* Define to allow pcretest to be linked with libreadline. */ +/* #undef SUPPORT_LIBREADLINE */ + +/* Define to allow pcregrep to be linked with libz, so that it is able to + handle .gz files. */ +/* #undef SUPPORT_LIBZ */ + +/* Define to enable support for Unicode properties */ +/* #undef SUPPORT_UCP */ + +/* Define to enable support for the UTF-8 Unicode encoding. This will work + even in an EBCDIC environment, but it is incompatible with the EBCDIC + macro. That is, PCRE can support *either* EBCDIC code *or* ASCII/UTF-8, but + not both at once. */ +/* #undef SUPPORT_UTF8 */ + +/* Version number of package */ +#ifndef VERSION +#define VERSION "8.10" +#endif + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to the type of a signed integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +/* #undef int64_t */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ diff --git a/Library/pcre-8.10/dftables.c b/Library/pcre-8.10/dftables.c new file mode 100644 index 00000000..12e1af14 --- /dev/null +++ b/Library/pcre-8.10/dftables.c @@ -0,0 +1,199 @@ +/************************************************* +* 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-2008 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 is a freestanding support program to generate a file containing +character tables for PCRE. The tables are built according to the current +locale. Now that pcre_maketables is a function visible to the outside world, we +make use of its code from here in order to be consistent. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include "pcre_internal.h" + +#define DFTABLES /* pcre_maketables.c notices this */ +#include "pcre_maketables.c" + + +int main(int argc, char **argv) +{ +FILE *f; +int i = 1; +const unsigned char *tables; +const unsigned char *base_of_tables; + +/* By default, the default C locale is used rather than what the building user +happens to have set. However, if the -L option is given, set the locale from +the LC_xxx environment variables. */ + +if (argc > 1 && strcmp(argv[1], "-L") == 0) + { + setlocale(LC_ALL, ""); /* Set from environment variables */ + i++; + } + +if (argc < i + 1) + { + fprintf(stderr, "dftables: one filename argument is required\n"); + return 1; + } + +tables = pcre_maketables(); +base_of_tables = tables; + +f = fopen(argv[i], "wb"); +if (f == NULL) + { + fprintf(stderr, "dftables: failed to open %s for writing\n", argv[1]); + return 1; + } + +/* There are several fprintf() calls here, because gcc in pedantic mode +complains about the very long string otherwise. */ + +fprintf(f, + "/*************************************************\n" + "* Perl-Compatible Regular Expressions *\n" + "*************************************************/\n\n" + "/* This file was automatically written by the dftables auxiliary\n" + "program. It contains character tables that are used when no external\n" + "tables are passed to PCRE by the application that calls it. The tables\n" + "are used only for characters whose code values are less than 256.\n\n"); +fprintf(f, + "The following #includes are present because without them gcc 4.x may remove\n" + "the array definition from the final binary if PCRE is built into a static\n" + "library and dead code stripping is activated. This leads to link errors.\n" + "Pulling in the header ensures that the array gets flagged as \"someone\n" + "outside this compilation unit might reference this\" and so it will always\n" + "be supplied to the linker. */\n\n" + "#ifdef HAVE_CONFIG_H\n" + "#include \"config.h\"\n" + "#endif\n\n" + "#include \"pcre_internal.h\"\n\n"); +fprintf(f, + "const unsigned char _pcre_default_tables[] = {\n\n" + "/* This table is a lower casing table. */\n\n"); + +fprintf(f, " "); +for (i = 0; i < 256; i++) + { + if ((i & 7) == 0 && i != 0) fprintf(f, "\n "); + fprintf(f, "%3d", *tables++); + if (i != 255) fprintf(f, ","); + } +fprintf(f, ",\n\n"); + +fprintf(f, "/* This table is a case flipping table. */\n\n"); + +fprintf(f, " "); +for (i = 0; i < 256; i++) + { + if ((i & 7) == 0 && i != 0) fprintf(f, "\n "); + fprintf(f, "%3d", *tables++); + if (i != 255) fprintf(f, ","); + } +fprintf(f, ",\n\n"); + +fprintf(f, + "/* This table contains bit maps for various character classes.\n" + "Each map is 32 bytes long and the bits run from the least\n" + "significant end of each byte. The classes that have their own\n" + "maps are: space, xdigit, digit, upper, lower, word, graph\n" + "print, punct, and cntrl. Other classes are built from combinations. */\n\n"); + +fprintf(f, " "); +for (i = 0; i < cbit_length; i++) + { + if ((i & 7) == 0 && i != 0) + { + if ((i & 31) == 0) fprintf(f, "\n"); + fprintf(f, "\n "); + } + fprintf(f, "0x%02x", *tables++); + if (i != cbit_length - 1) fprintf(f, ","); + } +fprintf(f, ",\n\n"); + +fprintf(f, + "/* This table identifies various classes of character by individual bits:\n" + " 0x%02x white space character\n" + " 0x%02x letter\n" + " 0x%02x decimal digit\n" + " 0x%02x hexadecimal digit\n" + " 0x%02x alphanumeric or '_'\n" + " 0x%02x regular expression metacharacter or binary zero\n*/\n\n", + ctype_space, ctype_letter, ctype_digit, ctype_xdigit, ctype_word, + ctype_meta); + +fprintf(f, " "); +for (i = 0; i < 256; i++) + { + if ((i & 7) == 0 && i != 0) + { + fprintf(f, " /* "); + if (isprint(i-8)) fprintf(f, " %c -", i-8); + else fprintf(f, "%3d-", i-8); + if (isprint(i-1)) fprintf(f, " %c ", i-1); + else fprintf(f, "%3d", i-1); + fprintf(f, " */\n "); + } + fprintf(f, "0x%02x", *tables++); + if (i != 255) fprintf(f, ","); + } + +fprintf(f, "};/* "); +if (isprint(i-8)) fprintf(f, " %c -", i-8); + else fprintf(f, "%3d-", i-8); +if (isprint(i-1)) fprintf(f, " %c ", i-1); + else fprintf(f, "%3d", i-1); +fprintf(f, " */\n\n/* End of pcre_chartables.c */\n"); + +fclose(f); +free((void *)base_of_tables); +return 0; +} + +/* End of dftables.c */ diff --git a/Library/pcre-8.10/pcre.h b/Library/pcre-8.10/pcre.h new file mode 100644 index 00000000..febb6174 --- /dev/null +++ b/Library/pcre-8.10/pcre.h @@ -0,0 +1,314 @@ +/************************************************* +* 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-2010 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 10 +#define PCRE_PRERELEASE +#define PCRE_DATE 2010-06-25 + +/* 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 + +/* 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. */ + +#define PCRE_CASELESS 0x00000001 +#define PCRE_MULTILINE 0x00000002 +#define PCRE_DOTALL 0x00000004 +#define PCRE_EXTENDED 0x00000008 +#define PCRE_ANCHORED 0x00000010 +#define PCRE_DOLLAR_ENDONLY 0x00000020 +#define PCRE_EXTRA 0x00000040 +#define PCRE_NOTBOL 0x00000080 +#define PCRE_NOTEOL 0x00000100 +#define PCRE_UNGREEDY 0x00000200 +#define PCRE_NOTEMPTY 0x00000400 +#define PCRE_UTF8 0x00000800 +#define PCRE_NO_AUTO_CAPTURE 0x00001000 +#define PCRE_NO_UTF8_CHECK 0x00002000 +#define PCRE_AUTO_CALLOUT 0x00004000 +#define PCRE_PARTIAL_SOFT 0x00008000 +#define PCRE_PARTIAL 0x00008000 /* Backwards compatible synonym */ +#define PCRE_DFA_SHORTEST 0x00010000 +#define PCRE_DFA_RESTART 0x00020000 +#define PCRE_FIRSTLINE 0x00040000 +#define PCRE_DUPNAMES 0x00080000 +#define PCRE_NEWLINE_CR 0x00100000 +#define PCRE_NEWLINE_LF 0x00200000 +#define PCRE_NEWLINE_CRLF 0x00300000 +#define PCRE_NEWLINE_ANY 0x00400000 +#define PCRE_NEWLINE_ANYCRLF 0x00500000 +#define PCRE_BSR_ANYCRLF 0x00800000 +#define PCRE_BSR_UNICODE 0x01000000 +#define PCRE_JAVASCRIPT_COMPAT 0x02000000 +#define PCRE_NO_START_OPTIMIZE 0x04000000 +#define PCRE_NO_START_OPTIMISE 0x04000000 +#define PCRE_PARTIAL_HARD 0x08000000 +#define PCRE_NOTEMPTY_ATSTART 0x10000000 +#define PCRE_UCP 0x20000000 + +/* 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) +#define PCRE_ERROR_BADUTF8_OFFSET (-11) +#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) + +/* 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 + +/* 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 + +/* Bit flags for the pcre_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 + +/* Types */ + +struct real_pcre; /* declaration; the definition is private */ +typedef struct real_pcre pcre; + +/* 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 */ +} pcre_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 */ + /* ------------------------------------------------------------------ */ +} pcre_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 *); +#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 *); +#endif /* VPCOMPAT */ + +/* Exported PCRE functions */ + +PCRE_EXP_DECL pcre *pcre_compile(const char *, 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 int pcre_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 pcre_copy_substring(const char *, int *, int, int, char *, + 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 pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR, + int, int, int, int *, int); +PCRE_EXP_DECL void pcre_free_substring(const char *); +PCRE_EXP_DECL void pcre_free_substring_list(const char **); +PCRE_EXP_DECL int pcre_fullinfo(const pcre *, const pcre_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 pcre_get_stringnumber(const pcre *, const char *); +PCRE_EXP_DECL int pcre_get_stringtable_entries(const pcre *, const char *, + char **, char **); +PCRE_EXP_DECL int pcre_get_substring(const char *, int *, int, int, + const char **); +PCRE_EXP_DECL int pcre_get_substring_list(const char *, int *, int, + const char ***); +PCRE_EXP_DECL int pcre_info(const pcre *, int *, int *); +PCRE_EXP_DECL const unsigned char *pcre_maketables(void); +PCRE_EXP_DECL int pcre_refcount(pcre *, int); +PCRE_EXP_DECL pcre_extra *pcre_study(const pcre *, int, const char **); +PCRE_EXP_DECL const char *pcre_version(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* End of pcre.h */ diff --git a/Library/pcre-8.10/pcre_chartables.c b/Library/pcre-8.10/pcre_chartables.c new file mode 100644 index 00000000..9117ae3c --- /dev/null +++ b/Library/pcre-8.10/pcre_chartables.c @@ -0,0 +1,198 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* This file contains character tables that are used when no external tables +are passed to PCRE by the application that calls it. The tables are used only +for characters whose code values are less than 256. + +This is a default version of the tables that assumes ASCII encoding. A program +called dftables (which is distributed with PCRE) can be used to build +alternative versions of this file. This is necessary if you are running in an +EBCDIC environment, or if you want to default to a different encoding, for +example ISO-8859-1. When dftables is run, it creates these tables in the +current locale. If PCRE is configured with --enable-rebuild-chartables, this +happens automatically. + +The following #includes are present because without them gcc 4.x may remove the +array definition from the final binary if PCRE is built into a static library +and dead code stripping is activated. This leads to link errors. Pulling in the +header ensures that the array gets flagged as "someone outside this compilation +unit might reference this" and so it will always be supplied to the linker. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + +const unsigned char _pcre_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/Library/pcre-8.10/pcre_compile.c b/Library/pcre-8.10/pcre_compile.c new file mode 100644 index 00000000..f1dc714a --- /dev/null +++ b/Library/pcre-8.10/pcre_compile.c @@ -0,0 +1,7205 @@ +/************************************************* +* 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-2010 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_compile(), along with +supporting internal functions that are not used by other modules. */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define NLBLOCK cd /* Block containing newline information */ +#define PSSTART start_pattern /* Field containing processed string start */ +#define PSEND end_pattern /* Field containing processed string end */ + +#include "pcre_internal.h" + + +/* When PCRE_DEBUG is defined, we need the pcre_printint() function, which is +also used by pcretest. PCRE_DEBUG is not defined when building a production +library. */ + +#ifdef PCRE_DEBUG +#include "pcre_printint.src" +#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. */ + +#define COMPILE_WORK_SIZE (4096) + +/* 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_CHECK (COMPILE_WORK_SIZE - 100) + + +/* 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 uschar 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 uschar *substitutes[] = { + (uschar *)"\\P{Nd}", /* \D */ + (uschar *)"\\p{Nd}", /* \d */ + (uschar *)"\\P{Xsp}", /* \S */ /* NOTE: Xsp is Perl space */ + (uschar *)"\\p{Xsp}", /* \s */ + (uschar *)"\\P{Xwd}", /* \W */ + (uschar *)"\\p{Xwd}" /* \w */ +}; + +static const uschar *posix_substitutes[] = { + (uschar *)"\\p{L}", /* alpha */ + (uschar *)"\\p{Ll}", /* lower */ + (uschar *)"\\p{Lu}", /* upper */ + (uschar *)"\\p{Xan}", /* alnum */ + NULL, /* ascii */ + (uschar *)"\\h", /* blank */ + NULL, /* cntrl */ + (uschar *)"\\p{Nd}", /* digit */ + NULL, /* graph */ + NULL, /* print */ + NULL, /* punct */ + (uschar *)"\\p{Xps}", /* space */ /* NOTE: Xps is POSIX space */ + (uschar *)"\\p{Xwd}", /* word */ + NULL, /* xdigit */ + /* Negated cases */ + (uschar *)"\\P{L}", /* ^alpha */ + (uschar *)"\\P{Ll}", /* ^lower */ + (uschar *)"\\P{Lu}", /* ^upper */ + (uschar *)"\\P{Xan}", /* ^alnum */ + NULL, /* ^ascii */ + (uschar *)"\\H", /* ^blank */ + NULL, /* ^cntrl */ + (uschar *)"\\P{Nd}", /* ^digit */ + NULL, /* ^graph */ + NULL, /* ^print */ + NULL, /* ^punct */ + (uschar *)"\\P{Xps}", /* ^space */ /* NOTE: Xps is POSIX space */ + (uschar *)"\\P{Xwd}", /* ^word */ + NULL /* ^xdigit */ +}; +#define POSIX_SUBSIZE (sizeof(posix_substitutes)/sizeof(uschar *)) +#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 not compiled with PCRE_UTF8 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 (not in 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" + "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 PCRE_UCP support\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. */ + +#ifndef EBCDIC + +/* This is the "normal" case, for ASCII systems, and EBCDIC systems running in +UTF-8 mode. */ + +static const unsigned char 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 unsigned char 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 unsigned char 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, int, uschar **, const uschar **, int *, BOOL, BOOL, 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; +} + + +/************************************************* +* 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 uschar **ptrptr, int *errorcodeptr, int bracount, + int options, BOOL isclass) +{ +BOOL utf8 = (options & PCRE_UTF8) != 0; +const uschar *ptr = *ptrptr + 1; +int c, 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 */ +else if (c < CHAR_0 || c > CHAR_z) {} /* Not alphanumeric */ +else if ((i = escapes[c - CHAR_0]) != 0) c = i; + +#else /* EBCDIC coding */ +else if (c < 'a' || (ebcdic_chartab[c] & 0x0E) == 0) {} /* Not alphanumeric */ +else if ((i = escapes[c - 0x48]) != 0) c = i; +#endif + +/* Escapes that need further processing, or are illegal. */ + +else + { + const uschar *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: + case CHAR_u: + case CHAR_U: + *errorcodeptr = ERR37; + break; + + /* \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 (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 uschar *p; + for (p = ptr+2; *p != 0 && *p != CHAR_RIGHT_CURLY_BRACKET; p++) + if (*p != CHAR_MINUS && (digitab[*p] & ctype_digit) == 0) 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; + + c = 0; + while ((digitab[ptr[1]] & ctype_digit) != 0) + c = c * 10 + *(++ptr) - CHAR_0; + + if (c < 0) /* Integer overflow */ + { + *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; + c -= CHAR_0; + while ((digitab[ptr[1]] & ctype_digit) != 0) + c = c * 10 + *(++ptr) - CHAR_0; + if (c < 0) /* Integer overflow */ + { + *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, 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; + if (!utf8 && c > 255) *errorcodeptr = ERR51; + break; + + /* \x is complicated. \x{ddd} is a character number which can be greater + than 0xff in utf8 mode, but only if the ddd are hex digits. If not, { is + treated as a data character. */ + + case CHAR_x: + if (ptr[1] == CHAR_LEFT_CURLY_BRACKET) + { + const uschar *pt = ptr + 2; + int count = 0; + + c = 0; + while ((digitab[*pt] & ctype_xdigit) != 0) + { + register int cc = *pt++; + if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */ + count++; + +#ifndef EBCDIC /* ASCII/UTF-8 coding */ + if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */ + c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10)); +#else /* EBCDIC coding */ + if (cc >= CHAR_a && cc <= CHAR_z) cc += 64; /* Convert to upper case */ + c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10)); +#endif + } + + if (*pt == CHAR_RIGHT_CURLY_BRACKET) + { + if (c < 0 || count > (utf8? 8 : 2)) *errorcodeptr = ERR34; + 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 && (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. + 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 >= 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}. */ + +if (c == -ESC_N && ptr[1] == CHAR_LEFT_CURLY_BRACKET) + *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 uschar **ptrptr, BOOL *negptr, int *dptr, int *errorcodeptr) +{ +int c, i, bot, top; +const uschar *ptr = *ptrptr; +char 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) - 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 = _pcre_utt_size; + +while (bot < top) + { + i = (bot + top) >> 1; + c = strcmp(name, _pcre_utt_names + _pcre_utt[i].name_offset); + if (c == 0) + { + *dptr = _pcre_utt[i].value; + return _pcre_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 + + + + +/************************************************* +* 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 uschar *p) +{ +if ((digitab[*p++] & ctype_digit) == 0) return FALSE; +while ((digitab[*p] & ctype_digit) != 0) p++; +if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE; + +if (*p++ != CHAR_COMMA) return FALSE; +if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE; + +if ((digitab[*p++] & ctype_digit) == 0) return FALSE; +while ((digitab[*p] & ctype_digit) != 0) p++; + +return (*p == CHAR_RIGHT_CURLY_BRACKET); +} + + + +/************************************************* +* 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 uschar * +read_repeat_counts(const uschar *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 ((digitab[*p] & ctype_digit) != 0) 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((digitab[*p] & ctype_digit) != 0) 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. We know that if (?P< is +encountered, the name will be terminated by '>' because that is checked in the +first pass. Recursion is used to keep track of subpatterns that reset the +capturing group numbers - the (?| feature. + +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 + 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(uschar **ptrptr, compile_data *cd, const uschar *name, int lorn, + BOOL xmode, int *count) +{ +uschar *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 (? 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 uschar *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((const char *)name, (const char *)thisname, lorn) == 0) + return *count; + term++; + } + } + } + +/* Past any initial parenthesis handling, scan for parentheses or vertical +bars. */ + +for (; *ptr != 0; 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((const char *)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) + { + while (*(++ptr) != 0 && *ptr != CHAR_NL) {}; + 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, 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 + +Returns: the number of the found subpattern, or -1 if not found +*/ + +static int +find_parens(compile_data *cd, const uschar *name, int lorn, BOOL xmode) +{ +uschar *ptr = (uschar *)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, &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, a change of option is important. +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 + options pointer to external options + optbit the option bit whose changing is significant, or + zero if none are + skipassert TRUE if certain assertions are to be skipped + +Returns: pointer to the first significant opcode +*/ + +static const uschar* +first_significant_code(const uschar *code, int *options, int optbit, + BOOL skipassert) +{ +for (;;) + { + switch ((int)*code) + { + case OP_OPT: + if (optbit > 0 && ((int)code[1] & optbit) != (*options & optbit)) + *options = (int)code[1]; + code += 2; + break; + + 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 += _pcre_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 += _pcre_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) + options the compiling options + 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 + or -3 if an OP_RECURSE item was encountered and atend is FALSE +*/ + +static int +find_fixedlength(uschar *code, int options, BOOL atend, compile_data *cd) +{ +int length = -1; + +register int branchlength = 0; +register uschar *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; + uschar *ce, *cs; + register int op = *cc; + switch (op) + { + case OP_CBRA: + case OP_BRA: + case OP_ONCE: + case OP_COND: + d = find_fixedlength(cc + ((op == OP_CBRA)? 2:0), options, 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. If it is + END it's the end of the outer call. All can be handled by the same code. */ + + case OP_ALT: + case OP_KET: + case OP_KETRMAX: + case OP_KETRMIN: + case OP_END: + 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 = (uschar *)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 + 2, options, 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); + /* 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_OPT: + case OP_CALLOUT: + case OP_SOD: + case OP_SOM: + case OP_SET_SOM: + case OP_EOD: + case OP_EODN: + case OP_CIRC: + case OP_DOLL: + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + cc += _pcre_OP_lengths[*cc]; + break; + + /* Handle literal characters */ + + case OP_CHAR: + case OP_CHARNC: + case OP_NOT: + branchlength++; + cc += 2; +#ifdef SUPPORT_UTF8 + if ((options & PCRE_UTF8) != 0 && cc[-1] >= 0xc0) + cc += _pcre_utf8_table4[cc[-1] & 0x3f]; +#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: + branchlength += GET2(cc,1); + cc += 4; +#ifdef SUPPORT_UTF8 + if ((options & PCRE_UTF8) != 0 && cc[-1] >= 0xc0) + cc += _pcre_utf8_table4[cc[-1] & 0x3f]; +#endif + break; + + case OP_TYPEEXACT: + branchlength += GET2(cc,1); + if (cc[3] == OP_PROP || cc[3] == OP_NOTPROP) cc += 2; + cc += 4; + break; + + /* Handle single-char 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: + branchlength++; + cc++; + break; + + /* The single-byte matcher isn't allowed */ + + case OP_ANYBYTE: + return -2; + + /* Check a class for variable quantification */ + +#ifdef SUPPORT_UTF8 + case OP_XCLASS: + cc += GET(cc, 1) - 33; + /* Fall through */ +#endif + + case OP_CLASS: + case OP_NCLASS: + cc += 33; + + switch (*cc) + { + 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,3)) return -1; + branchlength += GET2(cc,1); + cc += 5; + break; + + default: + branchlength++; + } + break; + + /* Anything else is variable length */ + + default: + return -1; + } + } +/* 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 + utf8 TRUE in UTF-8 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 uschar * +_pcre_find_bracket(const uschar *code, BOOL utf8, 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 (uschar *)code; + code += _pcre_OP_lengths[c]; + } + + /* Handle capturing bracket */ + + else if (c == OP_CBRA) + { + int n = GET2(code, 1+LINK_SIZE); + if (n == number) return (uschar *)code; + code += _pcre_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[3] == OP_PROP || code[3] == OP_NOTPROP) code += 2; + break; + + case OP_MARK: + case OP_PRUNE_ARG: + case OP_SKIP_ARG: + case OP_THEN_ARG: + code += code[1]; + break; + } + + /* Add in the fixed length from the table */ + + code += _pcre_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_UTF8 + if (utf8) switch(c) + { + case OP_CHAR: + case OP_CHARNC: + case OP_EXACT: + case OP_UPTO: + case OP_MINUPTO: + case OP_POSUPTO: + case OP_STAR: + case OP_MINSTAR: + case OP_POSSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_POSPLUS: + case OP_QUERY: + case OP_MINQUERY: + case OP_POSQUERY: + if (code[-1] >= 0xc0) code += _pcre_utf8_table4[code[-1] & 0x3f]; + break; + } +#else + (void)(utf8); /* 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 + utf8 TRUE in UTF-8 mode + +Returns: pointer to the opcode for OP_RECURSE, or NULL if not found +*/ + +static const uschar * +find_recurse(const uschar *code, BOOL utf8) +{ +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[3] == OP_PROP || code[3] == OP_NOTPROP) code += 2; + break; + + case OP_MARK: + case OP_PRUNE_ARG: + case OP_SKIP_ARG: + case OP_THEN_ARG: + code += code[1]; + break; + } + + /* Add in the fixed length from the table */ + + code += _pcre_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_UTF8 + if (utf8) switch(c) + { + case OP_CHAR: + case OP_CHARNC: + case OP_EXACT: + case OP_UPTO: + case OP_MINUPTO: + case OP_POSUPTO: + case OP_STAR: + case OP_MINSTAR: + case OP_POSSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_POSPLUS: + case OP_QUERY: + case OP_MINQUERY: + case OP_POSQUERY: + if (code[-1] >= 0xc0) code += _pcre_utf8_table4[code[-1] & 0x3f]; + break; + } +#else + (void)(utf8); /* 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 + utf8 TRUE if in UTF8 mode + cd contains pointers to tables etc. + +Returns: TRUE if what is matched could be empty +*/ + +static BOOL +could_be_empty_branch(const uschar *code, const uschar *endcode, BOOL utf8, + compile_data *cd) +{ +register int c; +for (code = first_significant_code(code + _pcre_OP_lengths[*code], NULL, 0, TRUE); + code < endcode; + code = first_significant_code(code + _pcre_OP_lengths[c], NULL, 0, TRUE)) + { + const uschar *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; + } + + /* Groups with zero repeats can of course be empty; skip them. */ + + if (c == OP_BRAZERO || c == OP_BRAMINZERO || c == OP_SKIPZERO) + { + code += _pcre_OP_lengths[c]; + 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 subroutine call, we can scan it. */ + + if (c == OP_RECURSE) + { + BOOL empty_branch = FALSE; + const uschar *scode = cd->start_code + GET(code, 1); + if (GET(scode, 1) == 0) return TRUE; /* Unclosed */ + do + { + if (could_be_empty_branch(scode, endcode, utf8, cd)) + { + empty_branch = TRUE; + break; + } + scode += GET(scode, 1); + } + while (*scode == OP_ALT); + if (!empty_branch) return FALSE; /* All branches are non-empty */ + continue; + } + + /* For other groups, scan the branches. */ + + if (c == OP_BRA || c == OP_CBRA || c == OP_ONCE || 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, utf8, 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 _pcre_OP_lengths[] is zero; the + actual length is stored in the compiled code, so we must update "code" + here. */ + +#ifdef SUPPORT_UTF8 + case OP_XCLASS: + ccode = code += GET(code, 1); + goto CHECK_CLASS_REPEAT; +#endif + + case OP_CLASS: + case OP_NCLASS: + ccode = code + 33; + +#ifdef SUPPORT_UTF8 + 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_CHARNC: + case OP_NOT: + 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[3] == OP_PROP || code[3] == OP_NOTPROP) code += 2; + break; + + /* End of branch */ + + case OP_KET: + case OP_KETRMAX: + case OP_KETRMIN: + 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_UTF8 + case OP_STAR: + case OP_MINSTAR: + case OP_POSSTAR: + case OP_QUERY: + case OP_MINQUERY: + case OP_POSQUERY: + if (utf8 && code[1] >= 0xc0) code += _pcre_utf8_table4[code[1] & 0x3f]; + break; + + case OP_UPTO: + case OP_MINUPTO: + case OP_POSUPTO: + if (utf8 && code[3] >= 0xc0) code += _pcre_utf8_table4[code[3] & 0x3f]; + break; +#endif + + /* MARK, and PRUNE/SKIP/THEN with an argument must skip over the argument + string. */ + + case OP_MARK: + case OP_PRUNE_ARG: + case OP_SKIP_ARG: + case OP_THEN_ARG: + code += code[1]; + break; + + /* None of the remaining opcodes are required to match a character. */ + + default: + break; + } + } + +return TRUE; +} + + + +/************************************************* +* Scan compiled regex for non-emptiness * +*************************************************/ + +/* This function is called to check for left recursive calls. We want to check +the current branch of the current pattern to see if it could match the empty +string. If it could, we must look outwards for branches at other levels, +stopping when we pass beyond the bracket which is the subject of the recursion. + +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 + utf8 TRUE if in UTF-8 mode + cd pointers to tables etc + +Returns: TRUE if what is matched could be empty +*/ + +static BOOL +could_be_empty(const uschar *code, const uschar *endcode, branch_chain *bcptr, + BOOL utf8, compile_data *cd) +{ +while (bcptr != NULL && bcptr->current_branch >= code) + { + if (!could_be_empty_branch(bcptr->current_branch, endcode, utf8, 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. + +Arguments: + ptr pointer to the initial [ + endptr where to return the end pointer + +Returns: TRUE or FALSE +*/ + +static BOOL +check_posix_syntax(const uschar *ptr, const uschar **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; + if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) + { + *endptr = ptr; + return TRUE; + } + } + } +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 uschar *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((const char *)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 + utf8 TRUE in UTF-8 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(uschar *group, int adjust, BOOL utf8, compile_data *cd, + uschar *save_hwm) +{ +uschar *ptr = group; + +while ((ptr = (uschar *)find_recurse(ptr, utf8)) != NULL) + { + int offset; + uschar *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 uschar * +auto_callout(uschar *code, const uschar *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(uschar *previous_callout, const uschar *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 == _pcre_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 (_pcre_ucp_gentype[prop->chartype] == ucp_L || + _pcre_ucp_gentype[prop->chartype] == ucp_N) == negated; + + case PT_SPACE: /* Perl space */ + return (_pcre_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 (_pcre_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 (_pcre_ucp_gentype[prop->chartype] == ucp_L || + _pcre_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 + utf8 TRUE in UTF-8 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 uschar *previous, BOOL utf8, const uschar *ptr, + int options, compile_data *cd) +{ +int c, next; +int op_code = *previous++; + +/* Skip whitespace and comments in extended mode */ + +if ((options & PCRE_EXTENDED) != 0) + { + for (;;) + { + while ((cd->ctypes[*ptr] & ctype_space) != 0) ptr++; + if (*ptr == CHAR_NUMBER_SIGN) + { + while (*(++ptr) != 0) + if (IS_NEWLINE(ptr)) { ptr += cd->nllen; break; } + } + 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 ((cd->ctypes[*ptr] & ctype_meta) == 0) + { +#ifdef SUPPORT_UTF8 + if (utf8) { GETCHARINC(next, ptr); } else +#endif + next = *ptr++; + } + +else return FALSE; + +/* Skip whitespace and comments in extended mode */ + +if ((options & PCRE_EXTENDED) != 0) + { + for (;;) + { + while ((cd->ctypes[*ptr] & ctype_space) != 0) ptr++; + if (*ptr == CHAR_NUMBER_SIGN) + { + while (*(++ptr) != 0) + if (IS_NEWLINE(ptr)) { ptr += cd->nllen; break; } + } + else break; + } + } + +/* If the next thing is itself optional, we have to give up. */ + +if (*ptr == CHAR_ASTERISK || *ptr == CHAR_QUESTION_MARK || + strncmp((char *)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_UTF8 + GETCHARTEST(c, previous); +#else + c = *previous; +#endif + return c != next; + + /* For CHARNC (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_CHARNC: +#ifdef SUPPORT_UTF8 + GETCHARTEST(c, previous); +#else + c = *previous; +#endif + if (c == next) return FALSE; +#ifdef SUPPORT_UTF8 + if (utf8) + { + 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_UTF8 */ + return (c != cd->fcc[next]); /* Non-UTF-8 mode */ + + /* For OP_NOT, its data is always a single-byte character. */ + + case OP_NOT: + if ((c = *previous) == next) return TRUE; + if ((options & PCRE_CASELESS) == 0) return FALSE; +#ifdef SUPPORT_UTF8 + if (utf8) + { + 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_UTF8 */ + return (c == 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_CHARNC: +#ifdef SUPPORT_UTF8 + 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((char *)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 + firstbyteptr set to initial literal character, or < 0 (REQ_UNSET, REQ_NONE) + reqbyteptr set to the last literal character required, else < 0 + bcptr points to current branch chain + 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, uschar **codeptr, const uschar **ptrptr, + int *errorcodeptr, int *firstbyteptr, int *reqbyteptr, branch_chain *bcptr, + 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; +int firstbyte, reqbyte; +int zeroreqbyte, zerofirstbyte; +int req_caseopt, reqvary, tempreqvary; +int options = *optionsptr; +int after_manual_callout = 0; +int length_prevgroup = 0; +register int c; +register uschar *code = *codeptr; +uschar *last_code = code; +uschar *orig_code = code; +uschar *tempcode; +BOOL inescq = FALSE; +BOOL groupsetfirstbyte = FALSE; +const uschar *ptr = *ptrptr; +const uschar *tempptr; +const uschar *nestptr = NULL; +uschar *previous = NULL; +uschar *previous_callout = NULL; +uschar *save_hwm = NULL; +uschar classbits[32]; + +#ifdef SUPPORT_UTF8 +BOOL class_utf8; +BOOL utf8 = (options & PCRE_UTF8) != 0; +uschar *class_utf8data; +uschar *class_utf8data_base; +uschar utf8_char[6]; +#else +BOOL utf8 = FALSE; +uschar *utf8_char = NULL; +#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; reqbyte 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 zeroreqbyte when such a repeat is encountered. The individual +item types that can be repeated set these backoff variables appropriately. */ + +firstbyte = reqbyte = zerofirstbyte = zeroreqbyte = REQ_UNSET; + +/* The variable req_caseopt contains either the REQ_CASELESS value or zero, +according to the current setting of the caseless flag. REQ_CASELESS is a bit +value > 255. It is added into the firstbyte or reqbyte 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_charcount; + int class_lastchar; + int newoptions; + int recno; + int refsign; + int skipbytes; + int subreqbyte; + int subfirstbyte; + int terminator; + int mclength; + uschar mcbuffer[8]; + + /* Get next byte 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 + WORK_SIZE_CHECK) /* 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\n", *lengthptr, code - last_code, 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, 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 + WORK_SIZE_CHECK) + { + *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 ((cd->ctypes[c] & ctype_space) != 0) continue; + if (c == CHAR_NUMBER_SIGN) + { + while (*(++ptr) != 0) + { + if (IS_NEWLINE(ptr)) { ptr += cd->nllen - 1; break; } + } + 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: + *firstbyteptr = firstbyte; + *reqbyteptr = reqbyte; + *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: + if ((options & PCRE_MULTILINE) != 0) + { + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + } + previous = NULL; + *code++ = OP_CIRC; + break; + + case CHAR_DOLLAR_SIGN: + previous = NULL; + *code++ = OP_DOLL; + break; + + /* There can never be a first char if '.' is first, whatever happens about + repeats. The value of reqbyte doesn't change either. */ + + case CHAR_DOT: + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + zerofirstbyte = firstbyte; + zeroreqbyte = reqbyte; + 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((const char *)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 (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + zerofirstbyte = firstbyte; + 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; + + /* Keep a count of chars with values < 256 so that we can optimize the case + of just a single character (as long as it's < 256). However, For higher + valued UTF-8 characters, we don't yet do any optimization. */ + + class_charcount = 0; + class_lastchar = -1; + + /* 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(uschar)); + +#ifdef SUPPORT_UTF8 + class_utf8 = FALSE; /* No chars >= 256 */ + class_utf8data = code + LINK_SIZE + 2; /* For UTF-8 items */ + class_utf8data_base = class_utf8data; /* 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 uschar *oldptr; + +#ifdef SUPPORT_UTF8 + if (utf8 && c > 127) + { /* Braces are required because the */ + GETCHARLEN(c, ptr, ptr); /* macro generates multiple statements */ + } + + /* In the pre-compile phase, accumulate the length of any UTF-8 extra + data and reset the pointer. This is so that very large classes that + contain a zillion UTF-8 characters no longer overwrite the work space + (which is on the stack). */ + + if (lengthptr != NULL) + { + *lengthptr += class_utf8data - class_utf8data_base; + class_utf8data = class_utf8data_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 uschar *cbits = cd->cbits; + uschar 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(uschar)); + + /* 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; + class_charcount = 10; /* Set > 1; assumes more than 1 per class */ + 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 set + class_charcount 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_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 uschar *cbits = cd->cbits; + class_charcount += 2; /* Greater than 1 is what matters */ + + 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_charcount -= 2; /* 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; + + case ESC_s: + 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_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 */ +#ifdef SUPPORT_UTF8 + if (utf8) + { + class_utf8 = TRUE; + *class_utf8data++ = XCL_SINGLE; + class_utf8data += _pcre_ord2utf8(0x1680, class_utf8data); + *class_utf8data++ = XCL_SINGLE; + class_utf8data += _pcre_ord2utf8(0x180e, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x2000, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x200A, class_utf8data); + *class_utf8data++ = XCL_SINGLE; + class_utf8data += _pcre_ord2utf8(0x202f, class_utf8data); + *class_utf8data++ = XCL_SINGLE; + class_utf8data += _pcre_ord2utf8(0x205f, class_utf8data); + *class_utf8data++ = XCL_SINGLE; + class_utf8data += _pcre_ord2utf8(0x3000, class_utf8data); + } +#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; + } + +#ifdef SUPPORT_UTF8 + if (utf8) + { + class_utf8 = TRUE; + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x0100, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x167f, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x1681, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x180d, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x180f, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x1fff, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x200B, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x202e, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x2030, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x205e, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x2060, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x2fff, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x3001, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x7fffffff, class_utf8data); + } +#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 */ +#ifdef SUPPORT_UTF8 + if (utf8) + { + class_utf8 = TRUE; + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x2028, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x2029, class_utf8data); + } +#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; + } + +#ifdef SUPPORT_UTF8 + if (utf8) + { + class_utf8 = TRUE; + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x0100, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x2027, class_utf8data); + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(0x2029, class_utf8data); + class_utf8data += _pcre_ord2utf8(0x7fffffff, class_utf8data); + } +#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; + class_utf8 = TRUE; + *class_utf8data++ = ((-c == ESC_p) != negated)? + XCL_PROP : XCL_NOTPROP; + *class_utf8data++ = ptype; + *class_utf8data++ = pdata; + class_charcount -= 2; /* Not a < 256 character */ + 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_charcount -= 2; /* Undo the default count from above */ + 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 in UTF-8 mode. */ + + } /* 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_UTF8 + if (utf8) + { /* 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; + + /* 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. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && (d > 255 || ((options & PCRE_CASELESS) != 0 && d > 127))) + { + class_utf8 = 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 + if ((options & PCRE_CASELESS) != 0) + { + 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_utf8data++ = XCL_SINGLE; + } + else + { + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(occ, class_utf8data); + } + class_utf8data += _pcre_ord2utf8(ocd, class_utf8data); + } + } +#endif /* SUPPORT_UCP */ + + /* Now record the original range, possibly modified for UCP caseless + overlapping ranges. */ + + *class_utf8data++ = XCL_RANGE; + class_utf8data += _pcre_ord2utf8(c, class_utf8data); + class_utf8data += _pcre_ord2utf8(d, class_utf8data); + + /* With UCP support, we are done. Without UCP support, there is no + caseless matching for UTF-8 characters > 127; we can use the bit map + for the smaller ones. */ + +#ifdef SUPPORT_UCP + continue; /* With next character in the class */ +#else + if ((options & PCRE_CASELESS) == 0 || c > 127) continue; + + /* Adjust upper limit and fall through to set up the map */ + + d = 127; + +#endif /* SUPPORT_UCP */ + } +#endif /* SUPPORT_UTF8 */ + + /* We use the bit map for all cases when not in UTF-8 mode; else + ranges that lie entirely within 0-127 when there is UCP support; else + for partial ranges without UCP support. */ + + class_charcount += d - c + 1; + class_lastchar = d; + + /* 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: + + /* Handle a character that cannot go in the bit map */ + +#ifdef SUPPORT_UTF8 + if (utf8 && (c > 255 || ((options & PCRE_CASELESS) != 0 && c > 127))) + { + class_utf8 = TRUE; + *class_utf8data++ = XCL_SINGLE; + class_utf8data += _pcre_ord2utf8(c, class_utf8data); + +#ifdef SUPPORT_UCP + if ((options & PCRE_CASELESS) != 0) + { + unsigned int othercase; + if ((othercase = UCD_OTHERCASE(c)) != c) + { + *class_utf8data++ = XCL_SINGLE; + class_utf8data += _pcre_ord2utf8(othercase, class_utf8data); + } + } +#endif /* SUPPORT_UCP */ + + } + else +#endif /* SUPPORT_UTF8 */ + + /* Handle a single-byte character */ + { + classbits[c/8] |= (1 << (c&7)); + if ((options & PCRE_CASELESS) != 0) + { + c = cd->fcc[c]; /* flip case */ + classbits[c/8] |= (1 << (c&7)); + } + class_charcount++; + class_lastchar = c; + } + } + + /* Loop until ']' reached. This "while" is the end of the "do" far above. + If we are at the end of an internal nested string, revert to the outer + string. */ + + while (((c = *(++ptr)) != 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 class_charcount is 1, we saw precisely one character whose value is + less than 256. As long as there were no 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 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[NC] if it's positive, or OP_NOT if it's negative. Note + that OP_NOT does not support multibyte characters. In the positive case, it + can cause firstbyte to be set. Otherwise, there can be no first char if + this item is first, whatever repeat count may follow. In the case of + reqbyte, save the previous value for reinstating. */ + +#ifdef SUPPORT_UTF8 + if (class_charcount == 1 && !class_utf8 && + (!utf8 || !negate_class || class_lastchar < 128)) +#else + if (class_charcount == 1) +#endif + { + zeroreqbyte = reqbyte; + + /* The OP_NOT opcode works on one-byte characters only. */ + + if (negate_class) + { + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + zerofirstbyte = firstbyte; + *code++ = OP_NOT; + *code++ = class_lastchar; + break; + } + + /* For a single, positive character, get the value into mcbuffer, and + then we can handle this with the normal one-character code. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && class_lastchar > 127) + mclength = _pcre_ord2utf8(class_lastchar, mcbuffer); + else +#endif + { + mcbuffer[0] = class_lastchar; + mclength = 1; + } + goto ONE_CHAR; + } /* End of 1-char optimization */ + + /* The general case - not the one-char optimization. If this is the first + thing in the branch, there can be no first char setting, whatever the + repeat count. Any reqbyte setting must remain unchanged after any kind of + repeat. */ + + if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + zerofirstbyte = firstbyte; + zeroreqbyte = reqbyte; + + /* 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_UTF8 + if (class_utf8 && (!should_flip_negation || (options & PCRE_UCP) != 0)) + { + *class_utf8data++ = 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_charcount > 0) + { + *code++ |= XCL_MAP; + memmove(code + 32, code, class_utf8data - code); + memcpy(code, classbits, 32); + code = class_utf8data + 32; + } + else code = class_utf8data; + + /* Now fill in the complete length of the item */ + + PUT(previous, 1, 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 (negate_class) + { + if (lengthptr == NULL) /* Save time in the pre-compile phase */ + for (c = 0; c < 32; c++) code[c] = ~classbits[c]; + } + else + { + memcpy(code, classbits, 32); + } + code += 32; + 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) + { + firstbyte = zerofirstbyte; /* Adjust for zero repeat */ + reqbyte = zeroreqbyte; /* 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 to make space + for an inserted OP_ONCE for the additional '+' extension. */ + + 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 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 reqbyte - 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 firstbyte + instead. */ + + if (*previous == OP_CHAR || *previous == OP_CHARNC) + { + /* Deal with UTF-8 characters that take up more than one byte. 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 0x80 to flag that it's a + length rather than a small character. */ + +#ifdef SUPPORT_UTF8 + if (utf8 && (code[-1] & 0x80) != 0) + { + uschar *lastchar = code - 1; + while((*lastchar & 0xc0) == 0x80) lastchar--; + c = code - lastchar; /* Length of UTF-8 character */ + memcpy(utf8_char, lastchar, c); /* Save the char */ + c |= 0x80; /* Flag c as a length */ + } + else +#endif + + /* Handle the case of a single byte - either with no UTF8 support, or + with UTF-8 disabled, or for a UTF-8 character < 128. */ + + { + c = code[-1]; + if (repeat_min > 1) reqbyte = 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, utf8, 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 is + currently used only for single-byte chars. */ + + else if (*previous == OP_NOT) + { + op_type = OP_NOTSTAR - OP_STAR; /* Use "not" opcodes */ + c = previous[1]; + if (!possessive_quantifier && + repeat_max < 0 && + check_auto_possessive(previous, utf8, 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) + { + uschar *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, utf8, 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 0x80 bit as a flag. */ + + if (repeat_max < 0) + { +#ifdef SUPPORT_UTF8 + if (utf8 && c >= 128) + { + memcpy(code, utf8_char, 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_UTF8 + if (utf8 && c >= 128) + { + memcpy(code, utf8_char, 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_UTF8 + if (utf8 && c >= 128) + { + memcpy(code, utf8_char, 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 || +#ifdef SUPPORT_UTF8 + *previous == OP_XCLASS || +#endif + *previous == OP_REF) + { + 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. */ + + else if (*previous == OP_BRA || *previous == OP_CBRA || + *previous == OP_ONCE || *previous == OP_COND) + { + register int i; + int ketoffset = 0; + int len = (int)(code - previous); + uschar *bralink = NULL; + + /* Repeating a DEFINE group is pointless */ + + if (*previous == OP_COND && previous[LINK_SIZE+1] == OP_DEF) + { + *errorcodeptr = ERR55; + goto FAILED; + } + + /* If the maximum repeat count is unlimited, find the end of the bracket + by scanning through from the start, and compute the offset back to it + from the current code pointer. There may be an OP_OPT setting following + the final KET, so we can't find the end just by going back from the code + pointer. */ + + if (repeat_max == -1) + { + register uschar *ket = previous; + do ket += GET(ket, 1); while (*ket != OP_KET); + ketoffset = (int)(code - ket); + } + + /* 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 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, utf8, cd, save_hwm); + memmove(previous+1, previous, len); + code++; + if (repeat_max == 0) + { + *previous++ = OP_SKIPZERO; + goto END_REPEAT; + } + *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, utf8, cd, save_hwm); + memmove(previous + 2 + LINK_SIZE, previous, 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 */ + + else + { + if (groupsetfirstbyte && reqbyte < 0) reqbyte = firstbyte; + for (i = 1; i < repeat_min; i++) + { + uschar *hc; + uschar *this_hwm = cd->hwm; + memcpy(code, previous, len); + 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--) + { + uschar *hc; + uschar *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, len); + 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); + uschar *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. We + can't just offset backwards from the current code point, because we + don't know if there's been an options resetting after the ket. The + correct offset was computed above. + + Then, when we are doing the actual compile phase, check to see whether + this group is a non-atomic 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 + atomic groups at runtime, but in a different way.] */ + + else + { + uschar *ketcode = code - ketoffset; + uschar *bracode = ketcode - GET(ketcode, 1); + *ketcode = OP_KETRMAX + repeat_type; + if (lengthptr == NULL && *bracode != OP_ONCE) + { + uschar *scode = bracode; + do + { + if (could_be_empty_branch(scode, ketcode, utf8, cd)) + { + *bracode += OP_SBRA - OP_BRA; + break; + } + scode += GET(scode, 1); + } + while (*scode == OP_ALT); + } + } + } + + /* 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 of the + simpler opcodes, there is an special alternative opcode for this. For + anything else, we wrap the entire repeated item inside OP_ONCE brackets. + The '+' notation is just syntactic sugar, taken from Sun's Java package, + but the special opcodes can optimize it a bit. 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 += _pcre_OP_lengths[*tempcode] + + ((tempcode[3] == OP_PROP || tempcode[3] == OP_NOTPROP)? 2 : 0); + + else if (*tempcode == OP_EXACT || *tempcode == OP_NOTEXACT) + { + tempcode += _pcre_OP_lengths[*tempcode]; +#ifdef SUPPORT_UTF8 + if (utf8 && tempcode[-1] >= 0xc0) + tempcode += _pcre_utf8_table4[tempcode[-1] & 0x3f]; +#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_TYPESTAR: *tempcode = OP_TYPEPOSSTAR; break; + case OP_TYPEPLUS: *tempcode = OP_TYPEPOSPLUS; break; + case OP_TYPEQUERY: *tempcode = OP_TYPEPOSQUERY; break; + case OP_TYPEUPTO: *tempcode = OP_TYPEPOSUPTO; break; + + case OP_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; + + /* 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, utf8, cd, save_hwm); + memmove(tempcode + 1+LINK_SIZE, tempcode, 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 reqbytes 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 '*'. */ + + if (*(++ptr) == CHAR_ASTERISK && + ((cd->ctypes[ptr[1]] & ctype_letter) != 0 || ptr[1] == ':')) + { + int i, namelen; + int arglen = 0; + const char *vn = verbnames; + const uschar *name = ptr + 1; + const uschar *arg = NULL; + previous = NULL; + while ((cd->ctypes[*++ptr] & ctype_letter) != 0) {}; + namelen = (int)(ptr - name); + + if (*ptr == CHAR_COLON) + { + arg = ++ptr; + while ((cd->ctypes[*ptr] & (ctype_letter|ctype_digit)) != 0 + || *ptr == '_') 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((char *)name, vn, namelen) == 0) + { + /* Check for open captures before ACCEPT */ + + if (verbs[i].op == OP_ACCEPT) + { + open_capitem *oc; + cd->had_accept = TRUE; + for (oc = cd->open_caps; oc != NULL; oc = oc->next) + { + *code++ = OP_CLOSE; + PUT2INC(code, 0, oc->number); + } + } + + /* Handle the cases with/without an argument */ + + if (arglen == 0) + { + if (verbs[i].op < 0) /* Argument is mandatory */ + { + *errorcodeptr = ERR66; + goto FAILED; + } + *code++ = verbs[i].op; + } + + else + { + if (verbs[i].op_arg < 0) /* Argument is forbidden */ + { + *errorcodeptr = ERR59; + goto FAILED; + } + *code++ = verbs[i].op_arg; + *code++ = arglen; + memcpy(code, arg, 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 uschar *name; + uschar *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 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 (?() 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 3 bytes at the start of the group. */ + + code[1+LINK_SIZE] = OP_CREF; + skipbytes = 3; + 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 (?() 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 ((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 ((cd->ctypes[*ptr] & ctype_word) != 0) + { + if (recno >= 0) + recno = ((digitab[*ptr] & ctype_digit) != 0)? + 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((char *)name, (char *)slot+2, 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)) > 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 (?(... 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 ((digitab[name[i]] & ctype_digit) == 0) + { + *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((char *)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; + 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; + break; + + + /* ------------------------------------------------------------ */ + case CHAR_LESS_THAN_SIGN: /* Lookbehind or named define */ + switch (ptr[1]) + { + case CHAR_EQUALS_SIGN: /* Positive lookbehind */ + bravalue = OP_ASSERTBACK; + ptr += 2; + break; + + case CHAR_EXCLAMATION_MARK: /* Negative lookbehind */ + bravalue = OP_ASSERTBACK_NOT; + ptr += 2; + break; + + default: /* Could be name define, else bad */ + if ((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; + while ((digitab[*(++ptr)] & ctype_digit) != 0) + 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 ((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 + 3 > cd->name_entry_size) + { + cd->name_entry_size = namelen + 3; + 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+2, namelen); + if (crc == 0) + { + if (slot[2+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, + (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) + { + uschar *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 + 2, name, namelen); + slot[2+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 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 ((cd->ctypes[*ptr] & ctype_word) != 0) ptr++; + namelen = (int)(ptr - name); + + /* In the pre-compile phase, do a syntax check and set a dummy + reference number. */ + + if (lengthptr != NULL) + { + if (namelen == 0) + { + *errorcodeptr = ERR62; + goto FAILED; + } + if (*ptr != terminator) + { + *errorcodeptr = ERR42; + goto FAILED; + } + if (namelen > MAX_NAME_SIZE) + { + *errorcodeptr = ERR48; + goto FAILED; + } + recno = 0; + } + + /* 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((char *)name, (char *)slot+2, namelen) == 0 && + slot[2+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)) <= 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 uschar *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 ((digitab[*ptr] & ctype_digit) == 0) + { + *errorcodeptr = ERR63; + goto FAILED; + } + } + else if (refsign == CHAR_MINUS) + { + if ((digitab[ptr[1]] & ctype_digit) == 0) + goto OTHER_CHAR_AFTER_QUERY; + ptr++; + } + + recno = 0; + while((digitab[*ptr] & ctype_digit) != 0) + 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 = _pcre_find_bracket(cd->start_code, utf8, recno); + + /* Forward reference */ + + if (called == NULL) + { + if (find_parens(cd, NULL, recno, + (options & PCRE_EXTENDED) != 0) < 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. */ + + called = cd->start_code + recno; + PUTINC(cd->hwm, 0, (int)(code + 2 + LINK_SIZE - 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. */ + + else if (GET(called, 1) == 0 && + could_be_empty(called, code, bcptr, utf8, cd)) + { + *errorcodeptr = ERR40; + goto FAILED; + } + } + + /* Insert the recursion/subroutine item, automatically wrapped inside + "once" brackets. Set up a "previous group" length so that a + subsequent quantifier will work. */ + + *code = OP_ONCE; + PUT(code, 1, 2 + 2*LINK_SIZE); + code += 1 + LINK_SIZE; + + *code = OP_RECURSE; + PUT(code, 1, (int)(called - cd->start_code)); + code += 1 + LINK_SIZE; + + *code = OP_KET; + PUT(code, 1, 2 + 2*LINK_SIZE); + code += 1 + LINK_SIZE; + + length_prevgroup = 3 + 3*LINK_SIZE; + } + + /* Can't determine a first byte now */ + + if (firstbyte == REQ_UNSET) firstbyte = 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, compile code to change the ims + options if this setting actually changes any of them, and reset the + greedy defaults and the case value for firstbyte and reqbyte. */ + + 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 + { + if ((options & PCRE_IMS) != (newoptions & PCRE_IMS)) + { + *code++ = OP_OPT; + *code++ = newoptions & PCRE_IMS; + } + 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. When not at the start of the pattern, this + information is also necessary so that a resetting item can be + compiled at the end of a group (if we are in a group). */ + + *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 = 2; + } + + /* Process nested bracketed regex. Assertions may not be repeated, but + other kinds can be. All their opcodes are >= OP_ONCE. We copy code into a + non-register variable in order to be able to pass its address because some + compilers complain otherwise. Pass in a new setting for the ims options if + they have changed. */ + + previous = (bravalue >= OP_ONCE)? code : NULL; + *code = bravalue; + tempcode = code; + tempreqvary = cd->req_varyopt; /* Save value before bracket */ + length_prevgroup = 0; /* Initialize for pre-compile phase */ + + if (!compile_regex( + newoptions, /* The complete new option state */ + options & PCRE_IMS, /* The previous ims 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 */ + &subfirstbyte, /* For possible first char */ + &subreqbyte, /* For possible last char */ + bcptr, /* Current branch chain */ + cd, /* Tables block */ + (lengthptr == NULL)? NULL : /* Actual compile phase */ + &length_prevgroup /* Pre-compile phase */ + )) + goto FAILED; + + /* 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 + and any option resetting that may follow it. 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) + { + uschar *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 firstbyte or reqbyte, because this is equivalent to an + empty second branch. */ + + else + { + if (condcount > 2) + { + *errorcodeptr = ERR27; + goto FAILED; + } + if (condcount == 1) subfirstbyte = subreqbyte = 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++ = OP_BRA; + 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 zeroreqbyte and + zerofirstbyte outside the main loop so that they can be accessed for the + back off. */ + + zeroreqbyte = reqbyte; + zerofirstbyte = firstbyte; + groupsetfirstbyte = FALSE; + + if (bravalue >= OP_ONCE) + { + /* If we have not yet set a firstbyte 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 reqbyte if necessary. If the subpattern has + no firstbyte, set "none" for the whole branch. In both cases, a zero + repeat forces firstbyte to "none". */ + + if (firstbyte == REQ_UNSET) + { + if (subfirstbyte >= 0) + { + firstbyte = subfirstbyte; + groupsetfirstbyte = TRUE; + } + else firstbyte = REQ_NONE; + zerofirstbyte = REQ_NONE; + } + + /* If firstbyte was previously set, convert the subpattern's firstbyte + into reqbyte if there wasn't one, using the vary flag that was in + existence beforehand. */ + + else if (subfirstbyte >= 0 && subreqbyte < 0) + subreqbyte = subfirstbyte | 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 (subreqbyte >= 0) reqbyte = subreqbyte; + } + + /* For a forward assertion, we take the reqbyte, 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 firstbyte + for an assertion, however because it leads to incorrect effect for patterns + such as /(?=a)a.+/ when the "real" "a" would then become a reqbyte instead + of a firstbyte. This is overcome by a scan at the end if there's no + firstbyte, looking for an asserted first char. */ + + else if (bravalue == OP_ASSERT && subreqbyte >= 0) reqbyte = subreqbyte; + 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 (firstbyte == REQ_UNSET && -c > ESC_b && -c < ESC_Z) + firstbyte = REQ_NONE; + + /* Set values to reset to if this is followed by a zero repeat. */ + + zerofirstbyte = firstbyte; + zeroreqbyte = reqbyte; + + /* \g or \g'name' is a subroutine call by name and \g 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 uschar *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 isnumber = TRUE; + for (p = ptr + 1; *p != 0 && *p != terminator; p++) + { + if ((cd->ctypes[*p] & ctype_digit) == 0) isnumber = FALSE; + if ((cd->ctypes[*p] & ctype_word) == 0) break; + } + if (*p != terminator) + { + *errorcodeptr = ERR57; + break; + } + if (isnumber) + { + 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 ((digitab[*p] & ctype_digit) != 0) p++; + if (*p != terminator) + { + *errorcodeptr = ERR57; + break; + } + ptr++; + goto HANDLE_NUMERICAL_RECURSION; + } + + /* \k or \k'name' is a back reference by name (Perl syntax). + We also support \k{name} (.NET syntax) */ + + if (-c == ESC_k && (ptr[1] == CHAR_LESS_THAN_SIGN || + ptr[1] == CHAR_APOSTROPHE || ptr[1] == CHAR_LEFT_CURLY_BRACKET)) + { + 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 firstbyte 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 (firstbyte == REQ_UNSET) firstbyte = REQ_NONE; + previous = code; + *code++ = 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 + { + previous = (-c > ESC_b && -c < ESC_Z)? code : NULL; + *code++ = -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_UTF8 + if (utf8 && c > 127) + mclength = _pcre_ord2utf8(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_UTF8 + if (utf8 && c >= 0xc0) + { + while ((ptr[1] & 0xc0) == 0x80) + 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_CHARNC : 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 firstbyte value alone, and don't change it on a zero + repeat. */ + + if (firstbyte == REQ_UNSET) + { + zerofirstbyte = REQ_NONE; + zeroreqbyte = reqbyte; + + /* If the character is more than one byte long, we can set firstbyte + only if it is not to be matched caselessly. */ + + if (mclength == 1 || req_caseopt == 0) + { + firstbyte = mcbuffer[0] | req_caseopt; + if (mclength != 1) reqbyte = code[-1] | cd->req_varyopt; + } + else firstbyte = reqbyte = REQ_NONE; + } + + /* firstbyte was previously set; we can set reqbyte only the length is + 1 or the matching is caseful. */ + + else + { + zerofirstbyte = firstbyte; + zeroreqbyte = reqbyte; + if (mclength == 1 || req_caseopt == 0) + reqbyte = 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. +If the ims options are changed at the start (for a (?ims: group) or during any +branch, we need to insert an OP_OPT item at the start of every following branch +to ensure they get set correctly at run time, and also pass the new options +into every subsequent branch compile. + +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 + oldims previous settings of ims option bits + 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) + firstbyteptr place to put the first required character, or a negative number + reqbyteptr 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, int oldims, uschar **codeptr, const uschar **ptrptr, + int *errorcodeptr, BOOL lookbehind, BOOL reset_bracount, int skipbytes, + int *firstbyteptr, int *reqbyteptr, branch_chain *bcptr, compile_data *cd, + int *lengthptr) +{ +const uschar *ptr = *ptrptr; +uschar *code = *codeptr; +uschar *last_branch = code; +uschar *start_bracket = code; +uschar *reverse_count = NULL; +open_capitem capitem; +int capnumber = 0; +int firstbyte, reqbyte; +int branchfirstbyte, branchreqbyte; +int length; +int orig_bracount; +int max_bracount; +int old_external_options = cd->external_options; +branch_chain bc; + +bc.outer = bcptr; +bc.current_branch = code; + +firstbyte = reqbyte = 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. */ + +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; + + /* Handle a change of ims options at the start of the branch */ + + if ((options & PCRE_IMS) != oldims) + { + *code++ = OP_OPT; + *code++ = options & PCRE_IMS; + length += 2; + } + + /* 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, &branchfirstbyte, + &branchreqbyte, &bc, cd, (lengthptr == NULL)? NULL : &length)) + { + *ptrptr = ptr; + return FALSE; + } + + /* If the external options have changed during this branch, it means that we + are at the top level, and a leading option setting has been encountered. We + need to re-set the original option values to take account of this so that, + during the pre-compile phase, we know to allow for a re-set at the start of + subsequent branches. */ + + if (old_external_options != cd->external_options) + oldims = cd->external_options & PCRE_IMS; + + /* 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 firstbyte and reqbyte values for the + branch become the values for the regex. */ + + if (*last_branch != OP_ALT) + { + firstbyte = branchfirstbyte; + reqbyte = branchreqbyte; + } + + /* If this is not the first branch, the first char and reqbyte have to + match the values from all the previous branches, except that if the + previous value for reqbyte didn't have REQ_VARY set, it can still match, + and we set REQ_VARY for the regex. */ + + else + { + /* If we previously had a firstbyte, but it doesn't match the new branch, + we have to abandon the firstbyte for the regex, but if there was + previously no reqbyte, it takes on the value of the old firstbyte. */ + + if (firstbyte >= 0 && firstbyte != branchfirstbyte) + { + if (reqbyte < 0) reqbyte = firstbyte; + firstbyte = REQ_NONE; + } + + /* If we (now or from before) have no firstbyte, a firstbyte from the + branch becomes a reqbyte if there isn't a branch reqbyte. */ + + if (firstbyte < 0 && branchfirstbyte >= 0 && branchreqbyte < 0) + branchreqbyte = branchfirstbyte; + + /* Now ensure that the reqbytes match */ + + if ((reqbyte & ~REQ_VARY) != (branchreqbyte & ~REQ_VARY)) + reqbyte = REQ_NONE; + else reqbyte |= branchreqbyte; /* 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, 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 : 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. If any of the ims options were changed inside the group, + compile a resetting op-code following, except at the very end of the pattern. + 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, + 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; + } + + /* Reset options if needed. */ + + if ((options & PCRE_IMS) != oldims && *ptr == CHAR_RIGHT_PARENTHESIS) + { + *code++ = OP_OPT; + *code++ = oldims; + length += 2; + } + + /* Retain the highest bracket number, in case resetting was used. */ + + cd->bracount = max_bracount; + + /* Set values to pass back */ + + *codeptr = code; + *ptrptr = ptr; + *firstbyteptr = firstbyte; + *reqbyteptr = reqbyte; + 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 +counts, since OP_CIRC can match in the middle. + +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) + options points to the options setting + 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 uschar *code, int *options, unsigned int bracket_map, + unsigned int backref_map) +{ +do { + const uschar *scode = first_significant_code(code + _pcre_OP_lengths[*code], + options, PCRE_MULTILINE, FALSE); + register int op = *scode; + + /* Non-capturing brackets */ + + if (op == OP_BRA) + { + if (!is_anchored(scode, options, bracket_map, backref_map)) return FALSE; + } + + /* Capturing brackets */ + + else if (op == OP_CBRA) + { + int n = GET2(scode, 1+LINK_SIZE); + int new_map = bracket_map | ((n < 32)? (1 << n) : 1); + if (!is_anchored(scode, options, new_map, backref_map)) return FALSE; + } + + /* Other brackets */ + + else if (op == OP_ASSERT || op == OP_ONCE || op == OP_COND) + { + if (!is_anchored(scode, options, 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 && + ((*options & PCRE_MULTILINE) != 0 || 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 uschar *code, unsigned int bracket_map, + unsigned int backref_map) +{ +do { + const uschar *scode = first_significant_code(code + _pcre_OP_lengths[*code], + NULL, 0, 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 += _pcre_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, NULL, 0, FALSE); + op = *scode; + } + + /* Non-capturing brackets */ + + if (op == OP_BRA) + { + if (!is_startline(scode, bracket_map, backref_map)) return FALSE; + } + + /* Capturing brackets */ + + else if (op == OP_CBRA) + { + 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) + { + 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) 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) + options pointer to the options (used to check casing changes) + inassert TRUE if in an assertion + +Returns: -1 or the fixed first char +*/ + +static int +find_firstassertedchar(const uschar *code, int *options, BOOL inassert) +{ +register int c = -1; +do { + int d; + const uschar *scode = + first_significant_code(code + 1+LINK_SIZE, options, PCRE_CASELESS, TRUE); + register int op = *scode; + + switch(op) + { + default: + return -1; + + case OP_BRA: + case OP_CBRA: + case OP_ASSERT: + case OP_ONCE: + case OP_COND: + if ((d = find_firstassertedchar(scode, options, op == OP_ASSERT)) < 0) + return -1; + if (c < 0) c = d; else if (c != d) return -1; + break; + + case OP_EXACT: /* Fall through */ + scode += 2; + + case OP_CHAR: + case OP_CHARNC: + case OP_PLUS: + case OP_MINPLUS: + case OP_POSPLUS: + if (!inassert) return -1; + if (c < 0) + { + c = scode[1]; + if ((*options & PCRE_CASELESS) != 0) c |= 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 +*/ + +PCRE_EXP_DEFN pcre * PCRE_CALL_CONVENTION +pcre_compile(const char *pattern, int options, const char **errorptr, + int *erroroffset, const unsigned char *tables) +{ +return pcre_compile2(pattern, options, NULL, errorptr, erroroffset, tables); +} + + +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) +{ +real_pcre *re; +int length = 1; /* For final END opcode */ +int firstbyte, reqbyte, newline; +int errorcode = 0; +int skipatstart = 0; +BOOL utf8; +size_t size; +uschar *code; +const uschar *codestart; +const uschar *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. */ + +uschar cworkspace[COMPILE_WORK_SIZE]; + +/* Set this early so that early errors get offset 0. */ + +ptr = (const uschar *)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 = _pcre_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; + + if (strncmp((char *)(ptr+skipatstart+2), STRING_UTF8_RIGHTPAR, 5) == 0) + { skipatstart += 7; options |= PCRE_UTF8; continue; } + else if (strncmp((char *)(ptr+skipatstart+2), STRING_UCP_RIGHTPAR, 4) == 0) + { skipatstart += 6; options |= PCRE_UCP; continue; } + + if (strncmp((char *)(ptr+skipatstart+2), STRING_CR_RIGHTPAR, 3) == 0) + { skipatstart += 5; newnl = PCRE_NEWLINE_CR; } + else if (strncmp((char *)(ptr+skipatstart+2), STRING_LF_RIGHTPAR, 3) == 0) + { skipatstart += 5; newnl = PCRE_NEWLINE_LF; } + else if (strncmp((char *)(ptr+skipatstart+2), STRING_CRLF_RIGHTPAR, 5) == 0) + { skipatstart += 7; newnl = PCRE_NEWLINE_CR + PCRE_NEWLINE_LF; } + else if (strncmp((char *)(ptr+skipatstart+2), STRING_ANY_RIGHTPAR, 4) == 0) + { skipatstart += 6; newnl = PCRE_NEWLINE_ANY; } + else if (strncmp((char *)(ptr+skipatstart+2), STRING_ANYCRLF_RIGHTPAR, 8) == 0) + { skipatstart += 10; newnl = PCRE_NEWLINE_ANYCRLF; } + + else if (strncmp((char *)(ptr+skipatstart+2), STRING_BSR_ANYCRLF_RIGHTPAR, 12) == 0) + { skipatstart += 14; newbsr = PCRE_BSR_ANYCRLF; } + else if (strncmp((char *)(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; + } + +utf8 = (options & PCRE_UTF8) != 0; + +/* Can't support UTF8 unless PCRE has been compiled to include the code. */ + +#ifdef SUPPORT_UTF8 +if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0 && + (*erroroffset = _pcre_valid_utf8((USPTR)pattern, -1)) >= 0) + { + errorcode = ERR44; + goto PCRE_EARLY_ERROR_RETURN2; + } +#else +if (utf8) + { + 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. */ + +switch (options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) + { + case 0: + case PCRE_BSR_ANYCRLF: + case PCRE_BSR_UNICODE: + break; + default: 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")); +DPRINTF(("%s\n", pattern)); + +/* 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_workspace = cworkspace; +cd->start_code = cworkspace; +cd->hwm = cworkspace; +cd->start_pattern = (const uschar *)pattern; +cd->end_pattern = (const uschar *)(pattern + strlen(pattern)); +cd->req_varyopt = 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, cd->external_options & PCRE_IMS, + &code, &ptr, &errorcode, FALSE, FALSE, 0, &firstbyte, &reqbyte, NULL, cd, + &length); +if (errorcode != 0) goto PCRE_EARLY_ERROR_RETURN; + +DPRINTF(("end pre-compile: length=%d workspace=%d\n", length, + 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 = length + sizeof(real_pcre) + cd->names_found * (cd->name_entry_size + 3); +re = (real_pcre *)(pcre_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_byte = 0; +re->req_byte = 0; +re->name_table_offset = sizeof(real_pcre); +re->name_entry_size = cd->name_entry_size; +re->name_count = cd->names_found; +re->ref_count = 0; +re->tables = (tables == _pcre_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->bracount = 0; +cd->names_found = 0; +cd->name_table = (uschar *)re + re->name_table_offset; +codestart = cd->name_table + re->name_entry_size * re->name_count; +cd->start_code = codestart; +cd->hwm = cworkspace; +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 uschar *)pattern + skipatstart; +code = (uschar *)codestart; +*code = OP_BRA; +(void)compile_regex(re->options, re->options & PCRE_IMS, &code, &ptr, + &errorcode, FALSE, FALSE, 0, &firstbyte, &reqbyte, NULL, cd, NULL); +re->top_bracket = cd->bracount; +re->top_backref = cd->top_backref; +re->flags = cd->external_flags; + +if (cd->had_accept) reqbyte = -1; /* 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. */ + +while (errorcode == 0 && cd->hwm > cworkspace) + { + int offset, recno; + const uschar *groupptr; + cd->hwm -= LINK_SIZE; + offset = GET(cd->hwm, 0); + recno = GET(codestart, offset); + groupptr = _pcre_find_bracket(codestart, utf8, recno); + if (groupptr == NULL) errorcode = ERR53; + else PUT(((uschar *)codestart), offset, (int)(groupptr - codestart)); + } + +/* 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) + { + uschar *cc = (uschar *)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 = (uschar *)_pcre_find_bracket(codestart, utf8, -1); + cc != NULL; + cc = (uschar *)_pcre_find_bracket(cc, utf8, -1)) + { + if (GET(cc, 1) == 0) + { + int fixed_length; + uschar *be = cc - 1 - LINK_SIZE + GET(cc, -LINK_SIZE); + int end_op = *be; + *be = OP_END; + fixed_length = find_fixedlength(cc, re->options, TRUE, cd); + *be = end_op; + DPRINTF(("fixed length = %d\n", fixed_length)); + if (fixed_length < 0) + { + errorcode = (fixed_length == -2)? ERR36 : ERR25; + break; + } + PUT(cc, 1, fixed_length); + } + cc += 1 + LINK_SIZE; + } + } + +/* Failed to compile, or error while post-processing */ + +if (errorcode != 0) + { + (pcre_free)(re); + PCRE_EARLY_ERROR_RETURN: + *erroroffset = (int)(ptr - (const uschar *)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) + { + int temp_options = re->options; /* May get changed during these scans */ + if (is_anchored(codestart, &temp_options, 0, cd->backref_map)) + re->options |= PCRE_ANCHORED; + else + { + if (firstbyte < 0) + firstbyte = find_firstassertedchar(codestart, &temp_options, FALSE); + if (firstbyte >= 0) /* Remove caseless flag for non-caseable chars */ + { + int ch = firstbyte & 255; + re->first_byte = ((firstbyte & REQ_CASELESS) != 0 && + cd->fcc[ch] == ch)? ch : firstbyte; + 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 (reqbyte >= 0 && + ((re->options & PCRE_ANCHORED) == 0 || (reqbyte & REQ_VARY) != 0)) + { + int ch = reqbyte & 255; + re->req_byte = ((reqbyte & REQ_CASELESS) != 0 && + cd->fcc[ch] == ch)? (reqbyte & ~REQ_CASELESS) : reqbyte; + 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) + { + int ch = re->first_byte & 255; + const char *caseless = ((re->first_byte & REQ_CASELESS) == 0)? + "" : " (caseless)"; + if (isprint(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) + { + int ch = re->req_byte & 255; + const char *caseless = ((re->req_byte & REQ_CASELESS) == 0)? + "" : " (caseless)"; + if (isprint(ch)) printf("Req char = %c%s\n", ch, caseless); + else printf("Req char = \\x%02x%s\n", ch, caseless); + } + +pcre_printint(re, stdout, TRUE); + +/* This check is done here in the debugging case so that the code that +was compiled can be seen. */ + +if (code - codestart > length) + { + (pcre_free)(re); + *errorptr = find_error_text(ERR23); + *erroroffset = ptr - (uschar *)pattern; + if (errorcodeptr != NULL) *errorcodeptr = ERR23; + return NULL; + } +#endif /* PCRE_DEBUG */ + +return (pcre *)re; +} + +/* End of pcre_compile.c */ diff --git a/Library/pcre-8.10/pcre_config.c b/Library/pcre-8.10/pcre_config.c new file mode 100644 index 00000000..78e8560b --- /dev/null +++ b/Library/pcre-8.10/pcre_config.c @@ -0,0 +1,128 @@ +/************************************************* +* 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-2009 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_config(). */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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 +*/ + +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_config(int what, void *where) +{ +switch (what) + { + case PCRE_CONFIG_UTF8: +#ifdef SUPPORT_UTF8 + *((int *)where) = 1; +#else + *((int *)where) = 0; +#endif + break; + + case PCRE_CONFIG_UNICODE_PROPERTIES: +#ifdef SUPPORT_UCP + *((int *)where) = 1; +#else + *((int *)where) = 0; +#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) = 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/Library/pcre-8.10/pcre_dfa_exec.c b/Library/pcre-8.10/pcre_dfa_exec.c new file mode 100644 index 00000000..e55d9680 --- /dev/null +++ b/Library/pcre-8.10/pcre_dfa_exec.c @@ -0,0 +1,3251 @@ +/************************************************* +* 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-2010 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_dfa_exec(), which is an +alternative matching function that uses a sort of DFA algorithm (not a true +FSM). This is NOT Perl- compatible, but it has advantages in certain +applications. */ + + +/* NOTE ABOUT PERFORMANCE: A user of this function sent some code that improved +the performance of his patterns greatly. I could not use it as it stood, as it +was not thread safe, and made assumptions about pattern sizes. Also, it caused +test 7 to loop, and test 9 to crash with a segfault. + +The issue is the check for duplicate states, which is done by a simple linear +search up the state list. (Grep for "duplicate" below to find the code.) For +many patterns, there will never be many states active at one time, so a simple +linear search is fine. In patterns that have many active states, it might be a +bottleneck. The suggested code used an indexing scheme to remember which states +had previously been used for each character, and avoided the linear search when +it knew there was no chance of a duplicate. This was implemented when adding +states to the state lists. + +I wrote some thread-safe, not-limited code to try something similar at the time +of checking for duplicates (instead of when adding states), using index vectors +on the stack. It did give a 13% improvement with one specially constructed +pattern for certain subject strings, but on other strings and on many of the +simpler patterns in the test suite it did worse. The major problem, I think, +was the extra time to initialize the index. This had to be done for each call +of internal_dfa_exec(). (The supplied patch used a static vector, initialized +only once - I suspect this was the cause of the problems with the tests.) + +Overall, I concluded that the gains in some cases did not outweigh the losses +in others, so I abandoned this code. */ + + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define NLBLOCK md /* Block containing newline information */ +#define PSSTART start_subject /* Field containing processed string start */ +#define PSEND end_subject /* Field containing processed string end */ + +#include "pcre_internal.h" + + +/* For use to indent debugging output */ + +#define SP " " + + +/************************************************* +* Code parameters and static tables * +*************************************************/ + +/* These are offsets that are used to turn the OP_TYPESTAR and friends opcodes +into others, under special conditions. A gap of 20 between the blocks should be +enough. The resulting opcodes don't have to be less than 256 because they are +never stored, so we push them well clear of the normal opcodes. */ + +#define OP_PROP_EXTRA 300 +#define OP_EXTUNI_EXTRA 320 +#define OP_ANYNL_EXTRA 340 +#define OP_HSPACE_EXTRA 360 +#define OP_VSPACE_EXTRA 380 + + +/* This table identifies those opcodes that are followed immediately by a +character that is to be tested in some way. This makes it possible to +centralize the loading of these characters. In the case of Type * etc, the +"character" is the opcode for \D, \d, \S, \s, \W, or \w, which will always be a +small value. Non-zero values in the table are the offsets from the opcode where +the character is to be found. ***NOTE*** If the start of this table is +modified, the three tables that follow must also be modified. */ + +static const uschar 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, /* \Z, \z, Opt, ^, $ */ + 1, /* Char */ + 1, /* Charnc */ + 1, /* not */ + /* Positive single-char repeats */ + 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ + 3, 3, 3, /* upto, minupto, exact */ + 1, 1, 1, 3, /* *+, ++, ?+, upto+ */ + /* Negative single-char repeats - only for chars < 256 */ + 1, 1, 1, 1, 1, 1, /* NOT *, *?, +, +?, ?, ?? */ + 3, 3, 3, /* NOT upto, minupto, exact */ + 1, 1, 1, 3, /* NOT *+, ++, ?+, updo+ */ + /* Positive type repeats */ + 1, 1, 1, 1, 1, 1, /* Type *, *?, +, +?, ?, ?? */ + 3, 3, 3, /* Type upto, minupto, exact */ + 1, 1, 1, 3, /* 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, /* RECURSE */ + 0, /* CALLOUT */ + 0, /* Alt */ + 0, /* Ket */ + 0, /* KetRmax */ + 0, /* KetRmin */ + 0, /* Assert */ + 0, /* Assert not */ + 0, /* Assert behind */ + 0, /* Assert behind not */ + 0, /* Reverse */ + 0, 0, 0, 0, /* ONCE, BRA, CBRA, COND */ + 0, 0, 0, /* SBRA, SCBRA, SCOND */ + 0, 0, /* CREF, NCREF */ + 0, 0, /* RREF, NRREF */ + 0, /* DEF */ + 0, 0, /* BRAZERO, BRAMINZERO */ + 0, 0, 0, /* MARK, PRUNE, PRUNE_ARG, */ + 0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG, */ + 0, 0, 0, 0, 0 /* COMMIT, FAIL, ACCEPT, 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 uschar 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, /* \Z, \z, Opt, ^, $ */ + 1, /* Char */ + 1, /* Charnc */ + 1, /* not */ + /* Positive single-char repeats */ + 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ + 1, 1, 1, /* upto, minupto, exact */ + 1, 1, 1, 1, /* *+, ++, ?+, upto+ */ + /* 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+ */ + /* 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, /* RECURSE */ + 0, /* CALLOUT */ + 0, /* Alt */ + 0, /* Ket */ + 0, /* KetRmax */ + 0, /* KetRmin */ + 0, /* Assert */ + 0, /* Assert not */ + 0, /* Assert behind */ + 0, /* Assert behind not */ + 0, /* Reverse */ + 0, 0, 0, 0, /* ONCE, BRA, CBRA, COND */ + 0, 0, 0, /* SBRA, SCBRA, SCOND */ + 0, 0, /* CREF, NCREF */ + 0, 0, /* RREF, NRREF */ + 0, /* DEF */ + 0, 0, /* BRAZERO, BRAMINZERO */ + 0, 0, 0, /* MARK, PRUNE, PRUNE_ARG, */ + 0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG, */ + 0, 0, 0, 0, 0 /* COMMIT, FAIL, ACCEPT, CLOSE, SKIPZERO */ +}; + +/* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W, +and \w */ + +static const uschar 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 uschar 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 ims; /* ims flag bits */ + 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(unsigned char *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 + ims the current ims flags + rlevel function call recursion level + recursing regex recursive call 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->ims = ims; \ + 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->ims = ims; \ + 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->ims = ims; \ + 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->ims = ims; \ + 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 uschar *this_start_code, + const uschar *current_subject, + int start_offset, + int *offsets, + int offsetcount, + int *workspace, + int wscount, + int ims, + int rlevel, + int recursing) +{ +stateblock *active_states, *new_states, *temp_states; +stateblock *next_active_state, *next_new_state; + +const uschar *ctypes, *lcc, *fcc; +const uschar *ptr; +const uschar *end_code, *first_op; + +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 uschar *start_subject = md->start_subject; +const uschar *end_subject = md->end_subject; +const uschar *start_code = md->start_code; + +#ifdef SUPPORT_UTF8 +BOOL utf8 = (md->poptions & PCRE_UTF8) != 0; +#else +BOOL utf8 = 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 r=%d\n", + rlevel*2-2, SP, rlevel*2-2, SP, rlevel, recursing)); + +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)? 2: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_UTF8 + /* In character mode we have to step back character by character */ + + if (utf8) + { + for (gone_back = 0; gone_back < max_back; gone_back++) + { + if (current_subject <= start_subject) break; + current_subject--; + while (current_subject > start_subject && + (*current_subject & 0xc0) == 0x80) + 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)? 2: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, 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((uschar *)ptr, strlen((char *)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_UTF8 + if (utf8) { GETCHARLEN(c, ptr, clen); } else +#endif /* SUPPORT_UTF8 */ + 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; + const uschar *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 + + /* This variable is referred to implicity in the ADD_xxx macros. */ + + ims = current_state->ims; + + /* 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_UTF8 + if (utf8) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else +#endif /* SUPPORT_UTF8 */ + 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. Otherwise, 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: + 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 + 3 + LINK_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) || + ((ims & PCRE_MULTILINE) != 0 && + ptr != end_subject && + WAS_NEWLINE(ptr))) + { ADD_ACTIVE(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_EOD: + if (ptr >= end_subject) { ADD_ACTIVE(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_OPT: + ims = code[1]; + ADD_ACTIVE(state_offset + 2, 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 || (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->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) && + ((ims & PCRE_MULTILINE) != 0 || ptr == end_subject - md->nllen) + )) + { ADD_ACTIVE(state_offset + 1, 0); } + } + else if ((ims & PCRE_MULTILINE) != 0 && 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 uschar *temp = ptr - 1; + if (temp < md->start_used_ptr) md->start_used_ptr = temp; +#ifdef SUPPORT_UTF8 + if (utf8) 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 = _pcre_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 = _pcre_ucp_gentype[prop->chartype] == ucp_L || + _pcre_ucp_gentype[prop->chartype] == ucp_N; + break; + + case PT_SPACE: /* Perl space */ + OK = _pcre_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 = _pcre_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 = _pcre_ucp_gentype[prop->chartype] == ucp_L || + _pcre_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 + 4, 0); } + else + { ADD_NEW(state_offset, count); } + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + case OP_TYPEPOSUPTO: + ADD_ACTIVE(state_offset + 4, 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 + 4, 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 = _pcre_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 = _pcre_ucp_gentype[prop->chartype] == ucp_L || + _pcre_ucp_gentype[prop->chartype] == ucp_N; + break; + + case PT_SPACE: /* Perl space */ + OK = _pcre_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 = _pcre_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 = _pcre_ucp_gentype[prop->chartype] == ucp_L || + _pcre_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 uschar *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 = _pcre_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 = _pcre_ucp_gentype[prop->chartype] == ucp_L || + _pcre_ucp_gentype[prop->chartype] == ucp_N; + break; + + case PT_SPACE: /* Perl space */ + OK = _pcre_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 = _pcre_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 = _pcre_ucp_gentype[prop->chartype] == ucp_L || + _pcre_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 uschar *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 + 6, 0); } + count = current_state->count; /* Number already matched */ + if (clen > 0) + { + BOOL OK; + const ucd_record * prop = GET_UCD(c); + switch(code[4]) + { + 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 = _pcre_ucp_gentype[prop->chartype] == code[5]; + break; + + case PT_PC: + OK = prop->chartype == code[5]; + break; + + case PT_SC: + OK = prop->script == code[5]; + break; + + /* These are specials for combination cases. */ + + case PT_ALNUM: + OK = _pcre_ucp_gentype[prop->chartype] == ucp_L || + _pcre_ucp_gentype[prop->chartype] == ucp_N; + break; + + case PT_SPACE: /* Perl space */ + OK = _pcre_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 = _pcre_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 = _pcre_ucp_gentype[prop->chartype] == ucp_L || + _pcre_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 + 6, 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 + 4, 0); } + count = current_state->count; /* Number already matched */ + if (clen > 0 && UCD_CATEGORY(c) != ucp_M) + { + const uschar *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 + 4), 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 + 4, 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 + 4), 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 + 4, 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 + 4), 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 + 4, 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 + 4), 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_CHARNC: + if (clen == 0) break; + +#ifdef SUPPORT_UTF8 + if (utf8) + { + 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_UTF8 */ + + /* Non-UTF-8 mode */ + { + if (lcc[c] == 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 uschar *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. 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) + { + unsigned int otherd = ((ims & PCRE_CASELESS) != 0)? fcc[d] : d; + if (c != d && c != otherd) { ADD_NEW(state_offset + dlen + 1, 0); } + } + break; + + /*-----------------------------------------------------------------*/ + 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 ((ims & PCRE_CASELESS) != 0) + { +#ifdef SUPPORT_UTF8 + if (utf8 && d >= 128) + { +#ifdef SUPPORT_UCP + otherd = UCD_OTHERCASE(d); +#endif /* SUPPORT_UCP */ + } + else +#endif /* SUPPORT_UTF8 */ + otherd = 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_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 ((ims & PCRE_CASELESS) != 0) + { +#ifdef SUPPORT_UTF8 + if (utf8 && d >= 128) + { +#ifdef SUPPORT_UCP + otherd = UCD_OTHERCASE(d); +#endif /* SUPPORT_UCP */ + } + else +#endif /* SUPPORT_UTF8 */ + otherd = 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_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 ((ims & PCRE_CASELESS) != 0) + { +#ifdef SUPPORT_UTF8 + if (utf8 && d >= 128) + { +#ifdef SUPPORT_UCP + otherd = UCD_OTHERCASE(d); +#endif /* SUPPORT_UCP */ + } + else +#endif /* SUPPORT_UTF8 */ + otherd = 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_EXACT: + case OP_NOTEXACT: + count = current_state->count; /* Number already matched */ + if (clen > 0) + { + unsigned int otherd = NOTACHAR; + if ((ims & PCRE_CASELESS) != 0) + { +#ifdef SUPPORT_UTF8 + if (utf8 && d >= 128) + { +#ifdef SUPPORT_UCP + otherd = UCD_OTHERCASE(d); +#endif /* SUPPORT_UCP */ + } + else +#endif /* SUPPORT_UTF8 */ + otherd = fcc[d]; + } + if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) + { + if (++count >= GET2(code, 1)) + { ADD_NEW(state_offset + dlen + 3, 0); } + else + { ADD_NEW(state_offset, count); } + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_UPTO: + case OP_MINUPTO: + case OP_POSUPTO: + case OP_NOTUPTO: + case OP_NOTMINUPTO: + case OP_NOTPOSUPTO: + ADD_ACTIVE(state_offset + dlen + 3, 0); + count = current_state->count; /* Number already matched */ + if (clen > 0) + { + unsigned int otherd = NOTACHAR; + if ((ims & PCRE_CASELESS) != 0) + { +#ifdef SUPPORT_UTF8 + if (utf8 && d >= 128) + { +#ifdef SUPPORT_UCP + otherd = UCD_OTHERCASE(d); +#endif /* SUPPORT_UCP */ + } + else +#endif /* SUPPORT_UTF8 */ + otherd = 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 + 3, 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 uschar *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 + 33; + if (clen > 0) + { + isinclass = (c > 255)? (codevalue == OP_NCLASS) : + ((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 = _pcre_xclass(c, code + 1 + LINK_SIZE); + } + + /* 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 + 5, 0); } + if (isinclass) + { + int max = GET2(ecode, 3); + if (++count >= max && max != 0) /* Max 0 => no limit */ + { ADD_NEW(next_state_offset + 5, 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 uschar *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 */ + ims, /* the current ims flags */ + rlevel, /* function recursion level */ + recursing); /* pass on regex recursion */ + + 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 (pcre_callout != NULL) + { + pcre_callout_block cb; + cb.version = 1; /* Version 1 of the callout block */ + cb.callout_number = code[LINK_SIZE+2]; + cb.offset_vector = offsets; + cb.subject = (PCRE_SPTR)start_subject; + 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; + if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc; /* Abandon */ + } + if (rrc > 0) break; /* Fail this thread */ + code += _pcre_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 (recursing > 0) + { ADD_ACTIVE(state_offset + LINK_SIZE + 4, 0); } + else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); } + } + + /* Otherwise, the condition is an assertion */ + + else + { + int rc; + const uschar *asscode = code + LINK_SIZE + 1; + const uschar *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 */ + ims, /* the current ims flags */ + rlevel, /* function recursion level */ + recursing); /* pass on regex recursion */ + + 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: + { + int local_offsets[1000]; + int local_workspace[1000]; + int rc; + + DPRINTF(("%.*sStarting regex recursion %d\n", rlevel*2-2, SP, + recursing + 1)); + + rc = internal_dfa_exec( + md, /* fixed match data */ + start_code + GET(code, 1), /* 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 */ + ims, /* the current ims flags */ + rlevel, /* function recursion level */ + recursing + 1); /* regex recurse level */ + + DPRINTF(("%.*sReturn from regex recursion %d: rc=%d\n", rlevel*2-2, SP, + recursing + 1, 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) + { + const uschar *p = start_subject + local_offsets[rc]; + const uschar *pp = start_subject + local_offsets[rc+1]; + int charcount = local_offsets[rc+1] - local_offsets[rc]; + while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--; + 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_ONCE: + { + 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 */ + ims, /* the current ims flags */ + rlevel, /* function recursion level */ + recursing); /* pass on regex recursion */ + + if (rc >= 0) + { + const uschar *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 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 + { + const uschar *p = start_subject + local_offsets[0]; + const uschar *pp = start_subject + local_offsets[1]; + while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--; + 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 (pcre_callout != NULL) + { + pcre_callout_block cb; + cb.version = 1; /* Version 1 of the callout block */ + cb.callout_number = code[1]; + cb.offset_vector = offsets; + cb.subject = (PCRE_SPTR)start_subject; + 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; + if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc; /* Abandon */ + } + if (rrc == 0) + { ADD_ACTIVE(state_offset + _pcre_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 > current_subject) /* Matched 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 +*/ + +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) +{ +real_pcre *re = (real_pcre *)argument_re; +dfa_match_data match_block; +dfa_match_data *md = &match_block; +BOOL utf8, anchored, startline, firstline; +const uschar *current_subject, *end_subject, *lcc; + +pcre_study_data internal_study; +const pcre_study_data *study = NULL; +real_pcre internal_re; + +const uschar *req_byte_ptr; +const uschar *start_bits = NULL; +BOOL first_byte_caseless = FALSE; +BOOL req_byte_caseless = FALSE; +int first_byte = -1; +int req_byte = -1; +int req_byte2 = -1; +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; + +/* 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, +test for a regex that was compiled on a host of opposite endianness. If this is +the case, flipped values are put in internal_re and internal_study if there was +study data too. */ + +if (re->magic_number != MAGIC_NUMBER) + { + re = _pcre_try_flipped(re, &internal_re, study, &internal_study); + if (re == NULL) return PCRE_ERROR_BADMAGIC; + if (study != NULL) study = &internal_study; + } + +/* Set some local values */ + +current_subject = (const unsigned char *)subject + start_offset; +end_subject = (const unsigned char *)subject + length; +req_byte_ptr = current_subject - 1; + +#ifdef SUPPORT_UTF8 +utf8 = (re->options & PCRE_UTF8) != 0; +#else +utf8 = 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 uschar *)argument_re + + re->name_table_offset + re->name_count * re->name_entry_size; +md->start_subject = (const unsigned char *)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_UTF8 +if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0) + { + if (_pcre_valid_utf8((uschar *)subject, length) >= 0) + return PCRE_ERROR_BADUTF8; + if (start_offset > 0 && start_offset < length) + { + int tb = ((uschar *)subject)[start_offset]; + if (tb > 127) + { + tb &= 0xc0; + if (tb != 0 && tb != 0xc0) 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 = _pcre_default_tables; + +/* The lower casing table and the "must be at the start of a line" flag are +used in a loop when finding where to start. */ + +lcc = md->tables + lcc_offset; +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) + { + first_byte = re->first_byte & 255; + if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE) + first_byte = lcc[first_byte]; + } + 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) + { + req_byte = re->req_byte & 255; + req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0; + req_byte2 = (md->tables + fcc_offset)[req_byte]; /* case flipped */ + } + +/* 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 uschar *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) + { + USPTR t = current_subject; +#ifdef SUPPORT_UTF8 + if (utf8) + { + while (t < md->end_subject && !IS_NEWLINE(t)) + { + t++; + while (t < end_subject && (*t & 0xc0) == 0x80) 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. */ + + if ((options & PCRE_NO_START_OPTIMIZE) == 0) + { + /* Advance to a known first byte. */ + + if (first_byte >= 0) + { + if (first_byte_caseless) + while (current_subject < end_subject && + lcc[*current_subject] != first_byte) + current_subject++; + else + while (current_subject < end_subject && + *current_subject != first_byte) + 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_UTF8 + if (utf8) + { + while (current_subject < end_subject && + !WAS_NEWLINE(current_subject)) + { + current_subject++; + while(current_subject < end_subject && + (*current_subject & 0xc0) == 0x80) + 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; + if ((start_bits[c/8] & (1 << (c&7))) == 0) + { + current_subject++; +#ifdef SUPPORT_UTF8 + if (utf8) + while(current_subject < end_subject && + (*current_subject & 0xc0) == 0x80) 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 & 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_byte is set, we know that that character must appear in the + subject for the match to succeed. If the first character is set, req_byte + 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 (req_byte >= 0 && end_subject - current_subject < REQ_BYTE_MAX) + { + register const uschar *p = current_subject + ((first_byte >= 0)? 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_byte_ptr) + { + if (req_byte_caseless) + { + while (p < end_subject) + { + register int pp = *p++; + if (pp == req_byte || pp == req_byte2) { p--; break; } + } + } + else + { + while (p < end_subject) + { + if (*p++ == req_byte) { 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_byte_ptr = p; + } + } + } + } /* End of optimizations that are done when not restarting */ + + /* OK, now we can do the business */ + + md->start_used_ptr = current_subject; + + 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 */ + re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL), /* ims flags */ + 0, /* function recurse level */ + 0); /* regex 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++; + if (utf8) + { + while (current_subject < end_subject && (*current_subject & 0xc0) == 0x80) + current_subject++; + } + 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/Library/pcre-8.10/pcre_exec.c b/Library/pcre-8.10/pcre_exec.c new file mode 100644 index 00000000..8029bef5 --- /dev/null +++ b/Library/pcre-8.10/pcre_exec.c @@ -0,0 +1,6255 @@ +/************************************************* +* 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-2010 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains pcre_exec(), the externally visible function that does +pattern matching using an NFA algorithm, trying to mimic Perl as closely as +possible. There are also some static supporting functions. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define NLBLOCK md /* Block containing newline information */ +#define PSSTART start_subject /* Field containing processed string start */ +#define PSEND end_subject /* Field containing processed string end */ + +#include "pcre_internal.h" + +/* Undefine some potentially clashing cpp symbols */ + +#undef min +#undef max + +/* Flag bits for the match() function */ + +#define match_condassert 0x01 /* Called to check a condition assertion */ +#define match_cbegroup 0x02 /* 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_PRUNE (-997) +#define MATCH_SKIP (-996) +#define MATCH_SKIP_ARG (-995) +#define MATCH_THEN (-994) + +/* This is a convenience macro for code that occurs many times. */ + +#define MRRETURN(ra) \ + { \ + md->mark = markptr; \ + RRETURN(ra); \ + } + +/* 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 uschar *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 * +*************************************************/ + +/* If a back reference hasn't been set, the length that is passed is greater +than the number of characters left in the string, so the match fails. + +Arguments: + offset index into the offset vector + eptr points into the subject + length length to be matched + md points to match data block + ims the ims flags + +Returns: TRUE if matched +*/ + +static BOOL +match_ref(int offset, register USPTR eptr, int length, match_data *md, + unsigned long int ims) +{ +USPTR p = md->start_subject + md->offset_vector[offset]; + +#ifdef PCRE_DEBUG +if (eptr >= md->end_subject) + printf("matching subject "); +else + { + printf("matching subject "); + pchars(eptr, length, TRUE, md); + } +printf(" against backref "); +pchars(p, length, FALSE, md); +printf("\n"); +#endif + +/* Always fail if not enough characters left */ + +if (length > md->end_subject - eptr) return FALSE; + +/* 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 ((ims & PCRE_CASELESS) != 0) + { +#ifdef SUPPORT_UTF8 +#ifdef SUPPORT_UCP + if (md->utf8) + { + USPTR endptr = eptr + length; + while (eptr < endptr) + { + int c, d; + GETCHARINC(c, eptr); + GETCHARINC(d, p); + if (c != d && c != UCD_OTHERCASE(d)) return FALSE; + } + } + else +#endif +#endif + + /* The same code works when not in UTF-8 mode and in UTF-8 mode when there + is no UCP support. */ + + while (length-- > 0) + { if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE; } + } + +/* In the caseful case, we can just compare the bytes, whether or not we +are in UTF-8 mode. */ + +else + { while (length-- > 0) if (*p++ != *eptr++) return FALSE; } + +return TRUE; +} + + + +/*************************************************************************** +**************************************************************************** + 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 }; + +/* 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,rf,rg,rw) \ + { \ + printf("match() called in line %d\n", __LINE__); \ + rrc = match(ra,rb,mstart,markptr,rc,rd,re,rf,rg,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,rf,rg,rw) \ + rrc = match(ra,rb,mstart,markptr,rc,rd,re,rf,rg,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,rf,rg,rw)\ + {\ + heapframe *newframe = (pcre_stack_malloc)(sizeof(heapframe));\ + if (newframe == NULL) RRETURN(PCRE_ERROR_NOMEMORY);\ + frame->Xwhere = rw; \ + newframe->Xeptr = ra;\ + newframe->Xecode = rb;\ + newframe->Xmstart = mstart;\ + newframe->Xmarkptr = markptr;\ + newframe->Xoffset_top = rc;\ + newframe->Xims = re;\ + newframe->Xeptrb = rf;\ + newframe->Xflags = rg;\ + 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;\ + (pcre_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 */ + + USPTR Xeptr; + const uschar *Xecode; + USPTR Xmstart; + USPTR Xmarkptr; + int Xoffset_top; + long int Xims; + eptrblock *Xeptrb; + int Xflags; + unsigned int Xrdepth; + + /* Function local variables */ + + USPTR Xcallpat; +#ifdef SUPPORT_UTF8 + USPTR Xcharptr; +#endif + USPTR Xdata; + USPTR Xnext; + USPTR Xpp; + USPTR Xprev; + USPTR Xsaved_eptr; + + recursion_info Xnew_recursive; + + BOOL Xcur_is_word; + BOOL Xcondition; + BOOL Xprev_is_word; + + unsigned long int Xoriginal_ims; + +#ifdef SUPPORT_UCP + int Xprop_type; + int Xprop_value; + int Xprop_fail_result; + int Xprop_category; + int Xprop_chartype; + int Xprop_script; + int Xoclength; + uschar Xocchars[8]; +#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 +appears 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 > mstart)\ + {\ + md->hitend = TRUE;\ + if (md->partial > 1) MRRETURN(PCRE_ERROR_PARTIAL);\ + } + +#define SCHECK_PARTIAL()\ + if (md->partial != 0 && eptr > mstart)\ + {\ + md->hitend = TRUE;\ + if (md->partial > 1) MRRETURN(PCRE_ERROR_PARTIAL);\ + } + + +/* Performance note: It might be tempting to extract commonly used fields from +the md structure (e.g. utf8, 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) + markptr pointer to the most recent MARK name, or NULL + offset_top current top pointer + md pointer to "static" info for the match + ims current /i, /m, and /s options + eptrb pointer to chain of blocks containing eptr at start of + brackets - for testing for empty matches + flags can contain + match_condassert - this is an assertion condition + match_cbegroup - this is the start of an unlimited repeat + group that can match an empty string + 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 USPTR eptr, REGISTER const uschar *ecode, USPTR mstart, + const uschar *markptr, int offset_top, match_data *md, unsigned long int ims, + eptrblock *eptrb, int flags, 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 utf8; /* Local copy of UTF-8 flag for speed */ + +BOOL minimize, possessive; /* Quantifier options */ +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" which is obtained from +heap storage. Set up the top-level frame here; others are obtained from the +heap whenever RMATCH() does a "recursion". See the macro definitions above. */ + +#ifdef NO_RECURSE +heapframe *frame = (pcre_stack_malloc)(sizeof(heapframe)); +if (frame == NULL) RRETURN(PCRE_ERROR_NOMEMORY); +frame->Xprevframe = NULL; /* Marks the top level */ + +/* Copy in the original argument variables */ + +frame->Xeptr = eptr; +frame->Xecode = ecode; +frame->Xmstart = mstart; +frame->Xmarkptr = markptr; +frame->Xoffset_top = offset_top; +frame->Xims = ims; +frame->Xeptrb = eptrb; +frame->Xflags = flags; +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 markptr frame->Xmarkptr +#define offset_top frame->Xoffset_top +#define ims frame->Xims +#define eptrb frame->Xeptrb +#define flags frame->Xflags +#define rdepth frame->Xrdepth + +/* Ditto for the local variables */ + +#ifdef SUPPORT_UTF8 +#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 + +#define original_ims frame->Xoriginal_ims + +#ifdef SUPPORT_UCP +#define prop_type frame->Xprop_type +#define prop_value frame->Xprop_value +#define prop_fail_result frame->Xprop_fail_result +#define prop_category frame->Xprop_category +#define prop_chartype frame->Xprop_chartype +#define prop_script frame->Xprop_script +#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 + + +#ifdef SUPPORT_UTF8 /* Many of these variables are used only */ +const uschar *charptr; /* in small blocks of the code. My normal */ +#endif /* style of coding would have declared */ +const uschar *callpat; /* them within each of those blocks. */ +const uschar *data; /* However, in order to accommodate the */ +const uschar *next; /* version of this code that uses an */ +USPTR pp; /* external "stack" implemented on the */ +const uschar *prev; /* heap, it is easier to declare them all */ +USPTR saved_eptr; /* here, so the declarations can be cut */ + /* out in a block. The only declarations */ +recursion_info new_recursive; /* within blocks below are for variables */ + /* that do not have to be preserved over */ +BOOL cur_is_word; /* a recursive call to RMATCH(). */ +BOOL condition; +BOOL prev_is_word; + +unsigned long int original_ims; + +#ifdef SUPPORT_UCP +int prop_type; +int prop_value; +int prop_fail_result; +int prop_category; +int prop_chartype; +int prop_script; +int oclength; +uschar occhars[8]; +#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; +#endif /* NO_RECURSE */ + +/* 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_UTF8 +utf8 = md->utf8; /* Local copy of the flag */ +#else +utf8 = 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); + +original_ims = ims; /* Save for resetting on ')' */ + +/* At the start of a group with an unlimited repeat that may match an empty +string, the match_cbegroup flag is set. When this is the case, 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 flag 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 ((flags & match_cbegroup) != 0) + { + newptrb.epb_saved_eptr = eptr; + newptrb.epb_prev = eptrb; + eptrb = &newptrb; + } + +/* Now start processing the opcodes. */ + +for (;;) + { + minimize = possessive = FALSE; + op = *ecode; + + switch(op) + { + case OP_MARK: + markptr = ecode + 2; + RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md, + ims, eptrb, flags, RM55); + + /* 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. */ + + if (rrc == MATCH_SKIP_ARG && + strcmp((char *)markptr, (char *)(md->start_match_ptr)) == 0) + { + md->start_match_ptr = eptr; + RRETURN(MATCH_SKIP); + } + + if (md->mark == NULL) md->mark = markptr; + RRETURN(rrc); + + case OP_FAIL: + MRRETURN(MATCH_NOMATCH); + + case OP_COMMIT: + RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, + ims, eptrb, flags, RM52); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + MRRETURN(MATCH_COMMIT); + + case OP_PRUNE: + RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, + ims, eptrb, flags, RM51); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + MRRETURN(MATCH_PRUNE); + + case OP_PRUNE_ARG: + RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md, + ims, eptrb, flags, RM56); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + md->mark = ecode + 2; + RRETURN(MATCH_PRUNE); + + case OP_SKIP: + RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, + ims, eptrb, flags, RM53); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + md->start_match_ptr = eptr; /* Pass back current position */ + MRRETURN(MATCH_SKIP); + + case OP_SKIP_ARG: + RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md, + ims, eptrb, flags, RM57); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + + /* Pass back the current skip name by overloading md->start_match_ptr and + returning the special MATCH_SKIP_ARG return code. This will either be + caught by a matching MARK, or get to the top, where it is treated the same + as PRUNE. */ + + md->start_match_ptr = ecode + 2; + RRETURN(MATCH_SKIP_ARG); + + case OP_THEN: + RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, + ims, eptrb, flags, RM54); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + MRRETURN(MATCH_THEN); + + case OP_THEN_ARG: + RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md, + ims, eptrb, flags, RM58); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + md->mark = ecode + 2; + RRETURN(MATCH_THEN); + + /* Handle a capturing bracket. 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. + + If the bracket fails to match, we need to restore this 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; + + DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); + md->offset_vector[md->offset_end - number] = + (int)(eptr - md->start_subject); + + flags = (op == OP_SCBRA)? match_cbegroup : 0; + do + { + RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, + ims, eptrb, flags, RM1); + if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); + md->capture_last = save_capture_last; + ecode += GET(ecode, 1); + } + while (*ecode == OP_ALT); + + 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; + + if (rrc != MATCH_THEN) md->mark = markptr; + 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 bracket. Loop for all the alternatives. When we get to the + final alternative within the brackets, we would return the result of a + recursive call to match() whatever happened. We can reduce stack usage by + turning this into a tail recursion, except in the case when match_cbegroup + is set.*/ + + case OP_BRA: + case OP_SBRA: + DPRINTF(("start non-capturing bracket\n")); + flags = (op >= OP_SBRA)? match_cbegroup : 0; + for (;;) + { + if (ecode[GET(ecode, 1)] != OP_ALT) /* Final alternative */ + { + if (flags == 0) /* Not a possibly empty group */ + { + ecode += _pcre_OP_lengths[*ecode]; + DPRINTF(("bracket 0 tail recursion\n")); + goto TAIL_RECURSE; + } + + /* Possibly empty group; can't use tail recursion. */ + + RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims, + eptrb, flags, RM48); + if (rrc == MATCH_NOMATCH) md->mark = markptr; + RRETURN(rrc); + } + + /* For non-final alternatives, continue the loop for a NOMATCH result; + otherwise return. */ + + RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims, + eptrb, flags, RM2); + if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); + ecode += GET(ecode, 1); + } + /* 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. As there is only one branch to be + obeyed, we can use tail recursion to avoid using another stack frame. */ + + 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 (pcre_callout != NULL) + { + pcre_callout_block cb; + cb.version = 1; /* Version 1 of the callout block */ + cb.callout_number = ecode[LINK_SIZE+2]; + cb.offset_vector = md->offset_vector; + cb.subject = (PCRE_SPTR)md->start_subject; + 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; + if ((rrc = (*pcre_callout)(&cb)) > 0) MRRETURN(MATCH_NOMATCH); + if (rrc < 0) RRETURN(rrc); + } + ecode += _pcre_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 && recno != RREF_ANY) + { + uschar *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) + { + uschar *slotB = slotA; + while (slotB > md->name_table) + { + slotB -= md->name_entry_size; + if (strcmp((char *)slotA + 2, (char *)slotB + 2) == 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((char *)slotA + 2, (char *)slotB + 2) == 0) + { + condition = GET2(slotB, 0) == md->recursive->group_num; + if (condition) break; + } + else break; + } + } + } + } + + /* Chose branch according to the condition */ + + ecode += condition? 3 : 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; + uschar *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) + { + uschar *slotB = slotA; + while (slotB > md->name_table) + { + slotB -= md->name_entry_size; + if (strcmp((char *)slotA + 2, (char *)slotB + 2) == 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((char *)slotA + 2, (char *)slotB + 2) == 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? 3 : 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 + the final argument match_condassert causes it to stop at the end of an + assertion. */ + + else + { + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, + match_condassert, RM3); + if (rrc == MATCH_MATCH) + { + condition = TRUE; + ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE + 2); + while (*ecode == OP_ALT) ecode += GET(ecode, 1); + } + 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, + we can use tail recursion to avoid using another stack frame, except when + match_cbegroup is required for an unlimited repeat of a possibly empty + group. If the second alternative doesn't exist, we can just plough on. */ + + if (condition || *ecode == OP_ALT) + { + ecode += 1 + LINK_SIZE; + if (op == OP_SCOND) /* Possibly empty group */ + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, match_cbegroup, RM49); + RRETURN(rrc); + } + else /* Group must match something */ + { + flags = 0; + goto TAIL_RECURSE; + } + } + else /* Condition false & no alternative */ + { + 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 += 3; + break; + + + /* End of the pattern, either real or forced. If we are in a top-level + recursion, we should restore the offsets appropriately and continue from + after the call. */ + + case OP_ACCEPT: + case OP_END: + if (md->recursive != NULL && md->recursive->group_num == 0) + { + recursion_info *rec = md->recursive; + DPRINTF(("End of pattern in a (?0) recursion\n")); + md->recursive = rec->prevrec; + memmove(md->offset_vector, rec->offset_save, + rec->saved_max * sizeof(int)); + offset_top = rec->save_offset_top; + ims = original_ims; + ecode = rec->after_call; + break; + } + + /* Otherwise, if we have matched an empty string, fail if 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 && + (md->notempty || + (md->notempty_atstart && + mstart == md->start_subject + md->start_offset))) + MRRETURN(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 MRRETURN when the heap is in use. */ + + rrc = (op == OP_END)? MATCH_MATCH : MATCH_ACCEPT; + MRRETURN(rrc); + + /* Change option settings */ + + case OP_OPT: + ims = ecode[1]; + ecode += 2; + DPRINTF(("ims set to %02lx\n", ims)); + break; + + /* 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. */ + + case OP_ASSERT: + case OP_ASSERTBACK: + do + { + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0, + RM4); + if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) + { + mstart = md->start_match_ptr; /* In case \K reset it */ + break; + } + if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); + ecode += GET(ecode, 1); + } + while (*ecode == OP_ALT); + if (*ecode == OP_KET) MRRETURN(MATCH_NOMATCH); + + /* If checking an assertion for a condition, return MATCH_MATCH. */ + + if ((flags & match_condassert) != 0) 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: + do + { + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0, + RM5); + if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) MRRETURN(MATCH_NOMATCH); + if (rrc == MATCH_SKIP || rrc == MATCH_PRUNE || rrc == MATCH_COMMIT) + { + do ecode += GET(ecode,1); while (*ecode == OP_ALT); + break; + } + if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); + ecode += GET(ecode,1); + } + while (*ecode == OP_ALT); + + if ((flags & match_condassert) != 0) RRETURN(MATCH_MATCH); + + 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_UTF8 + if (utf8) + { + i = GET(ecode, 1); + while (i-- > 0) + { + eptr--; + if (eptr < md->start_subject) MRRETURN(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) MRRETURN(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 (pcre_callout != NULL) + { + pcre_callout_block cb; + cb.version = 1; /* Version 1 of the callout block */ + cb.callout_number = ecode[1]; + cb.offset_vector = md->offset_vector; + cb.subject = (PCRE_SPTR)md->start_subject; + 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; + if ((rrc = (*pcre_callout)(&cb)) > 0) MRRETURN(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.) + + If there are any capturing brackets started but not finished, we have to + save their starting points and reinstate them after the recursion. However, + we don't know how many such there are (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. A problem is what to do if the malloc fails ... there is no way of + returning to the top level with an error. Save the top REC_STACK_SAVE_MAX + values on the stack, and accept that the rest may be wrong. + + 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. */ + + case OP_RECURSE: + { + callpat = md->start_code + GET(ecode, 1); + new_recursive.group_num = (callpat == md->start_code)? 0 : + GET2(callpat, 1 + LINK_SIZE); + + /* Add to "recursing stack" */ + + new_recursive.prevrec = md->recursive; + md->recursive = &new_recursive; + + /* Find where to continue from afterwards */ + + ecode += 1 + LINK_SIZE; + new_recursive.after_call = ecode; + + /* 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 *)(pcre_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)); + new_recursive.save_offset_top = offset_top; + + /* OK, now we can do the recursion. For each top-level alternative we + restore the offset and recursion data. */ + + DPRINTF(("Recursing into group %d\n", new_recursive.group_num)); + flags = (*callpat >= OP_SBRA)? match_cbegroup : 0; + do + { + RMATCH(eptr, callpat + _pcre_OP_lengths[*callpat], offset_top, + md, ims, eptrb, flags, RM6); + if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) + { + DPRINTF(("Recursion matched\n")); + md->recursive = new_recursive.prevrec; + if (new_recursive.offset_save != stacksave) + (pcre_free)(new_recursive.offset_save); + MRRETURN(MATCH_MATCH); + } + else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) + { + DPRINTF(("Recursion gave error %d\n", rrc)); + if (new_recursive.offset_save != stacksave) + (pcre_free)(new_recursive.offset_save); + RRETURN(rrc); + } + + md->recursive = &new_recursive; + memcpy(md->offset_vector, new_recursive.offset_save, + new_recursive.saved_max * sizeof(int)); + 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) + (pcre_free)(new_recursive.offset_save); + MRRETURN(MATCH_NOMATCH); + } + /* Control never reaches here */ + + /* "Once" brackets are like assertion brackets except that after a match, + the point in the subject string is not moved back. Thus there can never be + a move back into the brackets. Friedl calls these "atomic" subpatterns. + 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: + prev = ecode; + saved_eptr = eptr; + + do + { + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0, RM7); + if (rrc == MATCH_MATCH) /* Note: _not_ MATCH_ACCEPT */ + { + mstart = md->start_match_ptr; + break; + } + if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); + ecode += GET(ecode,1); + } + while (*ecode == OP_ALT); + + /* If hit the end of the group (which could be repeated), fail */ + + if (*ecode != OP_ONCE && *ecode != OP_ALT) RRETURN(MATCH_NOMATCH); + + /* Continue as from after the assertion, 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 there is an options reset, it will get obeyed in the normal + course of events. */ + + 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. We need to reset + any options that changed within the bracket before re-running it, so + check the next opcode. */ + + if (ecode[1+LINK_SIZE] == OP_OPT) + { + ims = (ims & ~PCRE_IMS) | ecode[4]; + DPRINTF(("ims set to %02lx at group repeat\n", ims)); + } + + if (*ecode == OP_KETRMIN) + { + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0, RM8); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode = prev; + flags = 0; + goto TAIL_RECURSE; + } + else /* OP_KETRMAX */ + { + RMATCH(eptr, prev, offset_top, md, ims, eptrb, match_cbegroup, RM9); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode += 1 + LINK_SIZE; + flags = 0; + goto TAIL_RECURSE; + } + /* Control never gets here */ + + /* 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, ims, eptrb, 0, 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, ims, eptrb, 0, 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; + + /* End of a group, repeated or non-repeating. */ + + case OP_KET: + case OP_KETRMIN: + case OP_KETRMAX: + 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) + { + 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 an 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_ASSERT_NOT || + *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT || + *prev == OP_ONCE) + { + md->end_match_ptr = eptr; /* For ONCE */ + md->end_offset_top = offset_top; + md->start_match_ptr = mstart; + MRRETURN(MATCH_MATCH); + } + + /* 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. Note that 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. */ + + if (*prev == OP_CBRA || *prev == OP_SCBRA) + { + number = GET2(prev, 1+LINK_SIZE); + offset = number << 1; + +#ifdef PCRE_DEBUG + printf("end bracket %d", 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; + } + + /* Handle a recursively called group. Restore the offsets + appropriately and continue from after the call. */ + + if (md->recursive != NULL && md->recursive->group_num == number) + { + recursion_info *rec = md->recursive; + DPRINTF(("Recursion (%d) succeeded - continuing\n", number)); + md->recursive = rec->prevrec; + memcpy(md->offset_vector, rec->offset_save, + rec->saved_max * sizeof(int)); + offset_top = rec->save_offset_top; + ecode = rec->after_call; + ims = original_ims; + break; + } + } + + /* For both capturing and non-capturing groups, reset the value of the ims + flags, in case they got changed during the group. */ + + ims = original_ims; + DPRINTF(("ims reset to %02lx\n", ims)); + + /* 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 there is an options reset, it will get obeyed in the normal + course of events. */ + + 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. In the second case, we can use + tail recursion to avoid using another stack frame, unless we have an + unlimited repeat of a group that can match an empty string. */ + + flags = (*prev >= OP_SBRA)? match_cbegroup : 0; + + if (*ecode == OP_KETRMIN) + { + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0, RM12); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (flags != 0) /* Could match an empty string */ + { + RMATCH(eptr, prev, offset_top, md, ims, eptrb, flags, RM50); + RRETURN(rrc); + } + ecode = prev; + goto TAIL_RECURSE; + } + else /* OP_KETRMAX */ + { + RMATCH(eptr, prev, offset_top, md, ims, eptrb, flags, RM13); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode += 1 + LINK_SIZE; + flags = 0; + goto TAIL_RECURSE; + } + /* Control never gets here */ + + /* Start of subject unless notbol, or after internal newline if multiline */ + + case OP_CIRC: + if (md->notbol && eptr == md->start_subject) MRRETURN(MATCH_NOMATCH); + if ((ims & PCRE_MULTILINE) != 0) + { + if (eptr != md->start_subject && + (eptr == md->end_subject || !WAS_NEWLINE(eptr))) + MRRETURN(MATCH_NOMATCH); + ecode++; + break; + } + /* ... else fall through */ + + /* Start of subject assertion */ + + case OP_SOD: + if (eptr != md->start_subject) MRRETURN(MATCH_NOMATCH); + ecode++; + break; + + /* Start of match assertion */ + + case OP_SOM: + if (eptr != md->start_subject + md->start_offset) MRRETURN(MATCH_NOMATCH); + ecode++; + break; + + /* Reset the start of match point */ + + case OP_SET_SOM: + mstart = eptr; + ecode++; + break; + + /* Assert before internal newline if multiline, or before a terminating + newline unless endonly is set, else end of subject unless noteol is set. */ + + case OP_DOLL: + if ((ims & PCRE_MULTILINE) != 0) + { + if (eptr < md->end_subject) + { if (!IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH); } + else + { if (md->noteol) MRRETURN(MATCH_NOMATCH); } + ecode++; + break; + } + else + { + if (md->noteol) MRRETURN(MATCH_NOMATCH); + if (!md->endonly) + { + if (eptr != md->end_subject && + (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen)) + MRRETURN(MATCH_NOMATCH); + ecode++; + break; + } + } + /* ... else fall through for endonly */ + + /* End of subject assertion (\z) */ + + case OP_EOD: + if (eptr < md->end_subject) MRRETURN(MATCH_NOMATCH); + ecode++; + break; + + /* End of subject or ending \n assertion (\Z) */ + + case OP_EODN: + if (eptr != md->end_subject && + (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen)) + MRRETURN(MATCH_NOMATCH); + 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_UTF8 + if (utf8) + { + /* Get status of previous character */ + + if (eptr == md->start_subject) prev_is_word = FALSE; else + { + USPTR lastptr = eptr - 1; + while((*lastptr & 0xc0) == 0x80) 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 = ((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 = ((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) + MRRETURN(MATCH_NOMATCH); + } + break; + + /* Match a single character type; inline for speed */ + + case OP_ANY: + if (IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH); + /* Fall through */ + + case OP_ALLANY: + if (eptr++ >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if (utf8) while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + 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) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + ecode++; + break; + + case OP_NOT_DIGIT: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c < 256 && +#endif + (md->ctypes[c] & ctype_digit) != 0 + ) + MRRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_DIGIT: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c >= 256 || +#endif + (md->ctypes[c] & ctype_digit) == 0 + ) + MRRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_NOT_WHITESPACE: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c < 256 && +#endif + (md->ctypes[c] & ctype_space) != 0 + ) + MRRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_WHITESPACE: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c >= 256 || +#endif + (md->ctypes[c] & ctype_space) == 0 + ) + MRRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_NOT_WORDCHAR: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c < 256 && +#endif + (md->ctypes[c] & ctype_word) != 0 + ) + MRRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_WORDCHAR: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ( +#ifdef SUPPORT_UTF8 + c >= 256 || +#endif + (md->ctypes[c] & ctype_word) == 0 + ) + MRRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_ANYNL: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + switch(c) + { + default: MRRETURN(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) MRRETURN(MATCH_NOMATCH); + break; + } + ecode++; + break; + + case OP_NOT_HSPACE: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(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 */ + MRRETURN(MATCH_NOMATCH); + } + ecode++; + break; + + case OP_HSPACE: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + switch(c) + { + default: MRRETURN(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(); + MRRETURN(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 */ + MRRETURN(MATCH_NOMATCH); + } + ecode++; + break; + + case OP_VSPACE: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + switch(c) + { + default: MRRETURN(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(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + { + const ucd_record *prop = GET_UCD(c); + + switch(ecode[1]) + { + case PT_ANY: + if (op == OP_NOTPROP) MRRETURN(MATCH_NOMATCH); + break; + + case PT_LAMP: + if ((prop->chartype == ucp_Lu || + prop->chartype == ucp_Ll || + prop->chartype == ucp_Lt) == (op == OP_NOTPROP)) + MRRETURN(MATCH_NOMATCH); + break; + + case PT_GC: + if ((ecode[2] != _pcre_ucp_gentype[prop->chartype]) == (op == OP_PROP)) + MRRETURN(MATCH_NOMATCH); + break; + + case PT_PC: + if ((ecode[2] != prop->chartype) == (op == OP_PROP)) + MRRETURN(MATCH_NOMATCH); + break; + + case PT_SC: + if ((ecode[2] != prop->script) == (op == OP_PROP)) + MRRETURN(MATCH_NOMATCH); + break; + + /* These are specials */ + + case PT_ALNUM: + if ((_pcre_ucp_gentype[prop->chartype] == ucp_L || + _pcre_ucp_gentype[prop->chartype] == ucp_N) == (op == OP_NOTPROP)) + MRRETURN(MATCH_NOMATCH); + break; + + case PT_SPACE: /* Perl space */ + if ((_pcre_ucp_gentype[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR) + == (op == OP_NOTPROP)) + MRRETURN(MATCH_NOMATCH); + break; + + case PT_PXSPACE: /* POSIX space */ + if ((_pcre_ucp_gentype[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || + c == CHAR_FF || c == CHAR_CR) + == (op == OP_NOTPROP)) + MRRETURN(MATCH_NOMATCH); + break; + + case PT_WORD: + if ((_pcre_ucp_gentype[prop->chartype] == ucp_L || + _pcre_ucp_gentype[prop->chartype] == ucp_N || + c == CHAR_UNDERSCORE) == (op == OP_NOTPROP)) + MRRETURN(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(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + { + int category = UCD_CATEGORY(c); + if (category == ucp_M) MRRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject) + { + int len = 1; + if (!utf8) c = *eptr; else + { + GETCHARLEN(c, eptr, len); + } + category = UCD_CATEGORY(c); + if (category != 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: + { + offset = GET2(ecode, 1) << 1; /* Doubled ref number */ + ecode += 3; + + /* If the reference is unset, there are two possibilities: + + (a) In the default, Perl-compatible state, set the length to be longer + than the amount of subject left; 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 : (int)(md->end_subject - eptr + 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, 3); + if (max == 0) max = INT_MAX; + ecode += 5; + break; + + default: /* No repeat follows */ + if (!match_ref(offset, eptr, length, md, ims)) + { + CHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + eptr += length; + continue; /* With the main loop */ + } + + /* If the length of the reference is zero, just continue with the + main loop. */ + + if (length == 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++) + { + if (!match_ref(offset, eptr, length, md, ims)) + { + CHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + eptr += length; + } + + /* 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++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM14); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (!match_ref(offset, eptr, length, md, ims)) + { + CHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + eptr += length; + } + /* Control never gets here */ + } + + /* If maximizing, find the longest string and work backwards */ + + else + { + pp = eptr; + for (i = min; i < max; i++) + { + if (!match_ref(offset, eptr, length, md, ims)) + { + CHECK_PARTIAL(); + break; + } + eptr += length; + } + while (eptr >= pp) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM15); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr -= length; + } + MRRETURN(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: + { + data = ecode + 1; /* Save for matching */ + ecode += 33; /* 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, 3); + if (max == 0) max = INT_MAX; + ecode += 5; + break; + + default: /* No repeat follows */ + min = max = 1; + break; + } + + /* First, ensure the minimum number of matches are present. */ + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINC(c, eptr); + if (c > 255) + { + if (op == OP_CLASS) MRRETURN(MATCH_NOMATCH); + } + else + { + if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(MATCH_NOMATCH); + } + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + c = *eptr++; + if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(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_UTF8 + /* UTF-8 mode */ + if (utf8) + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM16); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINC(c, eptr); + if (c > 255) + { + if (op == OP_CLASS) MRRETURN(MATCH_NOMATCH); + } + else + { + if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(MATCH_NOMATCH); + } + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM17); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + c = *eptr++; + if ((data[c/8] & (1 << (c&7))) == 0) MRRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + } + + /* If maximizing, find the longest possible run, then work backwards. */ + + else + { + pp = eptr; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + 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 ((data[c/8] & (1 << (c&7))) == 0) break; + } + eptr += len; + } + for (;;) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM18); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + c = *eptr; + if ((data[c/8] & (1 << (c&7))) == 0) break; + eptr++; + } + while (eptr >= pp) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM19); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr--; + } + } + + MRRETURN(MATCH_NOMATCH); + } + } + /* 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. */ + +#ifdef SUPPORT_UTF8 + 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, 3); + if (max == 0) max = INT_MAX; + ecode += 5; + 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(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if (!_pcre_xclass(c, data)) MRRETURN(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, ims, eptrb, 0, RM20); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if (!_pcre_xclass(c, data)) MRRETURN(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; + } + GETCHARLENTEST(c, eptr, len); + if (!_pcre_xclass(c, data)) break; + eptr += len; + } + for(;;) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM21); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + if (utf8) BACKCHAR(eptr); + } + MRRETURN(MATCH_NOMATCH); + } + + /* Control never gets here */ + } +#endif /* End of XCLASS */ + + /* Match a single character, casefully */ + + case OP_CHAR: +#ifdef SUPPORT_UTF8 + if (utf8) + { + length = 1; + ecode++; + GETCHARLEN(fc, ecode, length); + if (length > md->end_subject - eptr) + { + CHECK_PARTIAL(); /* Not SCHECK_PARTIAL() */ + MRRETURN(MATCH_NOMATCH); + } + while (length-- > 0) if (*ecode++ != *eptr++) MRRETURN(MATCH_NOMATCH); + } + else +#endif + + /* Non-UTF-8 mode */ + { + if (md->end_subject - eptr < 1) + { + SCHECK_PARTIAL(); /* This one can use SCHECK_PARTIAL() */ + MRRETURN(MATCH_NOMATCH); + } + if (ecode[1] != *eptr++) MRRETURN(MATCH_NOMATCH); + ecode += 2; + } + break; + + /* Match a single character, caselessly */ + + case OP_CHARNC: +#ifdef SUPPORT_UTF8 + if (utf8) + { + length = 1; + ecode++; + GETCHARLEN(fc, ecode, length); + + if (length > md->end_subject - eptr) + { + CHECK_PARTIAL(); /* Not SCHECK_PARTIAL() */ + MRRETURN(MATCH_NOMATCH); + } + + /* If the pattern character's value is < 128, we have only one byte, and + can use the fast lookup table. */ + + if (fc < 128) + { + if (md->lcc[*ecode++] != md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH); + } + + /* Otherwise we must pick up the subject character */ + + 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 + MRRETURN(MATCH_NOMATCH); + } + } + } + else +#endif /* SUPPORT_UTF8 */ + + /* Non-UTF-8 mode */ + { + if (md->end_subject - eptr < 1) + { + SCHECK_PARTIAL(); /* This one can use SCHECK_PARTIAL() */ + MRRETURN(MATCH_NOMATCH); + } + if (md->lcc[ecode[1]] != md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH); + ecode += 2; + } + break; + + /* Match a single character repeatedly. */ + + case OP_EXACT: + min = max = GET2(ecode, 1); + ecode += 3; + goto REPEATCHAR; + + case OP_POSUPTO: + possessive = TRUE; + /* Fall through */ + + case OP_UPTO: + case OP_MINUPTO: + min = 0; + max = GET2(ecode, 1); + minimize = *ecode == OP_MINUPTO; + ecode += 3; + goto REPEATCHAR; + + case OP_POSSTAR: + possessive = TRUE; + min = 0; + max = INT_MAX; + ecode++; + goto REPEATCHAR; + + case OP_POSPLUS: + possessive = TRUE; + min = 1; + max = INT_MAX; + ecode++; + goto REPEATCHAR; + + case OP_POSQUERY: + possessive = TRUE; + min = 0; + max = 1; + ecode++; + goto REPEATCHAR; + + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + c = *ecode++ - OP_STAR; + 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_UTF8 + if (utf8) + { + 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 ((ims & PCRE_CASELESS) != 0 && + (othercase = UCD_OTHERCASE(fc)) != fc) + oclength = _pcre_ord2utf8(othercase, occhars); + else oclength = 0; +#endif /* SUPPORT_UCP */ + + for (i = 1; i <= min; i++) + { + if (eptr <= md->end_subject - length && + memcmp(eptr, charptr, length) == 0) eptr += length; +#ifdef SUPPORT_UCP + else if (oclength > 0 && + eptr <= md->end_subject - oclength && + memcmp(eptr, occhars, oclength) == 0) eptr += oclength; +#endif /* SUPPORT_UCP */ + else + { + CHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + } + + if (min == max) continue; + + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM22); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr <= md->end_subject - length && + memcmp(eptr, charptr, length) == 0) eptr += length; +#ifdef SUPPORT_UCP + else if (oclength > 0 && + eptr <= md->end_subject - oclength && + memcmp(eptr, occhars, oclength) == 0) eptr += oclength; +#endif /* SUPPORT_UCP */ + else + { + CHECK_PARTIAL(); + MRRETURN(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, length) == 0) eptr += length; +#ifdef SUPPORT_UCP + else if (oclength > 0 && + eptr <= md->end_subject - oclength && + memcmp(eptr, occhars, oclength) == 0) eptr += oclength; +#endif /* SUPPORT_UCP */ + else + { + CHECK_PARTIAL(); + break; + } + } + + if (possessive) continue; + + for(;;) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM23); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr == pp) { MRRETURN(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_UTF8 */ + + /* When not in UTF-8 mode, load a single-byte character. */ + + fc = *ecode++; + + /* The value of fc at this point is always less than 256, though we may or + may not be in UTF-8 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 ((ims & PCRE_CASELESS) != 0) + { + fc = md->lcc[fc]; + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if (fc != md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH); + } + if (min == max) continue; + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM24); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if (fc != md->lcc[*eptr++]) MRRETURN(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 != md->lcc[*eptr]) break; + eptr++; + } + + if (possessive) continue; + + while (eptr >= pp) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM25); + eptr--; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + MRRETURN(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(); + MRRETURN(MATCH_NOMATCH); + } + if (fc != *eptr++) MRRETURN(MATCH_NOMATCH); + } + + if (min == max) continue; + + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM26); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if (fc != *eptr++) MRRETURN(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, ims, eptrb, 0, RM27); + eptr--; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + MRRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + + /* Match a negated single one-byte character. The character we are + checking can be multibyte. */ + + case OP_NOT: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + ecode++; + GETCHARINCTEST(c, eptr); + if ((ims & PCRE_CASELESS) != 0) + { +#ifdef SUPPORT_UTF8 + if (c < 256) +#endif + c = md->lcc[c]; + if (md->lcc[*ecode++] == c) MRRETURN(MATCH_NOMATCH); + } + else + { + if (*ecode++ == c) MRRETURN(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: + min = max = GET2(ecode, 1); + ecode += 3; + goto REPEATNOTCHAR; + + case OP_NOTUPTO: + case OP_NOTMINUPTO: + min = 0; + max = GET2(ecode, 1); + minimize = *ecode == OP_NOTMINUPTO; + ecode += 3; + goto REPEATNOTCHAR; + + case OP_NOTPOSSTAR: + possessive = TRUE; + min = 0; + max = INT_MAX; + ecode++; + goto REPEATNOTCHAR; + + case OP_NOTPOSPLUS: + possessive = TRUE; + min = 1; + max = INT_MAX; + ecode++; + goto REPEATNOTCHAR; + + case OP_NOTPOSQUERY: + possessive = TRUE; + min = 0; + max = 1; + ecode++; + goto REPEATNOTCHAR; + + case OP_NOTPOSUPTO: + possessive = TRUE; + min = 0; + max = GET2(ecode, 1); + ecode += 3; + goto REPEATNOTCHAR; + + case OP_NOTSTAR: + case OP_NOTMINSTAR: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTQUERY: + case OP_NOTMINQUERY: + c = *ecode++ - 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 ((ims & PCRE_CASELESS) != 0) + { + fc = md->lcc[fc]; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + register unsigned int d; + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINC(d, eptr); + if (d < 256) d = md->lcc[d]; + if (fc == d) MRRETURN(MATCH_NOMATCH); + } + } + else +#endif + + /* Not UTF-8 mode */ + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if (fc == md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH); + } + } + + if (min == max) continue; + + if (minimize) + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + register unsigned int d; + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM28); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINC(d, eptr); + if (d < 256) d = md->lcc[d]; + if (fc == d) MRRETURN(MATCH_NOMATCH); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM29); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if (fc == md->lcc[*eptr++]) MRRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + } + + /* Maximize case */ + + else + { + pp = eptr; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + 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 (d < 256) d = md->lcc[d]; + if (fc == d) break; + eptr += len; + } + if (possessive) continue; + for(;;) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM30); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (fc == md->lcc[*eptr]) break; + eptr++; + } + if (possessive) continue; + while (eptr >= pp) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM31); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr--; + } + } + + MRRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + + /* Caseful comparisons */ + + else + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + register unsigned int d; + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINC(d, eptr); + if (fc == d) MRRETURN(MATCH_NOMATCH); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if (fc == *eptr++) MRRETURN(MATCH_NOMATCH); + } + } + + if (min == max) continue; + + if (minimize) + { +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + register unsigned int d; + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM32); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINC(d, eptr); + if (fc == d) MRRETURN(MATCH_NOMATCH); + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM33); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if (fc == *eptr++) MRRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + } + + /* Maximize case */ + + else + { + pp = eptr; + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + 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, ims, eptrb, 0, RM34); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + /* Not UTF-8 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, ims, eptrb, 0, RM35); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr--; + } + } + + MRRETURN(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 += 3; + goto REPEATTYPE; + + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + min = 0; + max = GET2(ecode, 1); + minimize = *ecode == OP_TYPEMINUPTO; + ecode += 3; + 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 += 3; + 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) MRRETURN(MATCH_NOMATCH); + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + } + break; + + case PT_LAMP: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_chartype = UCD_CHARTYPE(c); + if ((prop_chartype == ucp_Lu || + prop_chartype == ucp_Ll || + prop_chartype == ucp_Lt) == prop_fail_result) + MRRETURN(MATCH_NOMATCH); + } + break; + + case PT_GC: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_category = UCD_CATEGORY(c); + if ((prop_category == prop_value) == prop_fail_result) + MRRETURN(MATCH_NOMATCH); + } + break; + + case PT_PC: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_chartype = UCD_CHARTYPE(c); + if ((prop_chartype == prop_value) == prop_fail_result) + MRRETURN(MATCH_NOMATCH); + } + break; + + case PT_SC: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_script = UCD_SCRIPT(c); + if ((prop_script == prop_value) == prop_fail_result) + MRRETURN(MATCH_NOMATCH); + } + break; + + case PT_ALNUM: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_category = UCD_CATEGORY(c); + if ((prop_category == ucp_L || prop_category == ucp_N) + == prop_fail_result) + MRRETURN(MATCH_NOMATCH); + } + break; + + case PT_SPACE: /* Perl space */ + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_category = UCD_CATEGORY(c); + if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL || + c == CHAR_FF || c == CHAR_CR) + == prop_fail_result) + MRRETURN(MATCH_NOMATCH); + } + break; + + case PT_PXSPACE: /* POSIX space */ + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_category = UCD_CATEGORY(c); + if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL || + c == CHAR_VT || c == CHAR_FF || c == CHAR_CR) + == prop_fail_result) + MRRETURN(MATCH_NOMATCH); + } + break; + + case PT_WORD: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_category = UCD_CATEGORY(c); + if ((prop_category == ucp_L || prop_category == ucp_N || + c == CHAR_UNDERSCORE) + == prop_fail_result) + MRRETURN(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(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_category = UCD_CATEGORY(c); + if (prop_category == ucp_M) MRRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject) + { + int len = 1; + if (!utf8) c = *eptr; + else { GETCHARLEN(c, eptr, len); } + prop_category = UCD_CATEGORY(c); + if (prop_category != ucp_M) break; + eptr += len; + } + } + } + + else +#endif /* SUPPORT_UCP */ + +/* Handle all other cases when the coding is UTF-8 */ + +#ifdef SUPPORT_UTF8 + if (utf8) switch(ctype) + { + case OP_ANY: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if (IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH); + eptr++; + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + break; + + case OP_ALLANY: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + eptr++; + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + break; + + case OP_ANYBYTE: + if (eptr > md->end_subject - min) MRRETURN(MATCH_NOMATCH); + eptr += min; + break; + + case OP_ANYNL: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINC(c, eptr); + switch(c) + { + default: MRRETURN(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) MRRETURN(MATCH_NOMATCH); + break; + } + } + break; + + case OP_NOT_HSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(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 */ + MRRETURN(MATCH_NOMATCH); + } + } + break; + + case OP_HSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINC(c, eptr); + switch(c) + { + default: MRRETURN(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(); + MRRETURN(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 */ + MRRETURN(MATCH_NOMATCH); + } + } + break; + + case OP_VSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINC(c, eptr); + switch(c) + { + default: MRRETURN(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(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINC(c, eptr); + if (c < 128 && (md->ctypes[c] & ctype_digit) != 0) + MRRETURN(MATCH_NOMATCH); + } + break; + + case OP_DIGIT: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if (*eptr >= 128 || (md->ctypes[*eptr++] & ctype_digit) == 0) + MRRETURN(MATCH_NOMATCH); + /* 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(); + MRRETURN(MATCH_NOMATCH); + } + if (*eptr < 128 && (md->ctypes[*eptr] & ctype_space) != 0) + MRRETURN(MATCH_NOMATCH); + while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80); + } + break; + + case OP_WHITESPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if (*eptr >= 128 || (md->ctypes[*eptr++] & ctype_space) == 0) + MRRETURN(MATCH_NOMATCH); + /* 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(); + MRRETURN(MATCH_NOMATCH); + } + if (*eptr < 128 && (md->ctypes[*eptr] & ctype_word) != 0) + MRRETURN(MATCH_NOMATCH); + while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80); + } + break; + + case OP_WORDCHAR: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if (*eptr >= 128 || (md->ctypes[*eptr++] & ctype_word) == 0) + MRRETURN(MATCH_NOMATCH); + /* 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_UTF8 */ + + /* 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(); + MRRETURN(MATCH_NOMATCH); + } + if (IS_NEWLINE(eptr)) MRRETURN(MATCH_NOMATCH); + eptr++; + } + break; + + case OP_ALLANY: + if (eptr > md->end_subject - min) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + eptr += min; + break; + + case OP_ANYBYTE: + if (eptr > md->end_subject - min) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + eptr += min; + break; + + case OP_ANYNL: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + switch(*eptr++) + { + default: MRRETURN(MATCH_NOMATCH); + case 0x000d: + if (eptr < md->end_subject && *eptr == 0x0a) eptr++; + break; + case 0x000a: + break; + + case 0x000b: + case 0x000c: + case 0x0085: + if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH); + break; + } + } + break; + + case OP_NOT_HSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + switch(*eptr++) + { + default: break; + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + MRRETURN(MATCH_NOMATCH); + } + } + break; + + case OP_HSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + switch(*eptr++) + { + default: MRRETURN(MATCH_NOMATCH); + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + break; + } + } + break; + + case OP_NOT_VSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + switch(*eptr++) + { + default: break; + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + MRRETURN(MATCH_NOMATCH); + } + } + break; + + case OP_VSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + switch(*eptr++) + { + default: MRRETURN(MATCH_NOMATCH); + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + break; + } + } + break; + + case OP_NOT_DIGIT: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if ((md->ctypes[*eptr++] & ctype_digit) != 0) MRRETURN(MATCH_NOMATCH); + } + break; + + case OP_DIGIT: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if ((md->ctypes[*eptr++] & ctype_digit) == 0) MRRETURN(MATCH_NOMATCH); + } + break; + + case OP_NOT_WHITESPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if ((md->ctypes[*eptr++] & ctype_space) != 0) MRRETURN(MATCH_NOMATCH); + } + break; + + case OP_WHITESPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if ((md->ctypes[*eptr++] & ctype_space) == 0) MRRETURN(MATCH_NOMATCH); + } + break; + + case OP_NOT_WORDCHAR: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if ((md->ctypes[*eptr++] & ctype_word) != 0) + MRRETURN(MATCH_NOMATCH); + } + break; + + case OP_WORDCHAR: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if ((md->ctypes[*eptr++] & ctype_word) == 0) + MRRETURN(MATCH_NOMATCH); + } + 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, ims, eptrb, 0, RM36); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if (prop_fail_result) MRRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_LAMP: + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM37); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_chartype = UCD_CHARTYPE(c); + if ((prop_chartype == ucp_Lu || + prop_chartype == ucp_Ll || + prop_chartype == ucp_Lt) == prop_fail_result) + MRRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_GC: + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM38); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_category = UCD_CATEGORY(c); + if ((prop_category == prop_value) == prop_fail_result) + MRRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_PC: + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM39); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_chartype = UCD_CHARTYPE(c); + if ((prop_chartype == prop_value) == prop_fail_result) + MRRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_SC: + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM40); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_script = UCD_SCRIPT(c); + if ((prop_script == prop_value) == prop_fail_result) + MRRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_ALNUM: + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM59); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_category = UCD_CATEGORY(c); + if ((prop_category == ucp_L || prop_category == ucp_N) + == prop_fail_result) + MRRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_SPACE: /* Perl space */ + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM60); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_category = UCD_CATEGORY(c); + if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL || + c == CHAR_FF || c == CHAR_CR) + == prop_fail_result) + MRRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_PXSPACE: /* POSIX space */ + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM61); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_category = UCD_CATEGORY(c); + if ((prop_category == ucp_Z || c == CHAR_HT || c == CHAR_NL || + c == CHAR_VT || c == CHAR_FF || c == CHAR_CR) + == prop_fail_result) + MRRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_WORD: + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM62); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_category = UCD_CATEGORY(c); + if ((prop_category == ucp_L || + prop_category == ucp_N || + c == CHAR_UNDERSCORE) + == prop_fail_result) + MRRETURN(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, ims, eptrb, 0, RM41); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + prop_category = UCD_CATEGORY(c); + if (prop_category == ucp_M) MRRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject) + { + int len = 1; + if (!utf8) c = *eptr; + else { GETCHARLEN(c, eptr, len); } + prop_category = UCD_CATEGORY(c); + if (prop_category != ucp_M) break; + eptr += len; + } + } + } + + else +#endif /* SUPPORT_UCP */ + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + if (utf8) + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM42); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if (ctype == OP_ANY && IS_NEWLINE(eptr)) + MRRETURN(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: MRRETURN(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) MRRETURN(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 */ + MRRETURN(MATCH_NOMATCH); + } + break; + + case OP_HSPACE: + switch(c) + { + default: MRRETURN(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 */ + MRRETURN(MATCH_NOMATCH); + } + break; + + case OP_VSPACE: + switch(c) + { + default: MRRETURN(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) + MRRETURN(MATCH_NOMATCH); + break; + + case OP_DIGIT: + if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0) + MRRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WHITESPACE: + if (c < 256 && (md->ctypes[c] & ctype_space) != 0) + MRRETURN(MATCH_NOMATCH); + break; + + case OP_WHITESPACE: + if (c >= 256 || (md->ctypes[c] & ctype_space) == 0) + MRRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WORDCHAR: + if (c < 256 && (md->ctypes[c] & ctype_word) != 0) + MRRETURN(MATCH_NOMATCH); + break; + + case OP_WORDCHAR: + if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) + MRRETURN(MATCH_NOMATCH); + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + } + } + else +#endif + /* Not UTF-8 mode */ + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM43); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) MRRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + MRRETURN(MATCH_NOMATCH); + } + if (ctype == OP_ANY && IS_NEWLINE(eptr)) + MRRETURN(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: MRRETURN(MATCH_NOMATCH); + case 0x000d: + if (eptr < md->end_subject && *eptr == 0x0a) eptr++; + break; + + case 0x000a: + break; + + case 0x000b: + case 0x000c: + case 0x0085: + if (md->bsr_anycrlf) MRRETURN(MATCH_NOMATCH); + break; + } + break; + + case OP_NOT_HSPACE: + switch(c) + { + default: break; + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + MRRETURN(MATCH_NOMATCH); + } + break; + + case OP_HSPACE: + switch(c) + { + default: MRRETURN(MATCH_NOMATCH); + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + 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 */ + MRRETURN(MATCH_NOMATCH); + } + break; + + case OP_VSPACE: + switch(c) + { + default: MRRETURN(MATCH_NOMATCH); + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + break; + } + break; + + case OP_NOT_DIGIT: + if ((md->ctypes[c] & ctype_digit) != 0) MRRETURN(MATCH_NOMATCH); + break; + + case OP_DIGIT: + if ((md->ctypes[c] & ctype_digit) == 0) MRRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WHITESPACE: + if ((md->ctypes[c] & ctype_space) != 0) MRRETURN(MATCH_NOMATCH); + break; + + case OP_WHITESPACE: + if ((md->ctypes[c] & ctype_space) == 0) MRRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WORDCHAR: + if ((md->ctypes[c] & ctype_word) != 0) MRRETURN(MATCH_NOMATCH); + break; + + case OP_WORDCHAR: + if ((md->ctypes[c] & ctype_word) == 0) MRRETURN(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 len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLENTEST(c, eptr, len); + prop_chartype = UCD_CHARTYPE(c); + if ((prop_chartype == ucp_Lu || + prop_chartype == ucp_Ll || + prop_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); + prop_category = UCD_CATEGORY(c); + if ((prop_category == 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); + prop_chartype = UCD_CHARTYPE(c); + if ((prop_chartype == 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); + prop_script = UCD_SCRIPT(c); + if ((prop_script == prop_value) == prop_fail_result) + break; + eptr+= len; + } + break; + + case PT_ALNUM: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLENTEST(c, eptr, len); + prop_category = UCD_CATEGORY(c); + if ((prop_category == ucp_L || prop_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); + prop_category = UCD_CATEGORY(c); + if ((prop_category == 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); + prop_category = UCD_CATEGORY(c); + if ((prop_category == 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 len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLENTEST(c, eptr, len); + prop_category = UCD_CATEGORY(c); + if ((prop_category == ucp_L || prop_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, ims, eptrb, 0, RM44); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + if (utf8) 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++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARINCTEST(c, eptr); + prop_category = UCD_CATEGORY(c); + if (prop_category == ucp_M) break; + while (eptr < md->end_subject) + { + int len = 1; + if (!utf8) c = *eptr; else + { + GETCHARLEN(c, eptr, len); + } + prop_category = UCD_CATEGORY(c); + if (prop_category != 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, ims, eptrb, 0, RM45); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + for (;;) /* Move back over one extended */ + { + int len = 1; + if (!utf8) c = *eptr; else + { + BACKCHAR(eptr); + GETCHARLEN(c, eptr, len); + } + prop_category = UCD_CATEGORY(c); + if (prop_category != ucp_M) break; + eptr--; + } + } + } + + else +#endif /* SUPPORT_UCP */ + +#ifdef SUPPORT_UTF8 + /* UTF-8 mode */ + + if (utf8) + { + 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++; + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) 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++; + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + } + break; + + case OP_ALLANY: + if (max < INT_MAX) + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + eptr++; + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++; + } + } + else eptr = md->end_subject; /* Unlimited UTF-8 repeat */ + 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) continue; + for(;;) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM46); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif /* SUPPORT_UTF8 */ + + /* Not UTF-8 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))) + 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) 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) 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) + 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) + break; + eptr++; + } + break; + + case OP_NOT_DIGIT: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if ((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 ((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 ((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 ((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 ((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 ((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) continue; + while (eptr >= pp) + { + RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM47); + eptr--; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + } + + /* Get here if we can't make it match with any permitted repetitions */ + + MRRETURN(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) +#ifdef SUPPORT_UTF8 + LBL(16) LBL(18) LBL(20) LBL(21) 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_UTF8 */ + default: + DPRINTF(("jump error in pcre match: label %d non-existent\n", frame->Xwhere)); + return PCRE_ERROR_INTERNAL; + } +#undef LBL +#endif /* NO_RECURSE */ +} + + +/*************************************************************************** +**************************************************************************** + RECURSION IN THE match() FUNCTION + +Undefine all the macros that were defined above to handle this. */ + +#ifdef NO_RECURSE +#undef eptr +#undef ecode +#undef mstart +#undef offset_top +#undef ims +#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 original_ims + +#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 +*/ + +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) +{ +int rc, resetcount, ocount; +int first_byte = -1; +int req_byte = -1; +int req_byte2 = -1; +int newline; +unsigned long int ims; +BOOL using_temporary_offsets = FALSE; +BOOL anchored; +BOOL startline; +BOOL firstline; +BOOL first_byte_caseless = FALSE; +BOOL req_byte_caseless = FALSE; +BOOL utf8; +match_data match_block; +match_data *md = &match_block; +const uschar *tables; +const uschar *start_bits = NULL; +USPTR start_match = (USPTR)subject + start_offset; +USPTR end_subject; +USPTR start_partial = NULL; +USPTR req_byte_ptr = start_match - 1; + +pcre_study_data internal_study; +const pcre_study_data *study; + +real_pcre internal_re; +const real_pcre *external_re = (const real_pcre *)argument_re; +const real_pcre *re = external_re; + +/* 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; + +/* This information is for finding all the numbers associated with a given +name, for condition testing. */ + +md->name_table = (uschar *)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 = external_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 = _pcre_default_tables; + +/* Check that the first field in the block is the magic number. If it is not, +test for a regex that was compiled on a host of opposite endianness. If this is +the case, flipped values are put in internal_re and internal_study if there was +study data too. */ + +if (re->magic_number != MAGIC_NUMBER) + { + re = _pcre_try_flipped(re, &internal_re, study, &internal_study); + if (re == NULL) return PCRE_ERROR_BADMAGIC; + if (study != NULL) study = &internal_study; + } + +/* 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 uschar *)external_re + re->name_table_offset + + re->name_count * re->name_entry_size; + +md->start_subject = (USPTR)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; +utf8 = md->utf8 = (re->options & PCRE_UTF8) != 0; +md->use_ucp = (re->options & PCRE_UCP) != 0; +md->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0; + +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->partial = ((options & PCRE_PARTIAL_HARD) != 0)? 2 : + ((options & PCRE_PARTIAL_SOFT) != 0)? 1 : 0; +md->hitend = FALSE; +md->mark = NULL; /* In case never set */ + +md->recursive = NULL; /* No recursion at top level */ + +md->lcc = tables + lcc_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; + +/* Check a UTF-8 string if required. Unfortunately there's no way of passing +back the character offset. */ + +#ifdef SUPPORT_UTF8 +if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0) + { + if (_pcre_valid_utf8((USPTR)subject, length) >= 0) + return PCRE_ERROR_BADUTF8; + if (start_offset > 0 && start_offset < length) + { + int tb = ((USPTR)subject)[start_offset]; + if (tb > 127) + { + tb &= 0xc0; + if (tb != 0 && tb != 0xc0) return PCRE_ERROR_BADUTF8_OFFSET; + } + } + } +#endif + +/* The ims options can vary during the matching as a result of the presence +of (?ims) items in the pattern. They are kept in a local variable so that +restoring at the exit of a group is easy. */ + +ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL); + +/* 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); + +if (re->top_backref > 0 && re->top_backref >= ocount/3) + { + ocount = re->top_backref * 3 + 3; + md->offset_vector = (int *)(pcre_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; + +/* Compute the minimum number of offsets that we need to reset each time. Doing +this makes a huge difference to execution time when there aren't many brackets +in the pattern. */ + +resetcount = 2 + re->top_bracket * 2; +if (resetcount > offsetcount) resetcount = ocount; + +/* 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. */ + +if (md->offset_vector != NULL) + { + register int *iptr = md->offset_vector + ocount; + register int *iend = iptr - resetcount/2 + 1; + while (--iptr >= iend) *iptr = -1; + } + +/* 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) + { + first_byte = re->first_byte & 255; + if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE) + first_byte = md->lcc[first_byte]; + } + 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) + { + req_byte = re->req_byte & 255; + req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0; + req_byte2 = (tables + fcc_offset)[req_byte]; /* case flipped */ + } + + +/* ==========================================================================*/ + +/* Loop for handling unanchored repeated matching attempts; for anchored regexs +the loop runs just once. */ + +for(;;) + { + USPTR save_end_subject = end_subject; + USPTR new_start_match; + + /* Reset the maximum number of extractions we might see. */ + + if (md->offset_vector != NULL) + { + register int *iptr = md->offset_vector; + register int *iend = iptr + resetcount; + while (iptr < iend) *iptr++ = -1; + } + + /* 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) + { + USPTR t = start_match; +#ifdef SUPPORT_UTF8 + if (utf8) + { + while (t < md->end_subject && !IS_NEWLINE(t)) + { + t++; + while (t < end_subject && (*t & 0xc0) == 0x80) 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. */ + + if ((options & PCRE_NO_START_OPTIMIZE) == 0) + { + /* Advance to a unique first byte if there is one. */ + + if (first_byte >= 0) + { + if (first_byte_caseless) + while (start_match < end_subject && md->lcc[*start_match] != first_byte) + start_match++; + else + while (start_match < end_subject && *start_match != first_byte) + 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_UTF8 + if (utf8) + { + while (start_match < end_subject && !WAS_NEWLINE(start_match)) + { + start_match++; + while(start_match < end_subject && (*start_match & 0xc0) == 0x80) + 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; + if ((start_bits[c/8] & (1 << (c&7))) == 0) + { + start_match++; +#ifdef SUPPORT_UTF8 + if (utf8) + while(start_match < end_subject && (*start_match & 0xc0) == 0x80) + 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 & 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_byte is set, we know that that character must appear in the + subject for the match to succeed. If the first character is set, req_byte + 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 (req_byte >= 0 && end_subject - start_match < REQ_BYTE_MAX) + { + register USPTR p = start_match + ((first_byte >= 0)? 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_byte_ptr) + { + if (req_byte_caseless) + { + while (p < end_subject) + { + register int pp = *p++; + if (pp == req_byte || pp == req_byte2) { p--; break; } + } + } + else + { + while (p < end_subject) + { + if (*p++ == req_byte) { 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_byte_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; + rc = match(start_match, md->start_code, start_match, NULL, 2, md, ims, NULL, + 0, 0); + if (md->hitend && start_partial == NULL) start_partial = md->start_used_ptr; + + switch(rc) + { + /* 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 */ + + /* If MATCH_SKIP_ARG reaches this level it means that a MARK that matched + the SKIP's arg was not found. We also treat this as NOMATCH. */ + + case MATCH_SKIP_ARG: + /* Fall through */ + + /* NOMATCH and PRUNE advance by one character. THEN at this level acts + exactly like PRUNE. */ + + case MATCH_NOMATCH: + case MATCH_PRUNE: + case MATCH_THEN: + new_start_match = start_match + 1; +#ifdef SUPPORT_UTF8 + if (utf8) + while(new_start_match < end_subject && (*new_start_match & 0xc0) == 0x80) + 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. */ + + if (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 (offsetcount >= 4) + { + memcpy(offsets + 2, md->offset_vector + 2, + (offsetcount - 2) * sizeof(int)); + DPRINTF(("Copied offsets from temporary memory\n")); + } + if (md->end_offset_top > offsetcount) md->offset_overflow = TRUE; + DPRINTF(("Freeing temporary memory\n")); + (pcre_free)(md->offset_vector); + } + + /* Set the return code to the number of captured strings, or 0 if there are + too many to fit into the vector. */ + + rc = md->offset_overflow? 0 : md->end_offset_top/2; + + /* 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); + } + + DPRINTF((">>>> returning %d\n", rc)); + goto RETURN_MARK; + } + +/* 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")); + (pcre_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 - (USPTR)subject); + offsets[1] = (int)(end_subject - (USPTR)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. */ + +RETURN_MARK: + +if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0) + *(extra_data->mark) = (unsigned char *)(md->mark); +return rc; +} + +/* End of pcre_exec.c */ diff --git a/Library/pcre-8.10/pcre_fullinfo.c b/Library/pcre-8.10/pcre_fullinfo.c new file mode 100644 index 00000000..6b8d789a --- /dev/null +++ b/Library/pcre-8.10/pcre_fullinfo.c @@ -0,0 +1,174 @@ +/************************************************* +* 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-2009 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_fullinfo(), which returns +information about a compiled pattern. */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/************************************************* +* Return info about compiled pattern * +*************************************************/ + +/* This is a newer "info" function which has an extensible interface so +that additional items can be added compatibly. + +Arguments: + argument_re points to compiled code + extra_data points extra data, or NULL + what what information is required + where where to put the information + +Returns: 0 if data returned, negative on error +*/ + +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_fullinfo(const pcre *argument_re, const pcre_extra *extra_data, int what, + void *where) +{ +real_pcre internal_re; +pcre_study_data internal_study; +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; + +if (re->magic_number != MAGIC_NUMBER) + { + re = _pcre_try_flipped(re, &internal_re, study, &internal_study); + if (re == NULL) return PCRE_ERROR_BADMAGIC; + if (study != NULL) study = &internal_study; + } + +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_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_byte : + ((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 uschar **)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)? + study->minlength : -1; + break; + + case PCRE_INFO_LASTLITERAL: + *((int *)where) = + ((re->flags & PCRE_REQCHSET) != 0)? re->req_byte : -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 uschar **)where) = (const uschar *)re + re->name_table_offset; + break; + + case PCRE_INFO_DEFAULT_TABLES: + *((const uschar **)where) = (const uschar *)(_pcre_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/Library/pcre-8.10/pcre_get.c b/Library/pcre-8.10/pcre_get.c new file mode 100644 index 00000000..61177864 --- /dev/null +++ b/Library/pcre-8.10/pcre_get.c @@ -0,0 +1,465 @@ +/************************************************* +* 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-2008 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains some convenience functions for extracting substrings +from the subject string after a regex match has succeeded. The original idea +for these functions came from Scott Wimer. */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/************************************************* +* Find number for named string * +*************************************************/ + +/* This function is used by the get_first_set() function below, as well +as being generally available. It assumes that names are unique. + +Arguments: + code the compiled regex + stringname the name whose number is required + +Returns: the number of the named parentheses, or a negative number + (PCRE_ERROR_NOSUBSTRING) if not found +*/ + +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_get_stringnumber(const pcre *code, const char *stringname) +{ +int rc; +int entrysize; +int top, bot; +uschar *nametable; + +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; + +bot = 0; +while (top > bot) + { + int mid = (top + bot) / 2; + uschar *entry = nametable + entrysize*mid; + int c = strcmp(stringname, (char *)(entry + 2)); + if (c == 0) return (entry[0] << 8) + entry[1]; + 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 +*/ + +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_get_stringtable_entries(const pcre *code, const char *stringname, + char **firstptr, char **lastptr) +{ +int rc; +int entrysize; +int top, bot; +uschar *nametable, *lastentry; + +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; + +lastentry = nametable + entrysize * (top - 1); +bot = 0; +while (top > bot) + { + int mid = (top + bot) / 2; + uschar *entry = nametable + entrysize*mid; + int c = strcmp(stringname, (char *)(entry + 2)); + if (c == 0) + { + uschar *first = entry; + uschar *last = entry; + while (first > nametable) + { + if (strcmp(stringname, (char *)(first - entrysize + 2)) != 0) break; + first -= entrysize; + } + while (last < lastentry) + { + if (strcmp(stringname, (char *)(last + entrysize + 2)) != 0) break; + last += entrysize; + } + *firstptr = (char *)first; + *lastptr = (char *)last; + 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 +*/ + +static int +get_first_set(const pcre *code, const char *stringname, int *ovector) +{ +const real_pcre *re = (const real_pcre *)code; +int entrysize; +char *first, *last; +uschar *entry; +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); +if (entrysize <= 0) return entrysize; +for (entry = (uschar *)first; entry <= (uschar *)last; entry += entrysize) + { + int n = (entry[0] << 8) + entry[1]; + if (ovector[n*2] >= 0) return n; + } +return (first[0] << 8) + first[1]; +} + + + + +/************************************************* +* 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 +*/ + +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_copy_substring(const char *subject, int *ovector, int stringcount, + int stringnumber, char *buffer, int size) +{ +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], 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 +*/ + +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) +{ +int n = get_first_set(code, stringname, ovector); +if (n <= 0) return n; +return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size); +} + + + +/************************************************* +* 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 +*/ + +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_get_substring_list(const char *subject, int *ovector, int stringcount, + const char ***listptr) +{ +int i; +int size = sizeof(char *); +int double_count = stringcount * 2; +char **stringlist; +char *p; + +for (i = 0; i < double_count; i += 2) + size += sizeof(char *) + ovector[i+1] - ovector[i] + 1; + +stringlist = (char **)(pcre_malloc)(size); +if (stringlist == NULL) return PCRE_ERROR_NOMEMORY; + +*listptr = (const char **)stringlist; +p = (char *)(stringlist + stringcount + 1); + +for (i = 0; i < double_count; i += 2) + { + int len = ovector[i+1] - ovector[i]; + memcpy(p, subject + ovector[i], 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 (pcre_free)() directly. + +Argument: the result of a previous pcre_get_substring_list() +Returns: nothing +*/ + +PCRE_EXP_DEFN void PCRE_CALL_CONVENTION +pcre_free_substring_list(const char **pointer) +{ +(pcre_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 +*/ + +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_get_substring(const char *subject, int *ovector, int stringcount, + int stringnumber, const char **stringptr) +{ +int yield; +char *substring; +if (stringnumber < 0 || stringnumber >= stringcount) + return PCRE_ERROR_NOSUBSTRING; +stringnumber *= 2; +yield = ovector[stringnumber+1] - ovector[stringnumber]; +substring = (char *)(pcre_malloc)(yield + 1); +if (substring == NULL) return PCRE_ERROR_NOMEMORY; +memcpy(substring, subject + ovector[stringnumber], yield); +substring[yield] = 0; +*stringptr = substring; +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 +*/ + +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) +{ +int n = get_first_set(code, stringname, ovector); +if (n <= 0) return n; +return pcre_get_substring(subject, ovector, stringcount, n, stringptr); +} + + + + +/************************************************* +* 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 (pcre_free)() directly. + +Argument: the result of a previous pcre_get_substring() +Returns: nothing +*/ + +PCRE_EXP_DEFN void PCRE_CALL_CONVENTION +pcre_free_substring(const char *pointer) +{ +(pcre_free)((void *)pointer); +} + +/* End of pcre_get.c */ diff --git a/Library/pcre-8.10/pcre_globals.c b/Library/pcre-8.10/pcre_globals.c new file mode 100644 index 00000000..4562e0a0 --- /dev/null +++ b/Library/pcre-8.10/pcre_globals.c @@ -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-2008 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains global variables that are exported by the PCRE library. +PCRE is thread-clean and doesn't use any global variables in the normal sense. +However, it calls memory allocation and freeing functions via the four +indirections below, and it can optionally do callouts, using the fifth +indirection. These values can be changed by the caller, but are shared between +all threads. + +For MS Visual Studio and Symbian OS, there are problems in initializing these +variables to non-local functions. In these cases, therefore, an indirection via +a local function is used. + +Also, when compiling for Virtual Pascal, things are done differently, and +global variables are not used. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + +#if defined _MSC_VER || defined __SYMBIAN32__ +static void* LocalPcreMalloc(size_t aSize) + { + return malloc(aSize); + } +static void LocalPcreFree(void* aPtr) + { + free(aPtr); + } +PCRE_EXP_DATA_DEFN void *(*pcre_malloc)(size_t) = LocalPcreMalloc; +PCRE_EXP_DATA_DEFN void (*pcre_free)(void *) = LocalPcreFree; +PCRE_EXP_DATA_DEFN void *(*pcre_stack_malloc)(size_t) = LocalPcreMalloc; +PCRE_EXP_DATA_DEFN void (*pcre_stack_free)(void *) = LocalPcreFree; +PCRE_EXP_DATA_DEFN int (*pcre_callout)(pcre_callout_block *) = NULL; + +#elif !defined VPCOMPAT +PCRE_EXP_DATA_DEFN void *(*pcre_malloc)(size_t) = malloc; +PCRE_EXP_DATA_DEFN void (*pcre_free)(void *) = free; +PCRE_EXP_DATA_DEFN void *(*pcre_stack_malloc)(size_t) = malloc; +PCRE_EXP_DATA_DEFN void (*pcre_stack_free)(void *) = free; +PCRE_EXP_DATA_DEFN int (*pcre_callout)(pcre_callout_block *) = NULL; +#endif + +/* End of pcre_globals.c */ diff --git a/Library/pcre-8.10/pcre_info.c b/Library/pcre-8.10/pcre_info.c new file mode 100644 index 00000000..f35f398d --- /dev/null +++ b/Library/pcre-8.10/pcre_info.c @@ -0,0 +1,93 @@ +/************************************************* +* 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-2009 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_info(), which gives some +information about a compiled pattern. However, use of this function is now +deprecated, as it has been superseded by pcre_fullinfo(). */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/************************************************* +* (Obsolete) Return info about compiled pattern * +*************************************************/ + +/* This is the original "info" function. It picks potentially useful data out +of the private structure, but its interface was too rigid. It remains for +backwards compatibility. The public options are passed back in an int - though +the re->options field has been expanded to a long int, all the public options +at the low end of it, and so even on 16-bit systems this will still be OK. +Therefore, I haven't changed the API for pcre_info(). + +Arguments: + argument_re points to compiled code + optptr where to pass back the options + first_byte where to pass back the first character, + or -1 if multiline and all branches start ^, + or -2 otherwise + +Returns: number of capturing subpatterns + or negative values on error +*/ + +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_info(const pcre *argument_re, int *optptr, int *first_byte) +{ +real_pcre internal_re; +const real_pcre *re = (const real_pcre *)argument_re; +if (re == NULL) return PCRE_ERROR_NULL; +if (re->magic_number != MAGIC_NUMBER) + { + re = _pcre_try_flipped(re, &internal_re, NULL, NULL); + if (re == NULL) return PCRE_ERROR_BADMAGIC; + } +if (optptr != NULL) *optptr = (int)(re->options & PUBLIC_COMPILE_OPTIONS); +if (first_byte != NULL) + *first_byte = ((re->flags & PCRE_FIRSTSET) != 0)? re->first_byte : + ((re->flags & PCRE_STARTLINE) != 0)? -1 : -2; +return re->top_bracket; +} + +/* End of pcre_info.c */ diff --git a/Library/pcre-8.10/pcre_internal.h b/Library/pcre-8.10/pcre_internal.h new file mode 100644 index 00000000..e293602f --- /dev/null +++ b/Library/pcre-8.10/pcre_internal.h @@ -0,0 +1,1829 @@ +/************************************************* +* 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-2010 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_". */ + +#ifndef PCRE_INTERNAL_H +#define PCRE_INTERNAL_H + +/* Define PCRE_DEBUG to get debugging output on stdout. */ + +#if 0 +#define PCRE_DEBUG +#endif + +/* We do not support both EBCDIC and UTF-8 at the same time. The "configure" +script prevents both being selected, but not everybody uses "configure". */ + +#if defined EBCDIC && defined SUPPORT_UTF8 +#error The use of both EBCDIC and SUPPORT_UTF8 is not supported. +#endif + +/* If SUPPORT_UCP is defined, SUPPORT_UTF8 must also be defined. The +"configure" script ensures this, but not everybody uses "configure". */ + +#if defined SUPPORT_UCP && !defined SUPPORT_UTF8 +#define SUPPORT_UTF8 1 +#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 +#include +#include +#include +#include +#include + +/* 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 16-bit 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. */ + +#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 +#elif HAVE_INTTYPES_H +#include +#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 *, because that +should make things easier for callers. We define a short type for unsigned char +to save lots of typing. I tried "uchar", but it causes problems on Digital +Unix, where it is defined in sys/types, so use "uschar" instead. */ + +typedef unsigned char uschar; + +/* 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 && \ + _pcre_is_newline((p), NLBLOCK->nltype, NLBLOCK->PSEND, &(NLBLOCK->nllen),\ + utf8)) \ + : \ + ((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 && \ + _pcre_was_newline((p), NLBLOCK->nltype, NLBLOCK->PSSTART, \ + &(NLBLOCK->nllen), utf8)) \ + : \ + ((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_SPTR CUSTOM_SUBJECT_PTR +#define USPTR CUSTOM_SUBJECT_PTR +#else +#define PCRE_SPTR const char * +#define USPTR const unsigned char * +#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. */ + +#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]) + +#define MAX_PATTERN_SIZE (1 << 30) /* Keep it positive */ + + +#else +#error LINK_SIZE must be either 2, 3, or 4 +#endif + + +/* 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. */ + +#define PUT2(a,n,d) \ + a[n] = (d) >> 8; \ + a[(n)+1] = (d) & 255 + +#define GET2(a,n) \ + (((a)[n] << 8) | (a)[(n)+1]) + +#define PUT2INC(a,n,d) PUT2(a,n,d), a += 2 + + +/* When UTF-8 encoding is being used, a character is no longer just a single +byte. The macros for character handling generate simple sequences when used in +byte-mode, and more complicated ones for UTF-8 characters. BACKCHAR should +never be called in byte mode. To make sure it can never even appear when UTF-8 +support is omitted, we don't even define it. */ + +#ifndef SUPPORT_UTF8 +#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 BACKCHAR(eptr) */ + +#else /* SUPPORT_UTF8 */ + +/* 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) \ + { \ + int gcii; \ + int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & _pcre_utf8_table3[gcaa]) << gcss; \ + for (gcii = 1; gcii <= gcaa; gcii++) \ + { \ + gcss -= 6; \ + c |= (eptr[gcii] & 0x3f) << gcss; \ + } \ + } + +/* Get the next UTF-8 character, testing for UTF-8 mode, and not advancing the +pointer. */ + +#define GETCHARTEST(c, eptr) \ + c = *eptr; \ + if (utf8 && c >= 0xc0) \ + { \ + int gcii; \ + int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & _pcre_utf8_table3[gcaa]) << gcss; \ + for (gcii = 1; gcii <= gcaa; gcii++) \ + { \ + gcss -= 6; \ + c |= (eptr[gcii] & 0x3f) << gcss; \ + } \ + } + +/* 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) \ + { \ + int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & _pcre_utf8_table3[gcaa]) << gcss; \ + while (gcaa-- > 0) \ + { \ + gcss -= 6; \ + c |= (*eptr++ & 0x3f) << gcss; \ + } \ + } + +/* 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 (utf8 && c >= 0xc0) \ + { \ + int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & _pcre_utf8_table3[gcaa]) << gcss; \ + while (gcaa-- > 0) \ + { \ + gcss -= 6; \ + c |= (*eptr++ & 0x3f) << gcss; \ + } \ + } + +/* 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) \ + { \ + int gcii; \ + int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & _pcre_utf8_table3[gcaa]) << gcss; \ + for (gcii = 1; gcii <= gcaa; gcii++) \ + { \ + gcss -= 6; \ + c |= (eptr[gcii] & 0x3f) << gcss; \ + } \ + len += gcaa; \ + } + +/* 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 (utf8 && c >= 0xc0) \ + { \ + int gcii; \ + int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \ + int gcss = 6*gcaa; \ + c = (c & _pcre_utf8_table3[gcaa]) << gcss; \ + for (gcii = 1; gcii <= gcaa; gcii++) \ + { \ + gcss -= 6; \ + c |= (eptr[gcii] & 0x3f) << gcss; \ + } \ + len += gcaa; \ + } + +/* 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-- + +#endif + + +/* 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 + + +/* These are the public options that can change during matching. */ + +#define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL) + +/* 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. */ + +#define PCRE_NOPARTIAL 0x0001 /* can't use partial with this regex */ +#define PCRE_FIRSTSET 0x0002 /* first_byte is set */ +#define PCRE_REQCHSET 0x0004 /* req_byte is set */ +#define PCRE_STARTLINE 0x0008 /* start after \n for multiline */ +#define PCRE_JCHANGED 0x0010 /* j option used in regex */ +#define PCRE_HASCRORLF 0x0020 /* explicit \r or \n in pattern */ + +/* Options for the "extra" block produced by pcre_study(). */ + +#define PCRE_STUDY_MAPPED 0x01 /* a map of starting chars exists */ +#define PCRE_STUDY_MINLEN 0x02 /* 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) + +#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 0 /* None defined */ + +/* Magic number to provide a small check against being handed junk. Also used +to detect whether a pattern was compiled on a host of different endianness. */ + +#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */ + +/* 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 + +/* Flags added to firstbyte or reqbyte; a "non-literal" item is either a +variable-length repeat, or a anything other than literal characters. */ + +#define REQ_CASELESS 0x0100 /* indicates caselessness */ +#define REQ_VARY 0x0200 /* reqbyte followed non-literal item */ + +/* 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_UTF8 + +/* 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)" +#define STRING_UTF8_RIGHTPAR "UTF8)" +#define STRING_UCP_RIGHTPAR "UCP)" + +#else /* SUPPORT_UTF8 */ + +/* 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 +#define STRING_UTF8_RIGHTPAR STR_U STR_T STR_F STR_8 STR_RIGHT_PARENTHESIS +#define STRING_UCP_RIGHTPAR STR_U STR_C STR_P STR_RIGHT_PARENTHESIS + +#endif /* SUPPORT_UTF8 */ + +/* 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 UTF-8 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. 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_OPT, /* 25 Set runtime options */ + OP_CIRC, /* 26 Start of line - varies with multiline switch */ + OP_DOLL, /* 27 End of line - varies with multiline switch */ + OP_CHAR, /* 28 Match one character, casefully */ + OP_CHARNC, /* 29 Match one character, caselessly */ + OP_NOT, /* 30 Match one character, not the following one */ + + OP_STAR, /* 31 The maximizing and minimizing versions of */ + OP_MINSTAR, /* 32 these six opcodes must come in pairs, with */ + OP_PLUS, /* 33 the minimizing one second. */ + OP_MINPLUS, /* 34 This first set applies to single characters.*/ + OP_QUERY, /* 35 */ + OP_MINQUERY, /* 36 */ + + OP_UPTO, /* 37 From 0 to n matches */ + OP_MINUPTO, /* 38 */ + OP_EXACT, /* 39 Exactly n matches */ + + OP_POSSTAR, /* 40 Possessified star */ + OP_POSPLUS, /* 41 Possessified plus */ + OP_POSQUERY, /* 42 Posesssified query */ + OP_POSUPTO, /* 43 Possessified upto */ + + OP_NOTSTAR, /* 44 The maximizing and minimizing versions of */ + OP_NOTMINSTAR, /* 45 these six opcodes must come in pairs, with */ + OP_NOTPLUS, /* 46 the minimizing one second. They must be in */ + OP_NOTMINPLUS, /* 47 exactly the same order as those above. */ + OP_NOTQUERY, /* 48 This set applies to "not" single characters. */ + OP_NOTMINQUERY, /* 49 */ + + OP_NOTUPTO, /* 50 From 0 to n matches */ + OP_NOTMINUPTO, /* 51 */ + OP_NOTEXACT, /* 52 Exactly n matches */ + + OP_NOTPOSSTAR, /* 53 Possessified versions */ + OP_NOTPOSPLUS, /* 54 */ + OP_NOTPOSQUERY, /* 55 */ + OP_NOTPOSUPTO, /* 56 */ + + OP_TYPESTAR, /* 57 The maximizing and minimizing versions of */ + OP_TYPEMINSTAR, /* 58 these six opcodes must come in pairs, with */ + OP_TYPEPLUS, /* 59 the minimizing one second. These codes must */ + OP_TYPEMINPLUS, /* 60 be in exactly the same order as those above. */ + OP_TYPEQUERY, /* 61 This set applies to character types such as \d */ + OP_TYPEMINQUERY, /* 62 */ + + OP_TYPEUPTO, /* 63 From 0 to n matches */ + OP_TYPEMINUPTO, /* 64 */ + OP_TYPEEXACT, /* 65 Exactly n matches */ + + OP_TYPEPOSSTAR, /* 66 Possessified versions */ + OP_TYPEPOSPLUS, /* 67 */ + OP_TYPEPOSQUERY, /* 68 */ + OP_TYPEPOSUPTO, /* 69 */ + + OP_CRSTAR, /* 70 The maximizing and minimizing versions of */ + OP_CRMINSTAR, /* 71 all these opcodes must come in pairs, with */ + OP_CRPLUS, /* 72 the minimizing one second. These codes must */ + OP_CRMINPLUS, /* 73 be in exactly the same order as those above. */ + OP_CRQUERY, /* 74 These are for character classes and back refs */ + OP_CRMINQUERY, /* 75 */ + OP_CRRANGE, /* 76 These are different to the three sets above. */ + OP_CRMINRANGE, /* 77 */ + + OP_CLASS, /* 78 Match a character class, chars < 256 only */ + OP_NCLASS, /* 79 Same, but the bitmap was created from a negative + class - the difference is relevant only when a UTF-8 + character > 255 is encountered. */ + + OP_XCLASS, /* 80 Extended class for handling UTF-8 chars within the + class. This does both positive and negative. */ + + OP_REF, /* 81 Match a back reference */ + OP_RECURSE, /* 82 Match a numbered subpattern (possibly recursive) */ + OP_CALLOUT, /* 83 Call out to external function if provided */ + + OP_ALT, /* 84 Start of alternation */ + OP_KET, /* 85 End of group that doesn't have an unbounded repeat */ + OP_KETRMAX, /* 86 These two must remain together and in this */ + OP_KETRMIN, /* 87 order. They are for groups the repeat for ever. */ + + /* The assertions must come before BRA, CBRA, ONCE, and COND.*/ + + OP_ASSERT, /* 88 Positive lookahead */ + OP_ASSERT_NOT, /* 89 Negative lookahead */ + OP_ASSERTBACK, /* 90 Positive lookbehind */ + OP_ASSERTBACK_NOT, /* 91 Negative lookbehind */ + OP_REVERSE, /* 92 Move pointer back - used in lookbehind assertions */ + + /* ONCE, BRA, CBRA, and COND must come after the assertions, with ONCE first, + as there's a test for >= ONCE for a subpattern that isn't an assertion. */ + + OP_ONCE, /* 93 Atomic group */ + OP_BRA, /* 94 Start of non-capturing bracket */ + OP_CBRA, /* 95 Start of capturing bracket */ + OP_COND, /* 96 Conditional group */ + + /* These three must follow the previous three, in the same order. There's a + check for >= SBRA to distinguish the two sets. */ + + OP_SBRA, /* 97 Start of non-capturing bracket, check empty */ + OP_SCBRA, /* 98 Start of capturing bracket, check empty */ + OP_SCOND, /* 99 Conditional group, check empty */ + + /* The next two pairs must (respectively) be kept together. */ + + OP_CREF, /* 100 Used to hold a capture number as condition */ + OP_NCREF, /* 101 Same, but generaged by a name reference*/ + OP_RREF, /* 102 Used to hold a recursion number as condition */ + OP_NRREF, /* 103 Same, but generaged by a name reference*/ + OP_DEF, /* 104 The DEFINE condition */ + + OP_BRAZERO, /* 105 These two must remain together and in this */ + OP_BRAMINZERO, /* 106 order. */ + + /* These are backtracking control verbs */ + + OP_MARK, /* 107 always has an argument */ + OP_PRUNE, /* 108 */ + OP_PRUNE_ARG, /* 109 same, but with argument */ + OP_SKIP, /* 110 */ + OP_SKIP_ARG, /* 111 same, but with argument */ + OP_THEN, /* 112 */ + OP_THEN_ARG, /* 113 same, but with argument */ + OP_COMMIT, /* 114 */ + + /* These are forced failure and success verbs */ + + OP_FAIL, /* 115 */ + OP_ACCEPT, /* 116 */ + OP_CLOSE, /* 117 Used before OP_ACCEPT to close open captures */ + + /* This is used to skip a subpattern with a {0} quantifier */ + + OP_SKIPZERO, /* 118 */ + + /* 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. The macro is referenced only in pcre_printint.c. */ + +#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", \ + "Opt", "^", "$", "char", "charnc", "not", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ + "*+","++", "?+", "{", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ + "*+","++", "?+", "{", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ + "*+","++", "?+", "{", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", \ + "class", "nclass", "xclass", "Ref", "Recurse", "Callout", \ + "Alt", "Ket", "KetRmax", "KetRmin", "Assert", "Assert not", \ + "AssertB", "AssertB not", "Reverse", \ + "Once", "Bra", "CBra", "Cond", "SBra", "SCBra", "SCond", \ + "Cond ref", "Cond nref", "Cond rec", "Cond nrec", "Cond def", \ + "Brazero", "Braminzero", \ + "*MARK", "*PRUNE", "*PRUNE", "*SKIP", "*SKIP", \ + "*THEN", "*THEN", "*COMMIT", "*FAIL", "*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, 2, 1, 1, /* \Z, \z, Opt, ^, $ */ \ + 2, /* Char - the minimum length */ \ + 2, /* Charnc - the minimum length */ \ + 2, /* not */ \ + /* Positive single-char repeats ** These are */ \ + 2, 2, 2, 2, 2, 2, /* *, *?, +, +?, ?, ?? ** minima in */ \ + 4, 4, 4, /* upto, minupto, exact ** UTF-8 mode */ \ + 2, 2, 2, 4, /* *+, ++, ?+, upto+ */ \ + /* Negative single-char repeats - only for chars < 256 */ \ + 2, 2, 2, 2, 2, 2, /* NOT *, *?, +, +?, ?, ?? */ \ + 4, 4, 4, /* NOT upto, minupto, exact */ \ + 2, 2, 2, 4, /* Possessive *, +, ?, upto */ \ + /* Positive type repeats */ \ + 2, 2, 2, 2, 2, 2, /* Type *, *?, +, +?, ?, ?? */ \ + 4, 4, 4, /* Type upto, minupto, exact */ \ + 2, 2, 2, 4, /* Possessive *+, ++, ?+, upto+ */ \ + /* Character class & ref repeats */ \ + 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ \ + 5, 5, /* CRRANGE, CRMINRANGE */ \ + 33, /* CLASS */ \ + 33, /* NCLASS */ \ + 0, /* XCLASS - variable length */ \ + 3, /* REF */ \ + 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, /* Assert */ \ + 1+LINK_SIZE, /* Assert not */ \ + 1+LINK_SIZE, /* Assert behind */ \ + 1+LINK_SIZE, /* Assert behind not */ \ + 1+LINK_SIZE, /* Reverse */ \ + 1+LINK_SIZE, /* ONCE */ \ + 1+LINK_SIZE, /* BRA */ \ + 3+LINK_SIZE, /* CBRA */ \ + 1+LINK_SIZE, /* COND */ \ + 1+LINK_SIZE, /* SBRA */ \ + 3+LINK_SIZE, /* SCBRA */ \ + 1+LINK_SIZE, /* SCOND */ \ + 3, 3, /* CREF, NCREF */ \ + 3, 3, /* RREF, NRREF */ \ + 1, /* DEF */ \ + 1, 1, /* BRAZERO, BRAMINZERO */ \ + 3, 1, 3, /* MARK, PRUNE, PRUNE_ARG, */ \ + 1, 3, 1, 3, /* SKIP, SKIP_ARG, THEN, THEN_ARG, */ \ + 1, 1, 1, 3, 1 /* COMMIT, FAIL, ACCEPT, 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, 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 +*/ + +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_byte; + pcre_uint16 req_byte; + 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 unsigned char *tables; /* Pointer to tables or NULL for std */ + const unsigned char *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 */ + uschar 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 uschar *lcc; /* Points to lower casing table */ + const uschar *fcc; /* Points to case-flipping table */ + const uschar *cbits; /* Points to character type table */ + const uschar *ctypes; /* Points to table of type maps */ + const uschar *start_workspace;/* The start of working space */ + const uschar *start_code; /* The start of the compiled code */ + const uschar *start_pattern; /* The start of the pattern */ + const uschar *end_pattern; /* The end of the pattern */ + open_capitem *open_caps; /* Chain of open capture items */ + uschar *hwm; /* High watermark of workspace */ + uschar *name_table; /* The name/number table */ + int names_found; /* Number of entries so far */ + int name_entry_size; /* Size of each entry */ + 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 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 */ + uschar 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. */ + +typedef struct branch_chain { + struct branch_chain *outer; + uschar *current_branch; +} branch_chain; + +/* Structure for items in a linked list that represents an explicit recursive +call within the pattern. */ + +typedef struct recursion_info { + struct recursion_info *prevrec; /* Previous recursion record (or NULL) */ + int group_num; /* Number of group that was called */ + const uschar *after_call; /* "Return value": points after the call in the expr */ + int *offset_save; /* Pointer to start of saved offsets */ + int saved_max; /* Number of saved offsets */ + int save_offset_top; /* Current value of offset_top */ +} 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. */ + +typedef struct eptrblock { + struct eptrblock *epb_prev; + USPTR 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 */ + uschar *name_table; /* Table of names */ + uschar nl[4]; /* Newline string when fixed */ + const uschar *lcc; /* Points to lower casing table */ + const uschar *ctypes; /* Points to table of type maps */ + BOOL offset_overflow; /* Set if too many extractions */ + BOOL notbol; /* NOTBOL flag */ + BOOL noteol; /* NOTEOL flag */ + BOOL utf8; /* UTF8 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 */ + const uschar *start_code; /* For use when recursing */ + USPTR start_subject; /* Start of the subject string */ + USPTR end_subject; /* End of the subject string */ + USPTR start_match_ptr; /* Start of matched string */ + USPTR end_match_ptr; /* Subject position at end match */ + USPTR 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 */ + 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 uschar *mark; /* Mark pointer to pass back */ +} match_data; + +/* A similar structure is used for the same purpose by the DFA matching +functions. */ + +typedef struct dfa_match_data { + const uschar *start_code; /* Start of the compiled pattern */ + const uschar *start_subject; /* Start of the subject string */ + const uschar *end_subject; /* End of subject string */ + const uschar *start_used_ptr; /* Earliest consulted character */ + const uschar *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 */ + uschar nl[4]; /* Newline string when fixed */ + void *callout_data; /* To pass back to callouts */ +} 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) + +/* 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. */ + +extern const int _pcre_utf8_table1[]; +extern const int _pcre_utf8_table2[]; +extern const int _pcre_utf8_table3[]; +extern const uschar _pcre_utf8_table4[]; + +extern const int _pcre_utf8_table1_size; + +extern const char _pcre_utt_names[]; +extern const ucp_type_table _pcre_utt[]; +extern const int _pcre_utt_size; + +extern const uschar _pcre_default_tables[]; + +extern const uschar _pcre_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. */ + +extern const uschar *_pcre_find_bracket(const uschar *, BOOL, int); +extern BOOL _pcre_is_newline(USPTR, int, USPTR, int *, BOOL); +extern int _pcre_ord2utf8(int, uschar *); +extern real_pcre *_pcre_try_flipped(const real_pcre *, real_pcre *, + const pcre_study_data *, pcre_study_data *); +extern int _pcre_valid_utf8(USPTR, int); +extern BOOL _pcre_was_newline(USPTR, int, USPTR, int *, BOOL); +extern BOOL _pcre_xclass(int, const uschar *); + + +/* Unicode character database (UCD) */ + +typedef struct { + uschar script; + uschar chartype; + pcre_int32 other_case; +} ucd_record; + +extern const ucd_record _pcre_ucd_records[]; +extern const uschar _pcre_ucd_stage1[]; +extern const pcre_uint16 _pcre_ucd_stage2[]; +extern const int _pcre_ucp_gentype[]; + + +/* UCD access macros */ + +#define UCD_BLOCK_SIZE 128 +#define GET_UCD(ch) (_pcre_ucd_records + \ + _pcre_ucd_stage2[_pcre_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) _pcre_ucp_gentype[UCD_CHARTYPE(ch)] +#define UCD_OTHERCASE(ch) (ch + GET_UCD(ch)->other_case) + +#endif + +/* End of pcre_internal.h */ diff --git a/Library/pcre-8.10/pcre_maketables.c b/Library/pcre-8.10/pcre_maketables.c new file mode 100644 index 00000000..219973e3 --- /dev/null +++ b/Library/pcre-8.10/pcre_maketables.c @@ -0,0 +1,143 @@ +/************************************************* +* 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-2008 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_maketables(), which builds +character tables for PCRE in the current locale. The file is compiled on its +own as part of the PCRE library. However, it is also included in the +compilation of dftables.c, in which case the macro DFTABLES is defined. */ + + +#ifndef DFTABLES +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif +# include "pcre_internal.h" +#endif + + +/************************************************* +* Create PCRE character tables * +*************************************************/ + +/* This function builds a set of character tables for use by PCRE and returns +a pointer to them. They are build using the ctype functions, and consequently +their contents will depend upon the current locale setting. When compiled as +part of the library, the store is obtained via pcre_malloc(), but when compiled +inside dftables, use malloc(). + +Arguments: none +Returns: pointer to the contiguous block of data +*/ + +const unsigned char * +pcre_maketables(void) +{ +unsigned char *yield, *p; +int i; + +#ifndef DFTABLES +yield = (unsigned char*)(pcre_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/Library/pcre-8.10/pcre_newline.c b/Library/pcre-8.10/pcre_newline.c new file mode 100644 index 00000000..38cf7f72 --- /dev/null +++ b/Library/pcre-8.10/pcre_newline.c @@ -0,0 +1,162 @@ +/************************************************* +* 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-2009 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains internal functions for testing newlines when more than +one kind of newline is to be recognized. When a newline is found, its length is +returned. In principle, we could implement several newline "types", each +referring to a different set of newline characters. At present, PCRE supports +only NLTYPE_FIXED, which gets handled without these functions, NLTYPE_ANYCRLF, +and NLTYPE_ANY. The full list of Unicode newline characters is taken from +http://unicode.org/unicode/reports/tr18/. */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + + +/************************************************* +* Check for newline at given position * +*************************************************/ + +/* It is guaranteed that the initial value of ptr is less than the end of the +string that is being processed. + +Arguments: + ptr pointer to possible newline + type the newline type + endptr pointer to the end of the string + lenptr where to return the length + utf8 TRUE if in utf8 mode + +Returns: TRUE or FALSE +*/ + +BOOL +_pcre_is_newline(USPTR ptr, int type, USPTR endptr, int *lenptr, BOOL utf8) +{ +int c; +if (utf8) { GETCHAR(c, ptr); } else 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 */ + case 0x0085: *lenptr = utf8? 2 : 1; return TRUE; /* NEL */ + case 0x2028: /* LS */ + case 0x2029: *lenptr = 3; return TRUE; /* PS */ + 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 + utf8 TRUE if in utf8 mode + +Returns: TRUE or FALSE +*/ + +BOOL +_pcre_was_newline(USPTR ptr, int type, USPTR startptr, int *lenptr, BOOL utf8) +{ +int c; +ptr--; +#ifdef SUPPORT_UTF8 +if (utf8) + { + BACKCHAR(ptr); + GETCHAR(c, ptr); + } +else c = *ptr; +#else /* no UTF-8 support */ +c = *ptr; +#endif /* SUPPORT_UTF8 */ + +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 */ + case 0x0085: *lenptr = utf8? 2 : 1; return TRUE; /* NEL */ + case 0x2028: /* LS */ + case 0x2029: *lenptr = 3; return TRUE; /* PS */ + default: return FALSE; + } +} + +/* End of pcre_newline.c */ diff --git a/Library/pcre-8.10/pcre_ord2utf8.c b/Library/pcre-8.10/pcre_ord2utf8.c new file mode 100644 index 00000000..6f4eb9eb --- /dev/null +++ b/Library/pcre-8.10/pcre_ord2utf8.c @@ -0,0 +1,87 @@ +/************************************************* +* 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-2008 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 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 - 0x7fffffff +and encodes it as a UTF-8 character in 0 to 6 bytes. + +Arguments: + cvalue the character value + buffer pointer to buffer for result - at least 6 bytes long + +Returns: number of characters placed in the buffer +*/ + +int +_pcre_ord2utf8(int cvalue, uschar *buffer) +{ +#ifdef SUPPORT_UTF8 +register int i, j; +for (i = 0; i < _pcre_utf8_table1_size; i++) + if (cvalue <= _pcre_utf8_table1[i]) break; +buffer += i; +for (j = i; j > 0; j--) + { + *buffer-- = 0x80 | (cvalue & 0x3f); + cvalue >>= 6; + } +*buffer = _pcre_utf8_table2[i] | cvalue; +return i + 1; +#else +(void)(cvalue); /* Keep compiler happy; this function won't ever be */ +(void)(buffer); /* called when SUPPORT_UTF8 is not defined. */ +return 0; +#endif +} + +/* End of pcre_ord2utf8.c */ diff --git a/Library/pcre-8.10/pcre_refcount.c b/Library/pcre-8.10/pcre_refcount.c new file mode 100644 index 00000000..92e4b850 --- /dev/null +++ b/Library/pcre-8.10/pcre_refcount.c @@ -0,0 +1,82 @@ +/************************************************* +* 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-2008 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_refcount(), which is an +auxiliary function that can be used to maintain a reference count in a compiled +pattern data block. This might be helpful in applications where the block is +shared by different users. */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/************************************************* +* Maintain reference count * +*************************************************/ + +/* The reference count is a 16-bit field, initialized to zero. It is not +possible to transfer a non-zero count from one host to a different host that +has a different byte order - though I can't see why anyone in their right mind +would ever want to do that! + +Arguments: + argument_re points to compiled code + adjust value to add to the count + +Returns: the (possibly updated) count value (a non-negative number), or + a negative error number +*/ + +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_refcount(pcre *argument_re, int adjust) +{ +real_pcre *re = (real_pcre *)argument_re; +if (re == NULL) return PCRE_ERROR_NULL; +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/Library/pcre-8.10/pcre_study.c b/Library/pcre-8.10/pcre_study.c new file mode 100644 index 00000000..f5e0c3a0 --- /dev/null +++ b/Library/pcre-8.10/pcre_study.c @@ -0,0 +1,1126 @@ +/************************************************* +* 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-2010 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_study(), along with local +supporting functions. */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + +#define SET_BIT(c) start_bits[c/8] |= (1 << (c&7)) + +/* Returns from set_start_bits() */ + +enum { SSB_FAIL, SSB_DONE, SSB_CONTINUE }; + + + +/************************************************* +* 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 + +Returns: the minimum length + -1 if \C was encountered + -2 internal error (missing capturing bracket) +*/ + +static int +find_minlength(const uschar *code, const uschar *startcode, int options) +{ +int length = -1; +BOOL utf8 = (options & PCRE_UTF8) != 0; +BOOL had_recurse = FALSE; +register int branchlength = 0; +register uschar *cc = (uschar *)code + 1 + LINK_SIZE; + +if (*code == OP_CBRA || *code == OP_SCBRA) cc += 2; + +/* 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; + uschar *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_ONCE: + d = find_minlength(cc, startcode, options); + 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. If it is + END it's the end of the outer call. All can be handled by the same code. */ + + case OP_ALT: + case OP_KET: + case OP_KETRMAX: + case OP_KETRMIN: + case OP_END: + if (length < 0 || (!had_recurse && branchlength < length)) + length = branchlength; + if (*cc != 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_OPT: + case OP_CALLOUT: + case OP_SOD: + case OP_SOM: + case OP_EOD: + case OP_EODN: + case OP_CIRC: + case OP_DOLL: + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + cc += _pcre_OP_lengths[*cc]; + break; + + /* Skip over a subpattern that has a {0} or {0,x} quantifier */ + + case OP_BRAZERO: + case OP_BRAMINZERO: + case OP_SKIPZERO: + cc += _pcre_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_CHARNC: + case OP_NOT: + case OP_PLUS: + case OP_MINPLUS: + case OP_POSPLUS: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTPOSPLUS: + branchlength++; + cc += 2; +#ifdef SUPPORT_UTF8 + if (utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f]; +#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_NOTEXACT: + branchlength += GET2(cc,1); + cc += 4; +#ifdef SUPPORT_UTF8 + if (utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f]; +#endif + break; + + case OP_TYPEEXACT: + branchlength += GET2(cc,1); + cc += (cc[3] == OP_PROP || cc[3] == OP_NOTPROP)? 6 : 4; + 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 */ + + case OP_ANYNL: + branchlength += 2; + cc++; + break; + + /* The single-byte matcher means we can't proceed in UTF-8 mode */ + + case OP_ANYBYTE: +#ifdef SUPPORT_UTF8 + if (utf8) 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 += _pcre_OP_lengths[op]; + break; + + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + case OP_TYPEPOSUPTO: + if (cc[3] == OP_PROP || cc[3] == OP_NOTPROP) cc += 2; + cc += _pcre_OP_lengths[op]; + break; + + /* Check a class for variable quantification */ + +#ifdef SUPPORT_UTF8 + case OP_XCLASS: + cc += GET(cc, 1) - 33; + /* Fall through */ +#endif + + case OP_CLASS: + case OP_NCLASS: + cc += 33; + + 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 += 5; + 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: + if ((options & PCRE_JAVASCRIPT_COMPAT) == 0) + { + ce = cs = (uschar *)_pcre_find_bracket(startcode, utf8, 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); + } + else d = 0; + cc += 3; + + /* Handle repeated back references */ + + switch (*cc) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + min = 0; + cc++; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + min = GET2(cc, 1); + cc += 5; + break; + + default: + min = 1; + break; + } + + branchlength += min * d; + break; + + case OP_RECURSE: + cs = ce = (uschar *)startcode + GET(cc, 1); + if (cs == NULL) return -2; + do ce += GET(ce, 1); while (*ce == OP_ALT); + if (cc > cs && cc < ce) + had_recurse = TRUE; + else + branchlength += find_minlength(cs, startcode, options); + 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. */ + + case OP_UPTO: + case OP_NOTUPTO: + case OP_MINUPTO: + case OP_NOTMINUPTO: + case OP_POSUPTO: + case OP_STAR: + case OP_MINSTAR: + case OP_NOTMINSTAR: + case OP_POSSTAR: + case OP_NOTPOSSTAR: + case OP_QUERY: + case OP_MINQUERY: + case OP_NOTMINQUERY: + case OP_POSQUERY: + case OP_NOTPOSQUERY: + cc += _pcre_OP_lengths[op]; +#ifdef SUPPORT_UTF8 + if (utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f]; +#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 += _pcre_OP_lengths[op] + cc[1]; + break; + + /* For the record, these are the opcodes that are matched by "default": + OP_ACCEPT, OP_CLOSE, OP_COMMIT, OP_FAIL, OP_PRUNE, OP_SET_SOM, OP_SKIP, + OP_THEN. */ + + default: + cc += _pcre_OP_lengths[op]; + break; + } + } +/* 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 + utf8 TRUE for UTF-8 mode + +Returns: pointer after the character +*/ + +static const uschar * +set_table_bit(uschar *start_bits, const uschar *p, BOOL caseless, + compile_data *cd, BOOL utf8) +{ +unsigned int c = *p; + +SET_BIT(c); + +#ifdef SUPPORT_UTF8 +if (utf8 && c > 127) + { + GETCHARINC(c, p); +#ifdef SUPPORT_UCP + if (caseless) + { + uschar buff[8]; + c = UCD_OTHERCASE(c); + (void)_pcre_ord2utf8(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; +} + + + +/************************************************* +* 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(uschar *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 (table_limit == 32) return; +for (c = 128; c < 256; c++) + { + if ((cd->cbits[c/8] & (1 << (c&7))) != 0) + { + uschar buff[8]; + (void)_pcre_ord2utf8(c, buff); + SET_BIT(buff[0]); + } + } +} + + +/************************************************* +* 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(uschar *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 (table_limit != 32) for (c = 24; c < 32; c++) start_bits[c] = 0xff; +} + + + +/************************************************* +* 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 + caseless the current state of the caseless flag + utf8 TRUE if in UTF-8 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 +*/ + +static int +set_start_bits(const uschar *code, uschar *start_bits, BOOL caseless, + BOOL utf8, compile_data *cd) +{ +register int c; +int yield = SSB_DONE; +int table_limit = utf8? 16:32; + +#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 + { + const uschar *tcode = code + (((int)*code == OP_CBRA)? 3:1) + LINK_SIZE; + BOOL try_next = TRUE; + + while (try_next) /* Loop for items in this branch */ + { + int rc; + switch(*tcode) + { + /* Fail if we reach something we don't understand */ + + default: + return SSB_FAIL; + + /* 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_ONCE: + case OP_ASSERT: + rc = set_start_bits(tcode, start_bits, caseless, utf8, cd); + if (rc == SSB_FAIL) return SSB_FAIL; + 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: + 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; + + /* Skip over an option setting, changing the caseless flag */ + + case OP_OPT: + caseless = (tcode[1] & PCRE_CASELESS) != 0; + tcode += 2; + break; + + /* BRAZERO does the bracket, but carries on. */ + + case OP_BRAZERO: + case OP_BRAMINZERO: + if (set_start_bits(++tcode, start_bits, caseless, utf8, cd) == SSB_FAIL) + return SSB_FAIL; +/* ========================================================================= + 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, caseless, cd, utf8); + 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 + 3, caseless, cd, utf8); + break; + + /* At least one single char sets the bit and stops */ + + case OP_EXACT: /* Fall through */ + tcode += 2; + + case OP_CHAR: + case OP_CHARNC: + case OP_PLUS: + case OP_MINPLUS: + case OP_POSPLUS: + (void)set_table_bit(start_bits, tcode + 1, caseless, cd, utf8); + 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); + if (utf8) + { + 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 */ + } + else SET_BIT(0xA0); + try_next = FALSE; + break; + + case OP_ANYNL: + case OP_VSPACE: + SET_BIT(0x0A); + SET_BIT(0x0B); + SET_BIT(0x0C); + SET_BIT(0x0D); + if (utf8) + { + SET_BIT(0xC2); /* For U+0085 */ + SET_BIT(0xE2); /* For U+2028, U+2029 */ + } + else SET_BIT(0x85); + 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 += 3; + 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 += 2; /* 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); + if (utf8) + { + 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 */ + } + else SET_BIT(0xA0); + break; + + case OP_ANYNL: + case OP_VSPACE: + SET_BIT(0x0A); + SET_BIT(0x0B); + SET_BIT(0x0C); + SET_BIT(0x0D); + if (utf8) + { + SET_BIT(0xC2); /* For U+0085 */ + SET_BIT(0xE2); /* For U+2028, U+2029 */ + } + else 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: +#ifdef SUPPORT_UTF8 + if (utf8) + { + start_bits[24] |= 0xf0; /* Bits for 0xc4 - 0xc8 */ + memset(start_bits+25, 0xff, 7); /* Bits for 0xc9 - 0xff */ + } +#endif + /* Fall through */ + + case OP_CLASS: + { + 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. */ + +#ifdef SUPPORT_UTF8 + if (utf8) + { + for (c = 0; c < 16; c++) start_bits[c] |= tcode[c]; + for (c = 128; c < 256; c++) + { + if ((tcode[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. */ + } + } + } + + /* In non-UTF-8 mode, the two bit maps are completely compatible. */ + + else +#endif + { + for (c = 0; c < 32; c++) start_bits[c] |= tcode[c]; + } + + /* Advance past the bit map, and act on what follows */ + + tcode += 32; + switch (*tcode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + tcode++; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + if (((tcode[1] << 8) + tcode[2]) == 0) tcode += 5; + 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_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_extra block, with study_data filled in and the + appropriate flags set; + NULL on error or if no optimization possible +*/ + +PCRE_EXP_DEFN pcre_extra * PCRE_CALL_CONVENTION +pcre_study(const pcre *external_re, int options, const char **errorptr) +{ +int min; +BOOL bits_set = FALSE; +uschar start_bits[32]; +pcre_extra *extra; +pcre_study_data *study; +const uschar *tables; +uschar *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 ((options & ~PUBLIC_STUDY_OPTIONS) != 0) + { + *errorptr = "unknown or incorrect option bit(s) set"; + return NULL; + } + +code = (uschar *)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) + { + /* Set the character tables in the block that is passed around */ + + tables = re->tables; + if (tables == NULL) + (void)pcre_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES, + (void *)(&tables)); + + 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(uschar)); + bits_set = set_start_bits(code, start_bits, + (re->options & PCRE_CASELESS) != 0, (re->options & PCRE_UTF8) != 0, + &compile_block) == SSB_DONE; + } + +/* Find the minimum length of subject string. */ + +min = find_minlength(code, code, re->options); + +/* Return NULL if no optimization is possible. */ + +if (!bits_set && min < 0) return NULL; + +/* Get a pcre_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. */ + +extra = (pcre_extra *)(pcre_malloc) + (sizeof(pcre_extra) + sizeof(pcre_study_data)); + +if (extra == NULL) + { + *errorptr = "failed to get memory"; + return NULL; + } + +study = (pcre_study_data *)((char *)extra + sizeof(pcre_extra)); +extra->flags = PCRE_EXTRA_STUDY_DATA; +extra->study_data = study; + +study->size = sizeof(pcre_study_data); +study->flags = 0; + +if (bits_set) + { + study->flags |= PCRE_STUDY_MAPPED; + memcpy(study->start_bits, start_bits, sizeof(start_bits)); + } + +if (min >= 0) + { + study->flags |= PCRE_STUDY_MINLEN; + study->minlength = min; + } + +return extra; +} + +/* End of pcre_study.c */ diff --git a/Library/pcre-8.10/pcre_tables.c b/Library/pcre-8.10/pcre_tables.c new file mode 100644 index 00000000..b1fba853 --- /dev/null +++ b/Library/pcre-8.10/pcre_tables.c @@ -0,0 +1,535 @@ +/************************************************* +* 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-2009 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 fixed tables that are used by more than one of the +PCRE code modules. The tables are also #included by the pcretest program, which +uses macros to change their names from _pcre_xxx to xxxx, thereby avoiding name +clashes with the library. */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/* 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 uschar _pcre_OP_lengths[] = { OP_LENGTHS }; + + + +/************************************************* +* Tables for UTF-8 support * +*************************************************/ + +/* These are the breakpoints for different numbers of bytes in a UTF-8 +character. */ + +#ifdef SUPPORT_UTF8 + +const int _pcre_utf8_table1[] = + { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff}; + +const int _pcre_utf8_table1_size = sizeof(_pcre_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 _pcre_utf8_table2[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; +const int _pcre_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 uschar _pcre_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 }; + +/* Table to translate from particular type value to the general value. */ + +const int _pcre_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 */ +}; + +/* 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 instead of maintaining it entirely 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_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_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_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 _pcre_utt_names[] = + STRING_Any0 + STRING_Arabic0 + STRING_Armenian0 + STRING_Avestan0 + STRING_Balinese0 + STRING_Bamum0 + STRING_Bengali0 + STRING_Bopomofo0 + 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_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 _pcre_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_Bengali }, + { 51, PT_SC, ucp_Bopomofo }, + { 60, PT_SC, ucp_Braille }, + { 68, PT_SC, ucp_Buginese }, + { 77, PT_SC, ucp_Buhid }, + { 83, PT_GC, ucp_C }, + { 85, PT_SC, ucp_Canadian_Aboriginal }, + { 105, PT_SC, ucp_Carian }, + { 112, PT_PC, ucp_Cc }, + { 115, PT_PC, ucp_Cf }, + { 118, PT_SC, ucp_Cham }, + { 123, PT_SC, ucp_Cherokee }, + { 132, PT_PC, ucp_Cn }, + { 135, PT_PC, ucp_Co }, + { 138, PT_SC, ucp_Common }, + { 145, PT_SC, ucp_Coptic }, + { 152, PT_PC, ucp_Cs }, + { 155, PT_SC, ucp_Cuneiform }, + { 165, PT_SC, ucp_Cypriot }, + { 173, PT_SC, ucp_Cyrillic }, + { 182, PT_SC, ucp_Deseret }, + { 190, PT_SC, ucp_Devanagari }, + { 201, PT_SC, ucp_Egyptian_Hieroglyphs }, + { 222, PT_SC, ucp_Ethiopic }, + { 231, PT_SC, ucp_Georgian }, + { 240, PT_SC, ucp_Glagolitic }, + { 251, PT_SC, ucp_Gothic }, + { 258, PT_SC, ucp_Greek }, + { 264, PT_SC, ucp_Gujarati }, + { 273, PT_SC, ucp_Gurmukhi }, + { 282, PT_SC, ucp_Han }, + { 286, PT_SC, ucp_Hangul }, + { 293, PT_SC, ucp_Hanunoo }, + { 301, PT_SC, ucp_Hebrew }, + { 308, PT_SC, ucp_Hiragana }, + { 317, PT_SC, ucp_Imperial_Aramaic }, + { 334, PT_SC, ucp_Inherited }, + { 344, PT_SC, ucp_Inscriptional_Pahlavi }, + { 366, PT_SC, ucp_Inscriptional_Parthian }, + { 389, PT_SC, ucp_Javanese }, + { 398, PT_SC, ucp_Kaithi }, + { 405, PT_SC, ucp_Kannada }, + { 413, PT_SC, ucp_Katakana }, + { 422, PT_SC, ucp_Kayah_Li }, + { 431, PT_SC, ucp_Kharoshthi }, + { 442, PT_SC, ucp_Khmer }, + { 448, PT_GC, ucp_L }, + { 450, PT_LAMP, 0 }, + { 453, PT_SC, ucp_Lao }, + { 457, PT_SC, ucp_Latin }, + { 463, PT_SC, ucp_Lepcha }, + { 470, PT_SC, ucp_Limbu }, + { 476, PT_SC, ucp_Linear_B }, + { 485, PT_SC, ucp_Lisu }, + { 490, PT_PC, ucp_Ll }, + { 493, PT_PC, ucp_Lm }, + { 496, PT_PC, ucp_Lo }, + { 499, PT_PC, ucp_Lt }, + { 502, PT_PC, ucp_Lu }, + { 505, PT_SC, ucp_Lycian }, + { 512, PT_SC, ucp_Lydian }, + { 519, PT_GC, ucp_M }, + { 521, PT_SC, ucp_Malayalam }, + { 531, PT_PC, ucp_Mc }, + { 534, PT_PC, ucp_Me }, + { 537, PT_SC, ucp_Meetei_Mayek }, + { 550, PT_PC, ucp_Mn }, + { 553, PT_SC, ucp_Mongolian }, + { 563, PT_SC, ucp_Myanmar }, + { 571, PT_GC, ucp_N }, + { 573, PT_PC, ucp_Nd }, + { 576, PT_SC, ucp_New_Tai_Lue }, + { 588, PT_SC, ucp_Nko }, + { 592, PT_PC, ucp_Nl }, + { 595, PT_PC, ucp_No }, + { 598, PT_SC, ucp_Ogham }, + { 604, PT_SC, ucp_Ol_Chiki }, + { 613, PT_SC, ucp_Old_Italic }, + { 624, PT_SC, ucp_Old_Persian }, + { 636, PT_SC, ucp_Old_South_Arabian }, + { 654, PT_SC, ucp_Old_Turkic }, + { 665, PT_SC, ucp_Oriya }, + { 671, PT_SC, ucp_Osmanya }, + { 679, PT_GC, ucp_P }, + { 681, PT_PC, ucp_Pc }, + { 684, PT_PC, ucp_Pd }, + { 687, PT_PC, ucp_Pe }, + { 690, PT_PC, ucp_Pf }, + { 693, PT_SC, ucp_Phags_Pa }, + { 702, PT_SC, ucp_Phoenician }, + { 713, PT_PC, ucp_Pi }, + { 716, PT_PC, ucp_Po }, + { 719, PT_PC, ucp_Ps }, + { 722, PT_SC, ucp_Rejang }, + { 729, PT_SC, ucp_Runic }, + { 735, PT_GC, ucp_S }, + { 737, PT_SC, ucp_Samaritan }, + { 747, PT_SC, ucp_Saurashtra }, + { 758, PT_PC, ucp_Sc }, + { 761, PT_SC, ucp_Shavian }, + { 769, PT_SC, ucp_Sinhala }, + { 777, PT_PC, ucp_Sk }, + { 780, PT_PC, ucp_Sm }, + { 783, PT_PC, ucp_So }, + { 786, PT_SC, ucp_Sundanese }, + { 796, PT_SC, ucp_Syloti_Nagri }, + { 809, PT_SC, ucp_Syriac }, + { 816, PT_SC, ucp_Tagalog }, + { 824, PT_SC, ucp_Tagbanwa }, + { 833, PT_SC, ucp_Tai_Le }, + { 840, PT_SC, ucp_Tai_Tham }, + { 849, PT_SC, ucp_Tai_Viet }, + { 858, PT_SC, ucp_Tamil }, + { 864, PT_SC, ucp_Telugu }, + { 871, PT_SC, ucp_Thaana }, + { 878, PT_SC, ucp_Thai }, + { 883, PT_SC, ucp_Tibetan }, + { 891, PT_SC, ucp_Tifinagh }, + { 900, PT_SC, ucp_Ugaritic }, + { 909, PT_SC, ucp_Vai }, + { 913, PT_ALNUM, 0 }, + { 917, PT_PXSPACE, 0 }, + { 921, PT_SPACE, 0 }, + { 925, PT_WORD, 0 }, + { 929, PT_SC, ucp_Yi }, + { 932, PT_GC, ucp_Z }, + { 934, PT_PC, ucp_Zl }, + { 937, PT_PC, ucp_Zp }, + { 940, PT_PC, ucp_Zs } +}; + +const int _pcre_utt_size = sizeof(_pcre_utt)/sizeof(ucp_type_table); + +#endif /* SUPPORT_UTF8 */ + +/* End of pcre_tables.c */ diff --git a/Library/pcre-8.10/pcre_try_flipped.c b/Library/pcre-8.10/pcre_try_flipped.c new file mode 100644 index 00000000..606504c0 --- /dev/null +++ b/Library/pcre-8.10/pcre_try_flipped.c @@ -0,0 +1,139 @@ +/************************************************* +* 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-2009 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains an internal function that tests a compiled pattern to +see if it was compiled with the opposite endianness. If so, it uses an +auxiliary local function to flip the appropriate bytes. */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/************************************************* +* Flip bytes in an integer * +*************************************************/ + +/* This function is called when the magic number in a regex doesn't match, in +order to flip its bytes to see if we are dealing with a pattern that was +compiled on a host of different endianness. If so, this function is used to +flip other byte values. + +Arguments: + value the number to flip + n the number of bytes to flip (assumed to be 2 or 4) + +Returns: the flipped value +*/ + +static unsigned long int +byteflip(unsigned long int value, int n) +{ +if (n == 2) return ((value & 0x00ff) << 8) | ((value & 0xff00) >> 8); +return ((value & 0x000000ff) << 24) | + ((value & 0x0000ff00) << 8) | + ((value & 0x00ff0000) >> 8) | + ((value & 0xff000000) >> 24); +} + + + +/************************************************* +* Test for a byte-flipped compiled regex * +*************************************************/ + +/* This function is called from pcre_exec(), pcre_dfa_exec(), and also from +pcre_fullinfo(). Its job is to test whether the regex is byte-flipped - that +is, it was compiled on a system of opposite endianness. The function is called +only when the native MAGIC_NUMBER test fails. If the regex is indeed flipped, +we flip all the relevant values into a different data block, and return it. + +Arguments: + re points to the regex + study points to study data, or NULL + internal_re points to a new regex block + internal_study points to a new study block + +Returns: the new block if is is indeed a byte-flipped regex + NULL if it is not +*/ + +real_pcre * +_pcre_try_flipped(const real_pcre *re, real_pcre *internal_re, + const pcre_study_data *study, pcre_study_data *internal_study) +{ +if (byteflip(re->magic_number, sizeof(re->magic_number)) != MAGIC_NUMBER) + return NULL; + +*internal_re = *re; /* To copy other fields */ +internal_re->size = byteflip(re->size, sizeof(re->size)); +internal_re->options = byteflip(re->options, sizeof(re->options)); +internal_re->flags = (pcre_uint16)byteflip(re->flags, sizeof(re->flags)); +internal_re->top_bracket = + (pcre_uint16)byteflip(re->top_bracket, sizeof(re->top_bracket)); +internal_re->top_backref = + (pcre_uint16)byteflip(re->top_backref, sizeof(re->top_backref)); +internal_re->first_byte = + (pcre_uint16)byteflip(re->first_byte, sizeof(re->first_byte)); +internal_re->req_byte = + (pcre_uint16)byteflip(re->req_byte, sizeof(re->req_byte)); +internal_re->name_table_offset = + (pcre_uint16)byteflip(re->name_table_offset, sizeof(re->name_table_offset)); +internal_re->name_entry_size = + (pcre_uint16)byteflip(re->name_entry_size, sizeof(re->name_entry_size)); +internal_re->name_count = + (pcre_uint16)byteflip(re->name_count, sizeof(re->name_count)); + +if (study != NULL) + { + *internal_study = *study; /* To copy other fields */ + internal_study->size = byteflip(study->size, sizeof(study->size)); + internal_study->flags = byteflip(study->flags, sizeof(study->flags)); + internal_study->minlength = byteflip(study->minlength, + sizeof(study->minlength)); + } + +return internal_re; +} + +/* End of pcre_tryflipped.c */ diff --git a/Library/pcre-8.10/pcre_ucd.c b/Library/pcre-8.10/pcre_ucd.c new file mode 100644 index 00000000..034d1630 --- /dev/null +++ b/Library/pcre-8.10/pcre_ucd.c @@ -0,0 +1,2829 @@ +#ifdef 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: 56880 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 _pcre_ucd_records[] = {{0,0,0 }}; +const uschar _pcre_ucd_stage1[] = {0}; +const pcre_uint16 _pcre_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 { +uschar property_0; +uschar property_1; +pcre_int32 property_2; +} ucd_record; */ + + +const ucd_record _pcre_ucd_records[] = { /* 4144 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, -209, }, /* 70 */ + { 33, 5, -211, }, /* 71 */ + { 33, 5, 10743, }, /* 72 */ + { 33, 5, 10749, }, /* 73 */ + { 33, 5, -213, }, /* 74 */ + { 33, 5, -214, }, /* 75 */ + { 33, 5, 10727, }, /* 76 */ + { 33, 5, -218, }, /* 77 */ + { 33, 5, -69, }, /* 78 */ + { 33, 5, -217, }, /* 79 */ + { 33, 5, -71, }, /* 80 */ + { 33, 5, -219, }, /* 81 */ + { 33, 6, 0, }, /* 82 */ + { 9, 6, 0, }, /* 83 */ + { 27, 12, 0, }, /* 84 */ + { 27, 12, 84, }, /* 85 */ + { 19, 9, 1, }, /* 86 */ + { 19, 5, -1, }, /* 87 */ + { 19, 24, 0, }, /* 88 */ + { 9, 2, 0, }, /* 89 */ + { 19, 6, 0, }, /* 90 */ + { 19, 5, 130, }, /* 91 */ + { 19, 9, 38, }, /* 92 */ + { 19, 9, 37, }, /* 93 */ + { 19, 9, 64, }, /* 94 */ + { 19, 9, 63, }, /* 95 */ + { 19, 5, 0, }, /* 96 */ + { 19, 9, 32, }, /* 97 */ + { 19, 5, -38, }, /* 98 */ + { 19, 5, -37, }, /* 99 */ + { 19, 5, -32, }, /* 100 */ + { 19, 5, -31, }, /* 101 */ + { 19, 5, -64, }, /* 102 */ + { 19, 5, -63, }, /* 103 */ + { 19, 9, 8, }, /* 104 */ + { 19, 5, -62, }, /* 105 */ + { 19, 5, -57, }, /* 106 */ + { 19, 9, 0, }, /* 107 */ + { 19, 5, -47, }, /* 108 */ + { 19, 5, -54, }, /* 109 */ + { 19, 5, -8, }, /* 110 */ + { 10, 9, 1, }, /* 111 */ + { 10, 5, -1, }, /* 112 */ + { 19, 5, -86, }, /* 113 */ + { 19, 5, -80, }, /* 114 */ + { 19, 5, 7, }, /* 115 */ + { 19, 9, -60, }, /* 116 */ + { 19, 5, -96, }, /* 117 */ + { 19, 25, 0, }, /* 118 */ + { 19, 9, -7, }, /* 119 */ + { 19, 9, -130, }, /* 120 */ + { 12, 9, 80, }, /* 121 */ + { 12, 9, 32, }, /* 122 */ + { 12, 5, -32, }, /* 123 */ + { 12, 5, -80, }, /* 124 */ + { 12, 9, 1, }, /* 125 */ + { 12, 5, -1, }, /* 126 */ + { 12, 26, 0, }, /* 127 */ + { 12, 12, 0, }, /* 128 */ + { 12, 11, 0, }, /* 129 */ + { 12, 9, 15, }, /* 130 */ + { 12, 5, -15, }, /* 131 */ + { 1, 9, 48, }, /* 132 */ + { 1, 6, 0, }, /* 133 */ + { 1, 21, 0, }, /* 134 */ + { 1, 5, -48, }, /* 135 */ + { 1, 5, 0, }, /* 136 */ + { 1, 17, 0, }, /* 137 */ + { 25, 12, 0, }, /* 138 */ + { 25, 17, 0, }, /* 139 */ + { 25, 21, 0, }, /* 140 */ + { 25, 7, 0, }, /* 141 */ + { 0, 25, 0, }, /* 142 */ + { 0, 21, 0, }, /* 143 */ + { 0, 23, 0, }, /* 144 */ + { 0, 26, 0, }, /* 145 */ + { 0, 12, 0, }, /* 146 */ + { 0, 7, 0, }, /* 147 */ + { 0, 11, 0, }, /* 148 */ + { 0, 6, 0, }, /* 149 */ + { 0, 13, 0, }, /* 150 */ + { 49, 21, 0, }, /* 151 */ + { 49, 1, 0, }, /* 152 */ + { 49, 7, 0, }, /* 153 */ + { 49, 12, 0, }, /* 154 */ + { 55, 7, 0, }, /* 155 */ + { 55, 12, 0, }, /* 156 */ + { 63, 13, 0, }, /* 157 */ + { 63, 7, 0, }, /* 158 */ + { 63, 12, 0, }, /* 159 */ + { 63, 6, 0, }, /* 160 */ + { 63, 26, 0, }, /* 161 */ + { 63, 21, 0, }, /* 162 */ + { 89, 7, 0, }, /* 163 */ + { 89, 12, 0, }, /* 164 */ + { 89, 6, 0, }, /* 165 */ + { 89, 21, 0, }, /* 166 */ + { 14, 12, 0, }, /* 167 */ + { 14, 10, 0, }, /* 168 */ + { 14, 7, 0, }, /* 169 */ + { 14, 13, 0, }, /* 170 */ + { 14, 6, 0, }, /* 171 */ + { 2, 12, 0, }, /* 172 */ + { 2, 10, 0, }, /* 173 */ + { 2, 7, 0, }, /* 174 */ + { 2, 13, 0, }, /* 175 */ + { 2, 23, 0, }, /* 176 */ + { 2, 15, 0, }, /* 177 */ + { 2, 26, 0, }, /* 178 */ + { 21, 12, 0, }, /* 179 */ + { 21, 10, 0, }, /* 180 */ + { 21, 7, 0, }, /* 181 */ + { 21, 13, 0, }, /* 182 */ + { 20, 12, 0, }, /* 183 */ + { 20, 10, 0, }, /* 184 */ + { 20, 7, 0, }, /* 185 */ + { 20, 13, 0, }, /* 186 */ + { 20, 23, 0, }, /* 187 */ + { 43, 12, 0, }, /* 188 */ + { 43, 10, 0, }, /* 189 */ + { 43, 7, 0, }, /* 190 */ + { 43, 13, 0, }, /* 191 */ + { 43, 26, 0, }, /* 192 */ + { 53, 12, 0, }, /* 193 */ + { 53, 7, 0, }, /* 194 */ + { 53, 10, 0, }, /* 195 */ + { 53, 13, 0, }, /* 196 */ + { 53, 15, 0, }, /* 197 */ + { 53, 26, 0, }, /* 198 */ + { 53, 23, 0, }, /* 199 */ + { 54, 10, 0, }, /* 200 */ + { 54, 7, 0, }, /* 201 */ + { 54, 12, 0, }, /* 202 */ + { 54, 13, 0, }, /* 203 */ + { 54, 15, 0, }, /* 204 */ + { 54, 26, 0, }, /* 205 */ + { 28, 10, 0, }, /* 206 */ + { 28, 7, 0, }, /* 207 */ + { 28, 12, 0, }, /* 208 */ + { 28, 13, 0, }, /* 209 */ + { 36, 10, 0, }, /* 210 */ + { 36, 7, 0, }, /* 211 */ + { 36, 12, 0, }, /* 212 */ + { 36, 13, 0, }, /* 213 */ + { 36, 15, 0, }, /* 214 */ + { 36, 26, 0, }, /* 215 */ + { 47, 10, 0, }, /* 216 */ + { 47, 7, 0, }, /* 217 */ + { 47, 12, 0, }, /* 218 */ + { 47, 21, 0, }, /* 219 */ + { 56, 7, 0, }, /* 220 */ + { 56, 12, 0, }, /* 221 */ + { 56, 6, 0, }, /* 222 */ + { 56, 21, 0, }, /* 223 */ + { 56, 13, 0, }, /* 224 */ + { 32, 7, 0, }, /* 225 */ + { 32, 12, 0, }, /* 226 */ + { 32, 6, 0, }, /* 227 */ + { 32, 13, 0, }, /* 228 */ + { 57, 7, 0, }, /* 229 */ + { 57, 26, 0, }, /* 230 */ + { 57, 21, 0, }, /* 231 */ + { 57, 12, 0, }, /* 232 */ + { 57, 13, 0, }, /* 233 */ + { 57, 15, 0, }, /* 234 */ + { 57, 22, 0, }, /* 235 */ + { 57, 18, 0, }, /* 236 */ + { 57, 10, 0, }, /* 237 */ + { 38, 7, 0, }, /* 238 */ + { 38, 10, 0, }, /* 239 */ + { 38, 12, 0, }, /* 240 */ + { 38, 13, 0, }, /* 241 */ + { 38, 21, 0, }, /* 242 */ + { 38, 26, 0, }, /* 243 */ + { 16, 9, 7264, }, /* 244 */ + { 16, 7, 0, }, /* 245 */ + { 16, 6, 0, }, /* 246 */ + { 23, 7, 0, }, /* 247 */ + { 15, 7, 0, }, /* 248 */ + { 15, 12, 0, }, /* 249 */ + { 15, 26, 0, }, /* 250 */ + { 15, 21, 0, }, /* 251 */ + { 15, 15, 0, }, /* 252 */ + { 8, 7, 0, }, /* 253 */ + { 7, 17, 0, }, /* 254 */ + { 7, 7, 0, }, /* 255 */ + { 7, 21, 0, }, /* 256 */ + { 40, 29, 0, }, /* 257 */ + { 40, 7, 0, }, /* 258 */ + { 40, 22, 0, }, /* 259 */ + { 40, 18, 0, }, /* 260 */ + { 45, 7, 0, }, /* 261 */ + { 45, 14, 0, }, /* 262 */ + { 50, 7, 0, }, /* 263 */ + { 50, 12, 0, }, /* 264 */ + { 24, 7, 0, }, /* 265 */ + { 24, 12, 0, }, /* 266 */ + { 6, 7, 0, }, /* 267 */ + { 6, 12, 0, }, /* 268 */ + { 51, 7, 0, }, /* 269 */ + { 51, 12, 0, }, /* 270 */ + { 31, 7, 0, }, /* 271 */ + { 31, 1, 0, }, /* 272 */ + { 31, 10, 0, }, /* 273 */ + { 31, 12, 0, }, /* 274 */ + { 31, 21, 0, }, /* 275 */ + { 31, 6, 0, }, /* 276 */ + { 31, 23, 0, }, /* 277 */ + { 31, 13, 0, }, /* 278 */ + { 31, 15, 0, }, /* 279 */ + { 37, 21, 0, }, /* 280 */ + { 37, 17, 0, }, /* 281 */ + { 37, 12, 0, }, /* 282 */ + { 37, 29, 0, }, /* 283 */ + { 37, 13, 0, }, /* 284 */ + { 37, 7, 0, }, /* 285 */ + { 37, 6, 0, }, /* 286 */ + { 34, 7, 0, }, /* 287 */ + { 34, 12, 0, }, /* 288 */ + { 34, 10, 0, }, /* 289 */ + { 34, 26, 0, }, /* 290 */ + { 34, 21, 0, }, /* 291 */ + { 34, 13, 0, }, /* 292 */ + { 52, 7, 0, }, /* 293 */ + { 39, 7, 0, }, /* 294 */ + { 39, 10, 0, }, /* 295 */ + { 39, 13, 0, }, /* 296 */ + { 39, 21, 0, }, /* 297 */ + { 31, 26, 0, }, /* 298 */ + { 5, 7, 0, }, /* 299 */ + { 5, 12, 0, }, /* 300 */ + { 5, 10, 0, }, /* 301 */ + { 5, 21, 0, }, /* 302 */ + { 90, 7, 0, }, /* 303 */ + { 90, 10, 0, }, /* 304 */ + { 90, 12, 0, }, /* 305 */ + { 90, 13, 0, }, /* 306 */ + { 90, 21, 0, }, /* 307 */ + { 90, 6, 0, }, /* 308 */ + { 61, 12, 0, }, /* 309 */ + { 61, 10, 0, }, /* 310 */ + { 61, 7, 0, }, /* 311 */ + { 61, 13, 0, }, /* 312 */ + { 61, 21, 0, }, /* 313 */ + { 61, 26, 0, }, /* 314 */ + { 75, 12, 0, }, /* 315 */ + { 75, 10, 0, }, /* 316 */ + { 75, 7, 0, }, /* 317 */ + { 75, 13, 0, }, /* 318 */ + { 69, 7, 0, }, /* 319 */ + { 69, 10, 0, }, /* 320 */ + { 69, 12, 0, }, /* 321 */ + { 69, 21, 0, }, /* 322 */ + { 69, 13, 0, }, /* 323 */ + { 72, 13, 0, }, /* 324 */ + { 72, 7, 0, }, /* 325 */ + { 72, 6, 0, }, /* 326 */ + { 72, 21, 0, }, /* 327 */ + { 9, 10, 0, }, /* 328 */ + { 9, 7, 0, }, /* 329 */ + { 12, 5, 0, }, /* 330 */ + { 12, 6, 0, }, /* 331 */ + { 33, 5, 35332, }, /* 332 */ + { 33, 5, 3814, }, /* 333 */ + { 33, 5, -59, }, /* 334 */ + { 33, 9, -7615, }, /* 335 */ + { 19, 5, 8, }, /* 336 */ + { 19, 9, -8, }, /* 337 */ + { 19, 5, 74, }, /* 338 */ + { 19, 5, 86, }, /* 339 */ + { 19, 5, 100, }, /* 340 */ + { 19, 5, 128, }, /* 341 */ + { 19, 5, 112, }, /* 342 */ + { 19, 5, 126, }, /* 343 */ + { 19, 8, -8, }, /* 344 */ + { 19, 5, 9, }, /* 345 */ + { 19, 9, -74, }, /* 346 */ + { 19, 8, -9, }, /* 347 */ + { 19, 5, -7205, }, /* 348 */ + { 19, 9, -86, }, /* 349 */ + { 19, 9, -100, }, /* 350 */ + { 19, 9, -112, }, /* 351 */ + { 19, 9, -128, }, /* 352 */ + { 19, 9, -126, }, /* 353 */ + { 27, 1, 0, }, /* 354 */ + { 9, 27, 0, }, /* 355 */ + { 9, 28, 0, }, /* 356 */ + { 27, 11, 0, }, /* 357 */ + { 9, 9, 0, }, /* 358 */ + { 9, 5, 0, }, /* 359 */ + { 19, 9, -7517, }, /* 360 */ + { 33, 9, -8383, }, /* 361 */ + { 33, 9, -8262, }, /* 362 */ + { 33, 9, 28, }, /* 363 */ + { 33, 5, -28, }, /* 364 */ + { 33, 14, 16, }, /* 365 */ + { 33, 14, -16, }, /* 366 */ + { 33, 14, 0, }, /* 367 */ + { 9, 26, 26, }, /* 368 */ + { 9, 26, -26, }, /* 369 */ + { 4, 26, 0, }, /* 370 */ + { 17, 9, 48, }, /* 371 */ + { 17, 5, -48, }, /* 372 */ + { 33, 9, -10743, }, /* 373 */ + { 33, 9, -3814, }, /* 374 */ + { 33, 9, -10727, }, /* 375 */ + { 33, 5, -10795, }, /* 376 */ + { 33, 5, -10792, }, /* 377 */ + { 33, 9, -10780, }, /* 378 */ + { 33, 9, -10749, }, /* 379 */ + { 33, 9, -10783, }, /* 380 */ + { 33, 9, -10782, }, /* 381 */ + { 33, 9, -10815, }, /* 382 */ + { 10, 5, 0, }, /* 383 */ + { 10, 26, 0, }, /* 384 */ + { 10, 12, 0, }, /* 385 */ + { 10, 21, 0, }, /* 386 */ + { 10, 15, 0, }, /* 387 */ + { 16, 5, -7264, }, /* 388 */ + { 58, 7, 0, }, /* 389 */ + { 58, 6, 0, }, /* 390 */ + { 22, 26, 0, }, /* 391 */ + { 22, 6, 0, }, /* 392 */ + { 22, 14, 0, }, /* 393 */ + { 26, 7, 0, }, /* 394 */ + { 26, 6, 0, }, /* 395 */ + { 29, 7, 0, }, /* 396 */ + { 29, 6, 0, }, /* 397 */ + { 3, 7, 0, }, /* 398 */ + { 23, 26, 0, }, /* 399 */ + { 29, 26, 0, }, /* 400 */ + { 22, 7, 0, }, /* 401 */ + { 60, 7, 0, }, /* 402 */ + { 60, 6, 0, }, /* 403 */ + { 60, 26, 0, }, /* 404 */ + { 85, 7, 0, }, /* 405 */ + { 85, 6, 0, }, /* 406 */ + { 85, 21, 0, }, /* 407 */ + { 76, 7, 0, }, /* 408 */ + { 76, 6, 0, }, /* 409 */ + { 76, 21, 0, }, /* 410 */ + { 76, 13, 0, }, /* 411 */ + { 12, 7, 0, }, /* 412 */ + { 12, 21, 0, }, /* 413 */ + { 78, 7, 0, }, /* 414 */ + { 78, 14, 0, }, /* 415 */ + { 78, 12, 0, }, /* 416 */ + { 78, 21, 0, }, /* 417 */ + { 33, 9, -35332, }, /* 418 */ + { 48, 7, 0, }, /* 419 */ + { 48, 12, 0, }, /* 420 */ + { 48, 10, 0, }, /* 421 */ + { 48, 26, 0, }, /* 422 */ + { 64, 7, 0, }, /* 423 */ + { 64, 21, 0, }, /* 424 */ + { 74, 10, 0, }, /* 425 */ + { 74, 7, 0, }, /* 426 */ + { 74, 12, 0, }, /* 427 */ + { 74, 21, 0, }, /* 428 */ + { 74, 13, 0, }, /* 429 */ + { 14, 21, 0, }, /* 430 */ + { 68, 13, 0, }, /* 431 */ + { 68, 7, 0, }, /* 432 */ + { 68, 12, 0, }, /* 433 */ + { 68, 21, 0, }, /* 434 */ + { 73, 7, 0, }, /* 435 */ + { 73, 12, 0, }, /* 436 */ + { 73, 10, 0, }, /* 437 */ + { 73, 21, 0, }, /* 438 */ + { 83, 12, 0, }, /* 439 */ + { 83, 10, 0, }, /* 440 */ + { 83, 7, 0, }, /* 441 */ + { 83, 21, 0, }, /* 442 */ + { 83, 6, 0, }, /* 443 */ + { 83, 13, 0, }, /* 444 */ + { 67, 7, 0, }, /* 445 */ + { 67, 12, 0, }, /* 446 */ + { 67, 10, 0, }, /* 447 */ + { 67, 13, 0, }, /* 448 */ + { 67, 21, 0, }, /* 449 */ + { 38, 6, 0, }, /* 450 */ + { 91, 7, 0, }, /* 451 */ + { 91, 12, 0, }, /* 452 */ + { 91, 6, 0, }, /* 453 */ + { 91, 21, 0, }, /* 454 */ + { 86, 7, 0, }, /* 455 */ + { 86, 10, 0, }, /* 456 */ + { 86, 12, 0, }, /* 457 */ + { 86, 21, 0, }, /* 458 */ + { 86, 13, 0, }, /* 459 */ + { 9, 4, 0, }, /* 460 */ + { 9, 3, 0, }, /* 461 */ + { 25, 25, 0, }, /* 462 */ + { 35, 7, 0, }, /* 463 */ + { 19, 14, 0, }, /* 464 */ + { 19, 15, 0, }, /* 465 */ + { 19, 26, 0, }, /* 466 */ + { 70, 7, 0, }, /* 467 */ + { 66, 7, 0, }, /* 468 */ + { 41, 7, 0, }, /* 469 */ + { 41, 15, 0, }, /* 470 */ + { 18, 7, 0, }, /* 471 */ + { 18, 14, 0, }, /* 472 */ + { 59, 7, 0, }, /* 473 */ + { 59, 21, 0, }, /* 474 */ + { 42, 7, 0, }, /* 475 */ + { 42, 21, 0, }, /* 476 */ + { 42, 14, 0, }, /* 477 */ + { 13, 9, 40, }, /* 478 */ + { 13, 5, -40, }, /* 479 */ + { 46, 7, 0, }, /* 480 */ + { 44, 7, 0, }, /* 481 */ + { 44, 13, 0, }, /* 482 */ + { 11, 7, 0, }, /* 483 */ + { 80, 7, 0, }, /* 484 */ + { 80, 21, 0, }, /* 485 */ + { 80, 15, 0, }, /* 486 */ + { 65, 7, 0, }, /* 487 */ + { 65, 15, 0, }, /* 488 */ + { 65, 21, 0, }, /* 489 */ + { 71, 7, 0, }, /* 490 */ + { 71, 21, 0, }, /* 491 */ + { 30, 7, 0, }, /* 492 */ + { 30, 12, 0, }, /* 493 */ + { 30, 15, 0, }, /* 494 */ + { 30, 21, 0, }, /* 495 */ + { 87, 7, 0, }, /* 496 */ + { 87, 15, 0, }, /* 497 */ + { 87, 21, 0, }, /* 498 */ + { 77, 7, 0, }, /* 499 */ + { 77, 21, 0, }, /* 500 */ + { 82, 7, 0, }, /* 501 */ + { 82, 15, 0, }, /* 502 */ + { 81, 7, 0, }, /* 503 */ + { 81, 15, 0, }, /* 504 */ + { 88, 7, 0, }, /* 505 */ + { 0, 15, 0, }, /* 506 */ + { 84, 12, 0, }, /* 507 */ + { 84, 10, 0, }, /* 508 */ + { 84, 7, 0, }, /* 509 */ + { 84, 21, 0, }, /* 510 */ + { 84, 1, 0, }, /* 511 */ + { 62, 7, 0, }, /* 512 */ + { 62, 14, 0, }, /* 513 */ + { 62, 21, 0, }, /* 514 */ + { 79, 7, 0, }, /* 515 */ + { 19, 12, 0, }, /* 516 */ + { 26, 26, 0, }, /* 517 */ +}; + +const uschar _pcre_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, 73, 74, 75, /* U+2000 */ + 76, 76, 65, 77, 65, 65, 78, 17, 79, 80, 81, 82, 83, 84, 85, 86, /* U+2800 */ + 87, 88, 89, 90, 91, 92, 93, 70, 94, 94, 94, 94, 94, 94, 94, 94, /* U+3000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+3800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+4000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 94, 94, 94, 94, /* U+4800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+5000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+5800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+6000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+6800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+7000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+7800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+8000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+8800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+9000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 96, /* U+9800 */ + 97, 98, 98, 98, 98, 98, 98, 98, 98, 99,100,100,101,102,103,104, /* U+A000 */ +105,106,107,108,109,110, 17,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, 94, 94,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 */ + 17,141, 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 */ +142,142,142,142,142,142,143, 17,144, 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 */ +145,145,145,145,145,145,145,145,146, 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 */ + 17, 17, 17, 17, 17, 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 */ + 17, 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,147,148,149,150, 17,151, 17,152,153,154,155,156,157,158,159, /* 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 */ +160,161,162,163,164, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1F000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1F800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+20000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+20800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+21000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+21800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+22000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+22800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+23000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+23800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+24000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+24800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+25000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+25800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+26000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+26800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+27000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+27800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+28000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+28800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+29000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+29800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,165, 94, 94, /* U+2A000 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, /* U+2A800 */ + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,166, 17, /* U+2B000 */ + 17, 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 */ + 94, 94, 94, 94,167, 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 */ +168, 17,169,170, 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,171, /* 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,171, /* U+10F800 */ +}; + +const pcre_uint16 _pcre_ucd_stage2[] = { /* 44032 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, 14, 14, 14, 70, 71, 14, 72, 14, 14, 14, 71, + 14, 73, 74, 14, 14, 75, 14, 14, 14, 14, 14, 14, 14, 76, 14, 14, + +/* block 5 */ + 77, 14, 14, 77, 14, 14, 14, 14, 77, 78, 79, 79, 80, 14, 14, 14, + 14, 14, 81, 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, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 10, 10, 10, 10, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 82, 82, 82, 82, 82, 10, 10, 10, 10, 10, 10, 10, 83, 10, 83, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + +/* block 6 */ + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 85, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 86, 87, 86, 87, 83, 88, 86, 87, 89, 89, 90, 91, 91, 91, 2, 89, + +/* block 7 */ + 89, 89, 89, 89, 88, 10, 92, 2, 93, 93, 93, 89, 94, 89, 95, 95, + 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 89, 97, 97, 97, 97, 97, 97, 97, 97, 97, 98, 99, 99, 99, + 96,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, +100,100,101,100,100,100,100,100,100,100,100,100,102,103,103,104, +105,106,107,107,107,108,109,110, 86, 87, 86, 87, 86, 87, 86, 87, + 86, 87,111,112,111,112,111,112,111,112,111,112,111,112,111,112, +113,114,115, 96,116,117,118, 86, 87,119, 86, 87, 96,120,120,120, + +/* block 8 */ +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +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, +125,126,125,126,125,126,125,126,125,126,125,126,125,126,125,126, +125,126,125,126,125,126,125,126,125,126,125,126,125,126,125,126, + +/* block 9 */ +125,126,127,128,128, 84, 84,128,129,129,125,126,125,126,125,126, +125,126,125,126,125,126,125,126,125,126,125,126,125,126,125,126, +125,126,125,126,125,126,125,126,125,126,125,126,125,126,125,126, +125,126,125,126,125,126,125,126,125,126,125,126,125,126,125,126, +130,125,126,125,126,125,126,125,126,125,126,125,126,125,126,131, +125,126,125,126,125,126,125,126,125,126,125,126,125,126,125,126, +125,126,125,126,125,126,125,126,125,126,125,126,125,126,125,126, +125,126,125,126,125,126,125,126,125,126,125,126,125,126,125,126, + +/* block 10 */ +125,126,125,126,125,126,125,126,125,126,125,126,125,126,125,126, +125,126,125,126,125,126,125,126,125,126,125,126,125,126,125,126, +125,126,125,126,125,126, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132, +132,132,132,132,132,132,132, 89, 89,133,134,134,134,134,134,134, + 89,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, +135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135, + +/* block 11 */ +135,135,135,135,135,135,135,136, 89, 2,137, 89, 89, 89, 89, 89, + 89,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, +138,138,138,138,138,138,138,138,138,138,138,138,138,138,139,138, +140,138,138,140,138,138,140,138, 89, 89, 89, 89, 89, 89, 89, 89, +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, +141,141,141,141,141,141,141,141,141,141,141, 89, 89, 89, 89, 89, +141,141,141,140,140, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 12 */ + 16, 16, 16, 16, 89, 89,142,142,142,143,143,144, 2,143,145,145, +146,146,146,146,146,146,146,146,146,146,146, 2, 89, 89,143, 2, + 89,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, + 83,147,147,147,147,147,147,147,147,147,147, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84,146,146,146,146,146,146,146,146,146, 89, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,143,143,143,143,147,147, + 84,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, + +/* block 13 */ +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,143,147,146,146,146,146,146,146,146, 16,148,146, +146,146,146,146,146,149,149,146,146,145,146,146,146,146,147,147, +150,150,150,150,150,150,150,150,150,150,147,147,147,145,145,147, + +/* block 14 */ +151,151,151,151,151,151,151,151,151,151,151,151,151,151, 89,152, +153,154,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153, +154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, +154,154,154,154,154,154,154,154,154,154,154, 89, 89,153,153,153, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, + +/* block 15 */ +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,155,155, +155,155,155,155,155,155,156,156,156,156,156,156,156,156,156,156, +156,155, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, +157,157,157,157,157,157,157,157,157,157,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158, +158,158,158,158,158,158,158,158,158,158,158,159,159,159,159,159, +159,159,159,159,160,160,161,162,162,162,160, 89, 89, 89, 89, 89, + +/* block 16 */ +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163, +163,163,163,163,163,163,164,164,164,164,165,164,164,164,164,164, +164,164,164,164,165,164,164,164,165,164,164,164,164,164, 89, 89, +166,166,166,166,166,166,166,166,166,166,166,166,166,166,166, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 17 */ + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 18 */ +167,167,167,168,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,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,169,169,169,169, 89, 89,167,169,168,168, +168,167,167,167,167,167,167,167,167,168,168,168,168,167,168, 89, +169, 84, 84,167,167,167, 89, 89,169,169,169,169,169,169,169,169, +169,169,167,167, 2, 2,170,170,170,170,170,170,170,170,170,170, + 2,171,169, 89, 89, 89, 89, 89, 89,169,169,169,169,169,169,169, + +/* block 19 */ + 89,172,173,173, 89,174,174,174,174,174,174,174,174, 89, 89,174, +174, 89, 89,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174, 89,174,174,174,174,174,174, +174, 89,174, 89, 89, 89,174,174,174,174, 89, 89,172,174,173,173, +173,172,172,172,172, 89, 89,173,173, 89, 89,173,173,172,174, 89, + 89, 89, 89, 89, 89, 89, 89,173, 89, 89, 89, 89,174,174, 89,174, +174,174,172,172, 89, 89,175,175,175,175,175,175,175,175,175,175, +174,174,176,176,177,177,177,177,177,177,178,176, 89, 89, 89, 89, + +/* block 20 */ + 89,179,179,180, 89,181,181,181,181,181,181, 89, 89, 89, 89,181, +181, 89, 89,181,181,181,181,181,181,181,181,181,181,181,181,181, +181,181,181,181,181,181,181,181,181, 89,181,181,181,181,181,181, +181, 89,181,181, 89,181,181, 89,181,181, 89, 89,179, 89,180,180, +180,179,179, 89, 89, 89, 89,179,179, 89, 89,179,179,179, 89, 89, + 89,179, 89, 89, 89, 89, 89, 89, 89,181,181,181,181, 89,181, 89, + 89, 89, 89, 89, 89, 89,182,182,182,182,182,182,182,182,182,182, +179,179,181,181,181,179, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 21 */ + 89,183,183,184, 89,185,185,185,185,185,185,185,185,185, 89,185, +185,185, 89,185,185,185,185,185,185,185,185,185,185,185,185,185, +185,185,185,185,185,185,185,185,185, 89,185,185,185,185,185,185, +185, 89,185,185, 89,185,185,185,185,185, 89, 89,183,185,184,184, +184,183,183,183,183,183, 89,183,183,184, 89,184,184,183, 89, 89, +185, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, +185,185,183,183, 89, 89,186,186,186,186,186,186,186,186,186,186, + 89,187, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 22 */ + 89,188,189,189, 89,190,190,190,190,190,190,190,190, 89, 89,190, +190, 89, 89,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190, 89,190,190,190,190,190,190, +190, 89,190,190, 89,190,190,190,190,190, 89, 89,188,190,189,188, +189,188,188,188,188, 89, 89,189,189, 89, 89,189,189,188, 89, 89, + 89, 89, 89, 89, 89, 89,188,189, 89, 89, 89, 89,190,190, 89,190, +190,190,188,188, 89, 89,191,191,191,191,191,191,191,191,191,191, +192,190, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 23 */ + 89, 89,193,194, 89,194,194,194,194,194,194, 89, 89, 89,194,194, +194, 89,194,194,194,194, 89, 89, 89,194,194, 89,194, 89,194,194, + 89, 89, 89,194,194, 89, 89, 89,194,194,194, 89, 89, 89,194,194, +194,194,194,194,194,194,194,194,194,194, 89, 89, 89, 89,195,195, +193,195,195, 89, 89, 89,195,195,195, 89,195,195,195,193, 89, 89, +194, 89, 89, 89, 89, 89, 89,195, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89,196,196,196,196,196,196,196,196,196,196, +197,197,197,198,198,198,198,198,198,199,198, 89, 89, 89, 89, 89, + +/* block 24 */ + 89,200,200,200, 89,201,201,201,201,201,201,201,201, 89,201,201, +201, 89,201,201,201,201,201,201,201,201,201,201,201,201,201,201, +201,201,201,201,201,201,201,201,201, 89,201,201,201,201,201,201, +201,201,201,201, 89,201,201,201,201,201, 89, 89, 89,201,202,202, +202,200,200,200,200, 89,202,202,202, 89,202,202,202,202, 89, 89, + 89, 89, 89, 89, 89,202,202, 89,201,201, 89, 89, 89, 89, 89, 89, +201,201,202,202, 89, 89,203,203,203,203,203,203,203,203,203,203, + 89, 89, 89, 89, 89, 89, 89, 89,204,204,204,204,204,204,204,205, + +/* block 25 */ + 89, 89,206,206, 89,207,207,207,207,207,207,207,207, 89,207,207, +207, 89,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207, 89,207,207,207,207,207,207, +207,207,207,207, 89,207,207,207,207,207, 89, 89,208,207,206,208, +206,206,206,206,206, 89,208,206,206, 89,206,206,208,208, 89, 89, + 89, 89, 89, 89, 89,206,206, 89, 89, 89, 89, 89, 89, 89,207, 89, +207,207,208,208, 89, 89,209,209,209,209,209,209,209,209,209,209, + 89, 13, 13, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 26 */ + 89, 89,210,210, 89,211,211,211,211,211,211,211,211, 89,211,211, +211, 89,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211, 89,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211, 89, 89, 89,211,210,210, +210,212,212,212,212, 89,210,210,210, 89,210,210,210,212, 89, 89, + 89, 89, 89, 89, 89, 89, 89,210, 89, 89, 89, 89, 89, 89, 89, 89, +211,211,212,212, 89, 89,213,213,213,213,213,213,213,213,213,213, +214,214,214,214,214,214, 89, 89, 89,215,211,211,211,211,211,211, + +/* block 27 */ + 89, 89,216,216, 89,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217, 89, 89, 89,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217, 89,217,217,217,217,217,217,217,217,217, 89,217, 89, 89, +217,217,217,217,217,217,217, 89, 89, 89,218, 89, 89, 89, 89,216, +216,216,218,218,218, 89,218, 89,216,216,216,216,216,216,216,216, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89,216,216,219, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 28 */ + 89,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220, +220,221,220,220,221,221,221,221,221,221,221, 89, 89, 89, 89, 3, +220,220,220,220,220,220,222,221,221,221,221,221,221,221,221,223, +224,224,224,224,224,224,224,224,224,224,223,223, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 29 */ + 89,225,225, 89,225, 89, 89,225,225, 89,225, 89, 89,225, 89, 89, + 89, 89, 89, 89,225,225,225,225, 89,225,225,225,225,225,225,225, + 89,225,225,225, 89,225, 89,225, 89, 89,225,225, 89,225,225,225, +225,226,225,225,226,226,226,226,226,226, 89,226,226,225, 89, 89, +225,225,225,225,225, 89,227, 89,226,226,226,226,226,226, 89, 89, +228,228,228,228,228,228,228,228,228,228, 89, 89,225,225, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 30 */ +229,230,230,230,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,230,230,230,230,230,232,232,230,230,230,230,230,230, +233,233,233,233,233,233,233,233,233,233,234,234,234,234,234,234, +234,234,234,234,230,232,230,232,230,232,235,236,235,236,237,237, +229,229,229,229,229,229,229,229, 89,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229, +229,229,229,229,229,229,229,229,229,229,229,229,229, 89, 89, 89, + 89,232,232,232,232,232,232,232,232,232,232,232,232,232,232,237, + +/* block 31 */ +232,232,232,232,232,231,232,232,229,229,229,229, 89, 89, 89, 89, +232,232,232,232,232,232,232,232, 89,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, +232,232,232,232,232,232,232,232,232,232,232,232,232, 89,230,230, +230,230,230,230,230,230,232,230,230,230,230,230,230, 89,230,230, +231,231,231,231,231, 13, 13, 13, 13, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 32 */ +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,238,238,238,238,238,238,238,239,239,240,240,240, +240,239,240,240,240,240,240,240,239,240,240,239,239,240,240,238, +241,241,241,241,241,241,241,241,241,241,242,242,242,242,242,242, +238,238,238,238,238,238,239,239,240,240,238,238,238,238,240,240, +240,238,239,239,239,238,238,239,239,239,239,239,239,239,238,238, +238,240,240,240,240,238,238,238,238,238,238,238,238,238,238,238, + +/* block 33 */ +238,238,240,239,239,240,240,239,239,239,239,239,239,240,238,239, +241,241,241,241,241,241,241,241,241,241,239,239,239,240,243,243, +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, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, +245,245,245,245,245,245,245,245,245,245,245, 2,246, 89, 89, 89, + +/* block 34 */ +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, + +/* block 35 */ +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248, 89,248,248,248,248, 89, 89, +248,248,248,248,248,248,248, 89,248, 89,248,248,248,248, 89, 89, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, + +/* block 36 */ +248,248,248,248,248,248,248,248,248, 89,248,248,248,248, 89, 89, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248, 89,248,248,248,248, 89, 89,248,248,248,248,248,248,248, 89, +248, 89,248,248,248,248, 89, 89,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248, 89,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, + +/* block 37 */ +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248, 89,248,248,248,248, 89, 89,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,248,248, 89, 89, 89, 89,249, +250,251,251,251,251,251,251,251,251,252,252,252,252,252,252,252, +252,252,252,252,252,252,252,252,252,252,252,252,252, 89, 89, 89, + +/* block 38 */ +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +250,250,250,250,250,250,250,250,250,250, 89, 89, 89, 89, 89, 89, +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, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 39 */ +254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + +/* block 40 */ +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + +/* block 41 */ +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,256,256,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + +/* block 42 */ +257,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258, +258,258,258,258,258,258,258,258,258,258,258,259,260, 89, 89, 89, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261, 2, 2, 2,262,262, +262, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 43 */ +263,263,263,263,263,263,263,263,263,263,263,263,263, 89,263,263, +263,263,264,264,264, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, +265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265, +265,265,266,266,266, 2, 2, 89, 89, 89, 89, 89, 89, 89, 89, 89, +267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,267, +267,267,268,268, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, +269,269,269,269,269,269,269,269,269,269,269,269,269, 89,269,269, +269, 89,270,270, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 44 */ +271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, +271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, +271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, +271,271,271,271,272,272,273,274,274,274,274,274,274,274,273,273, +273,273,273,273,273,273,274,273,273,274,274,274,274,274,274,274, +274,274,274,274,275,275,275,276,275,275,275,277,271,274, 89, 89, +278,278,278,278,278,278,278,278,278,278, 89, 89, 89, 89, 89, 89, +279,279,279,279,279,279,279,279,279,279, 89, 89, 89, 89, 89, 89, + +/* block 45 */ +280,280, 2, 2,280, 2,281,280,280,280,280,282,282,282,283, 89, +284,284,284,284,284,284,284,284,284,284, 89, 89, 89, 89, 89, 89, +285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285, +285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285, +285,285,285,286,285,285,285,285,285,285,285,285,285,285,285,285, +285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285, +285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285, +285,285,285,285,285,285,285,285, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 46 */ +285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285, +285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285, +285,285,285,285,285,285,285,285,285,282,285, 89, 89, 89, 89, 89, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 47 */ +287,287,287,287,287,287,287,287,287,287,287,287,287,287,287,287, +287,287,287,287,287,287,287,287,287,287,287,287,287, 89, 89, 89, +288,288,288,289,289,289,289,288,288,289,289,289, 89, 89, 89, 89, +289,289,288,289,289,289,289,289,289,288,288,288, 89, 89, 89, 89, +290, 89, 89, 89,291,291,292,292,292,292,292,292,292,292,292,292, +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,293, 89, 89, +293,293,293,293,293, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 48 */ +294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294, +294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294, +294,294,294,294,294,294,294,294,294,294,294,294, 89, 89, 89, 89, +295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295, +295,294,294,294,294,294,294,294,295,295, 89, 89, 89, 89, 89, 89, +296,296,296,296,296,296,296,296,296,296,296, 89, 89, 89,297,297, +298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298, +298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298, + +/* block 49 */ +299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299, +299,299,299,299,299,299,299,300,300,301,301,301, 89, 89,302,302, +303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303, +303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303, +303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303, +303,303,303,303,303,304,305,304,305,305,305,305,305,305,305, 89, +305,304,305,304,304,305,305,305,305,305,305,305,305,304,304,304, +304,304,304,305,305,305,305,305,305,305,305,305,305, 89, 89,305, + +/* block 50 */ +306,306,306,306,306,306,306,306,306,306, 89, 89, 89, 89, 89, 89, +306,306,306,306,306,306,306,306,306,306, 89, 89, 89, 89, 89, 89, +307,307,307,307,307,307,307,308,307,307,307,307,307,307, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 51 */ +309,309,309,309,310,311,311,311,311,311,311,311,311,311,311,311, +311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311, +311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311, +311,311,311,311,309,310,309,309,309,309,309,310,309,310,310,310, +310,310,309,310,310,311,311,311,311,311,311,311, 89, 89, 89, 89, +312,312,312,312,312,312,312,312,312,312,313,313,313,313,313,313, +313,314,314,314,314,314,314,314,314,314,314,309,309,309,309,309, +309,309,309,309,314,314,314,314,314,314,314,314,314, 89, 89, 89, + +/* block 52 */ +315,315,316,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,316,315,315,315,315,316,316,315,315,316, 89, 89, 89,317,317, +318,318,318,318,318,318,318,318,318,318, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 53 */ +319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319, +319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319, +319,319,319,319,320,320,320,320,320,320,320,320,321,321,321,321, +321,321,321,321,320,320,321,321, 89, 89, 89,322,322,322,322,322, +323,323,323,323,323,323,323,323,323,323, 89, 89, 89,319,319,319, +324,324,324,324,324,324,324,324,324,324,325,325,325,325,325,325, +325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325, +325,325,325,325,325,325,325,325,326,326,326,326,326,326,327,327, + +/* block 54 */ + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 84, 84, 84, 2, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84,328, 84, 84, 84, 84, 84, 84, 84,329,329,329,329, 84,329,329, +329,329,328, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* 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, 96, 96, 96, 96, 96,330, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 90, 90, 90, + 90, 90, 14, 14, 14, 14, 96, 96, 96, 96, 96, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14,331,332, 14, 14, 14,333, 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, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 90, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 84, 84, 84, + +/* 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,334, 14, 14,335, 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 */ +336,336,336,336,336,336,336,336,337,337,337,337,337,337,337,337, +336,336,336,336,336,336, 89, 89,337,337,337,337,337,337, 89, 89, +336,336,336,336,336,336,336,336,337,337,337,337,337,337,337,337, +336,336,336,336,336,336,336,336,337,337,337,337,337,337,337,337, +336,336,336,336,336,336, 89, 89,337,337,337,337,337,337, 89, 89, + 96,336, 96,336, 96,336, 96,336, 89,337, 89,337, 89,337, 89,337, +336,336,336,336,336,336,336,336,337,337,337,337,337,337,337,337, +338,338,339,339,339,339,340,340,341,341,342,342,343,343, 89, 89, + +/* block 60 */ +336,336,336,336,336,336,336,336,344,344,344,344,344,344,344,344, +336,336,336,336,336,336,336,336,344,344,344,344,344,344,344,344, +336,336,336,336,336,336,336,336,344,344,344,344,344,344,344,344, +336,336, 96,345, 96, 89, 96, 96,337,337,346,346,347, 88,348, 88, + 88, 88, 96,345, 96, 89, 96, 96,349,349,349,349,347, 88, 88, 88, +336,336, 96, 96, 89, 89, 96, 96,337,337,350,350, 89, 88, 88, 88, +336,336, 96, 96, 96,115, 96, 96,337,337,351,351,119, 88, 88, 88, + 89, 89, 96,345, 96, 89, 96, 96,352,352,353,353,347, 88, 88, 89, + +/* block 61 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16,354,354, 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,355,356, 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, 89, 89, 89, 89, 89, 16, 16, 16, 16, 16, 16, + 17, 82, 89, 89, 17, 17, 17, 17, 17, 17, 6, 6, 6, 4, 5, 82, + +/* block 62 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 6, 6, 6, 4, 5, 89, + 82, 82, 82, 82, 82, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 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, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,357,357,357, +357, 84,357,357,357, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 63 */ + 13, 13,358, 13, 13, 13, 13,358, 13, 13,359,358,358,358,359,359, +358,358,358,359, 13,358, 13, 13, 13,358,358,358,358,358, 13, 13, + 13, 13, 13, 13,358, 13,360, 13,358, 13,361,362,358,358, 13,359, +358,358,363,358,359,329,329,329,329,359, 13, 13,359,359,358,358, + 6, 6, 6, 6, 6,358,359,359,359,359, 13, 6, 13, 13,364, 13, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, +365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365, +366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366, + +/* block 64 */ +367,367,367, 21, 22,367,367,367,367, 17, 89, 89, 89, 89, 89, 89, + 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, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* 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, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 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,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +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, 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 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 89, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 89, 13, 89, 89, 89, 89, 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 74 */ + 89, 13, 13, 13, 13, 89, 13, 13, 13, 13, 89, 89, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 89, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 89, 13, 89, 13, + 13, 13, 13, 89, 89, 89, 13, 13, 13, 13, 13, 13, 13, 13, 13, 89, + 89, 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 75 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 13, 89, 89, 89, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 89, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 89, + 6, 6, 6, 6, 6, 4, 5, 6, 6, 6, 6, 89, 6, 89, 89, 89, + 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 76 */ +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,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,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,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, +370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, + +/* block 77 */ + 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 78 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 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, 89, 89, 89, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 79 */ +371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371, +371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371, +371,371,371,371,371,371,371,371,371,371,371,371,371,371,371, 89, +372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372, +372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372, +372,372,372,372,372,372,372,372,372,372,372,372,372,372,372, 89, + 21, 22,373,374,375,376,377, 21, 22, 21, 22, 21, 22,378,379,380, +381, 14, 21, 22, 14, 21, 22, 14, 14, 14, 14, 14, 14, 82,382,382, + +/* block 80 */ +111,112,111,112,111,112,111,112,111,112,111,112,111,112,111,112, +111,112,111,112,111,112,111,112,111,112,111,112,111,112,111,112, +111,112,111,112,111,112,111,112,111,112,111,112,111,112,111,112, +111,112,111,112,111,112,111,112,111,112,111,112,111,112,111,112, +111,112,111,112,111,112,111,112,111,112,111,112,111,112,111,112, +111,112,111,112,111,112,111,112,111,112,111,112,111,112,111,112, +111,112,111,112,383,384,384,384,384,384,384,111,112,111,112,385, +385,385, 89, 89, 89, 89, 89, 89, 89,386,386,386,386,387,386,386, + +/* block 81 */ +388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388, +388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388, +388,388,388,388,388,388, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, +389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389, +389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389, +389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389, +389,389,389,389,389,389, 89, 89, 89, 89, 89, 89, 89, 89, 89,390, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 82 */ +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248, 89, 89, 89, 89, 89, 89, 89, 89, 89, +248,248,248,248,248,248,248, 89,248,248,248,248,248,248,248, 89, +248,248,248,248,248,248,248, 89,248,248,248,248,248,248,248, 89, +248,248,248,248,248,248,248, 89,248,248,248,248,248,248,248, 89, +248,248,248,248,248,248,248, 89,248,248,248,248,248,248,248, 89, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, + +/* block 83 */ + 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, 83, + 2, 2, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 84 */ +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391, 89,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 85 */ +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, + +/* block 86 */ +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391, +391,391,391,391,391,391, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 89, 89, 89, 89, + +/* block 87 */ + 1, 2, 2, 2, 13,392,329,393, 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,393,393,393,393,393,393,393,393,393, 84, 84, 84, 84, 84, 84, + 7, 83, 83, 83, 83, 83, 13, 13,393,393,393,392,329, 2, 13, 13, + 89,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394, +394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394, +394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394, +394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394, + +/* block 88 */ +394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394, +394,394,394,394,394,394,394, 89, 89, 84, 84, 10, 10,395,395,394, + 7,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396, +396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396, +396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396, +396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396, +396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396, +396,396,396,396,396,396,396,396,396,396,396, 2, 83,397,397,396, + +/* block 89 */ + 89, 89, 89, 89, 89,398,398,398,398,398,398,398,398,398,398,398, +398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398, +398,398,398,398,398,398,398,398,398,398,398,398,398,398, 89, 89, + 89,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, + +/* block 90 */ +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, 89, + 13, 13, 17, 17, 17, 17, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398, +398,398,398,398,398,398,398,398, 89, 89, 89, 89, 89, 89, 89, 89, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, +396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396, + +/* block 91 */ +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, 89, + 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, +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, 13, + +/* block 92 */ + 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, +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, 89, + +/* block 93 */ +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,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, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 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 94 */ +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, + +/* block 95 */ +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 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 96 */ +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 97 */ +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,403,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, + +/* block 98 */ +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, + +/* block 99 */ +402,402,402,402,402,402,402,402,402,402,402,402,402, 89, 89, 89, +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, 89, 89, 89, 89, 89, 89, 89, 89, 89, +405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405, +405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405, +405,405,405,405,405,405,405,405,406,406,406,406,406,406,407,407, + +/* block 100 */ +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,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,408,408, + +/* block 101 */ +408,408,408,408,408,408,408,408,408,408,408,408,409,410,410,410, +408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, +411,411,411,411,411,411,411,411,411,411,408,408, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, +125,126,125,126,125,126,125,126,125,126,125,126,125,126,125,126, +125,126,125,126,125,126,125,126,125,126,125,126,125,126,125,126, + 89, 89,125,126,125,126,125,126,125,126,125,126,125,126,412,128, +129,129,129,413, 89, 89, 89, 89, 89, 89, 89, 89,128,128,413,331, + +/* block 102 */ +125,126,125,126,125,126,125,126,125,126,125,126,125,126,125,126, +125,126,125,126,125,126,125,126, 89, 89, 89, 89, 89, 89, 89, 89, +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,415,415,415,415,415,415,415,415,415,415, +416,416,417,417,417,417,417,417, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 103 */ + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 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, + 82, 14, 14, 14, 14, 14, 14, 14, 14, 21, 22, 21, 22,418, 21, 22, + +/* block 104 */ + 21, 22, 21, 22, 21, 22, 21, 22, 83, 10, 10, 21, 22, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 45, 45, 45, 45, 45, + +/* block 105 */ +419,419,420,419,419,419,420,419,419,419,419,420,419,419,419,419, +419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, +419,419,419,421,421,420,420,421,422,422,422,422, 89, 89, 89, 89, + 17, 17, 17, 17, 17, 17, 13, 13, 3, 13, 89, 89, 89, 89, 89, 89, +423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423, +423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423, +423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423, +423,423,423,423,424,424,424,424, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 106 */ +425,425,426,426,426,426,426,426,426,426,426,426,426,426,426,426, +426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, +426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426, +426,426,426,426,425,425,425,425,425,425,425,425,425,425,425,425, +425,425,425,425,427, 89, 89, 89, 89, 89, 89, 89, 89, 89,428,428, +429,429,429,429,429,429,429,429,429,429, 89, 89, 89, 89, 89, 89, +167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167, +167,167,169,169,169,169,169,169,430,430,430,169, 89, 89, 89, 89, + +/* block 107 */ +431,431,431,431,431,431,431,431,431,431,432,432,432,432,432,432, +432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432, +432,432,432,432,432,432,433,433,433,433,433,433,433,433,434,434, +435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435, +435,435,435,435,435,435,435,436,436,436,436,436,436,436,436,436, +436,436,437,437, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,438, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247, 89, 89, 89, + +/* block 108 */ +439,439,439,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,439,440,440,439,439,439,439,440,440,439,440,440,440, +440,442,442,442,442,442,442,442,442,442,442,442,442,442, 89,443, +444,444,444,444,444,444,444,444,444,444, 89, 89, 89, 89,442,442, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 109 */ +445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445, +445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445, +445,445,445,445,445,445,445,445,445,446,446,446,446,446,446,447, +447,446,446,447,447,446,446, 89, 89, 89, 89, 89, 89, 89, 89, 89, +445,445,445,446,445,445,445,445,445,445,445,445,446,447, 89, 89, +448,448,448,448,448,448,448,448,448,448, 89, 89,449,449,449,449, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +450,238,238,238,238,238,238,243,243,243,238,239, 89, 89, 89, 89, + +/* block 110 */ +451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, +451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, +451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, +452,451,452,452,452,451,451,452,452,451,451,451,451,451,452,452, +451,452,451, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,451,451,453,454,454, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 111 */ + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, +455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455, +455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455, +455,455,455,456,456,457,456,456,457,456,456,458,456,457, 89, 89, +459,459,459,459,459,459,459,459,459,459, 89, 89, 89, 89, 89, 89, + +/* block 112 */ +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247, 89, 89, 89, 89,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247, 89, 89, 89, 89, + +/* block 113 */ +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,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,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,460,460,460,460,460, + +/* block 114 */ +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, + +/* block 115 */ +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401, 89, 89, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401, 89, 89, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, + +/* block 116 */ +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 117 */ + 14, 14, 14, 14, 14, 14, 14, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89,136,136,136,136,136, 89, 89, 89, 89, 89,141,138,141, +141,141,141,141,141,141,141,141,141,462,141,141,141,141,141,141, +141,141,141,141,141,141,141, 89,141,141,141,141,141, 89,141, 89, +141,141, 89,141,141, 89,141,141,141,141,141,141,141,141,141,141, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, + +/* block 118 */ +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, + +/* block 119 */ +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, + +/* block 120 */ +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147, 4, 5, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, + +/* block 121 */ +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, + 89, 89,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, +147,147,147,147,147,147,147,147,147,147,147,147,144, 13, 89, 89, + +/* block 122 */ + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 2, 2, 2, 2, 2, 2, 2, 4, 5, 2, 89, 89, 89, 89, 89, 89, + 84, 84, 84, 84, 84, 84, 84, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 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, 89, 2, 2, 2, 2, 7, 4, 5, 4, 5, 4, 5, 2, + 2, 2, 6, 7, 6, 6, 6, 89, 2, 3, 2, 2, 89, 89, 89, 89, +147,147,147,147,147, 89,147,147,147,147,147,147,147,147,147,147, + +/* block 123 */ +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, +147,147,147,147,147,147,147,147,147,147,147,147,147, 89, 89, 16, + +/* block 124 */ + 89, 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,396,396,396,396,396,396,396,396,396,396, + 83,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396, + +/* block 125 */ +396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396, +396,396,396,396,396,396,396,396,396,396,396,396,396,396, 83, 83, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247, 89, + 89, 89,247,247,247,247,247,247, 89, 89,247,247,247,247,247,247, + 89, 89,247,247,247,247,247,247, 89, 89,247,247,247, 89, 89, 89, + 3, 3, 6, 10, 13, 3, 3, 89, 13, 6, 6, 6, 6, 13, 13, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 16, 16, 16, 13, 13, 89, 89, + +/* block 126 */ +463,463,463,463,463,463,463,463,463,463,463,463, 89,463,463,463, +463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, +463,463,463,463,463,463,463, 89,463,463,463,463,463,463,463,463, +463,463,463,463,463,463,463,463,463,463,463, 89,463,463, 89,463, +463,463,463,463,463,463,463,463,463,463,463,463,463,463, 89, 89, +463,463,463,463,463,463,463,463,463,463,463,463,463,463, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 127 */ +463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, +463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, +463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, +463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, +463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, +463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, +463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463, +463,463,463,463,463,463,463,463,463,463,463, 89, 89, 89, 89, 89, + +/* block 128 */ + 2, 2, 13, 89, 89, 89, 89, 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, 89, 89, 89, 13, 13, 13, 13, 13, 13, 13, 13, 13, +464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464, +464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464, +464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464, +464,464,464,464,464,465,465,465,465,466,466,466,466,466,466,466, + +/* block 129 */ +466,466,466,466,466,466,466,466,466,466,465, 89, 89, 89, 89, 89, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 84, 89, 89, + +/* block 130 */ +467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,467,467,467,467,467, 89, 89, 89, +468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, +468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, +468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, +468, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 131 */ +469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469, +469,469,469,469,469,469,469,469,469,469,469,469,469,469,469, 89, +470,470,470,470, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, +471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471, +471,472,471,471,471,471,471,471,471,471,472, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 132 */ +473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, +473,473,473,473,473,473,473,473,473,473,473,473,473,473, 89,474, +475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, +475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, +475,475,475,475, 89, 89, 89, 89,475,475,475,475,475,475,475,475, +476,477,477,477,477,477, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 133 */ +478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, +478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478, +478,478,478,478,478,478,478,478,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +480,480,480,480,480,480,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, + +/* block 134 */ +481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481, +481,481,481,481,481,481,481,481,481,481,481,481,481,481, 89, 89, +482,482,482,482,482,482,482,482,482,482, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 135 */ +483,483,483,483,483,483, 89, 89,483, 89,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,483,483,483,483,483,483,483,483,483, +483,483,483,483,483,483, 89,483,483, 89, 89, 89,483, 89, 89,483, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484, 89,485,486,486,486,486,486,486,486,486, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 136 */ +487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487, +487,487,487,487,487,487,488,488,488,488,488,488, 89, 89, 89,489, +490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490, +490,490,490,490,490,490,490,490,490,490, 89, 89, 89, 89, 89,491, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 137 */ +492,493,493,493, 89,493,493, 89, 89, 89, 89, 89,493,493,493,493, +492,492,492,492, 89,492,492,492, 89,492,492,492,492,492,492,492, +492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492, +492,492,492,492, 89, 89, 89, 89,493,493,493, 89, 89, 89, 89,493, +494,494,494,494,494,494,494,494, 89, 89, 89, 89, 89, 89, 89, 89, +495,495,495,495,495,495,495,495,495, 89, 89, 89, 89, 89, 89, 89, +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,497,497,498, + +/* block 138 */ +499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499, +499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499, +499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499, +499,499,499,499,499,499, 89, 89, 89,500,500,500,500,500,500,500, +501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501, +501,501,501,501,501,501, 89, 89,502,502,502,502,502,502,502,502, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503, 89, 89, 89, 89, 89,504,504,504,504,504,504,504,504, + +/* block 139 */ +505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505, +505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505, +505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505, +505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505, +505,505,505,505,505,505,505,505,505, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 140 */ + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, +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,506,506,506,506,506, 89, + +/* block 141 */ +507,507,508,509,509,509,509,509,509,509,509,509,509,509,509,509, +509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509, +509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509, +508,508,508,507,507,507,507,508,508,507,507,510,510,511,510,510, +510,510, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 142 */ +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,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,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,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,512,512,512,512,512,512,512,512,512,512,512,512, + +/* block 143 */ +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,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,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,512,512,512,512,512,512,512,512,512, +512,512,512,512,512,512,512,512,512,512,512,512,512,512,512, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 144 */ +513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, +513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, +513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, +513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, +513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, +513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, +513,513,513, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, +514,514,514,514, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 145 */ +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,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,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, + +/* block 146 */ +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, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 147 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 148 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 89, 89, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13,328,328, 84, 84, 84, 13, 13, 13,328,328,328, +328,328,328, 16, 16, 16, 16, 16, 16, 16, 16, 84, 84, 84, 84, 84, + +/* block 149 */ + 84, 84, 84, 13, 13, 84, 84, 84, 84, 84, 84, 84, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 84, 84, 84, 84, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 150 */ +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, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, +466,466,516,516,516,466, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* 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, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 152 */ +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,358,358,358,358,358,358,358,358,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,359,359, +359,359,359,359,359, 89,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,358,358,358,358,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, + +/* block 153 */ +358,358,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,358, 89,358,358, + 89, 89,358, 89, 89,358,358, 89, 89,358,358,358,358, 89,358,358, +358,358,358,358,358,358,359,359,359,359, 89,359, 89,359,359,359, +359,359,359,359, 89,359,359,359,359,359,359,359,359,359,359,359, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, + +/* block 154 */ +359,359,359,359,358,358, 89,358,358,358,358, 89, 89,358,358,358, +358,358,358,358,358, 89,358,358,358,358,358,358,358, 89,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,358,358, 89,358,358,358,358, 89, +358,358,358,358,358, 89,358, 89, 89, 89,358,358,358,358,358,358, +358, 89,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, + +/* block 155 */ +358,358,358,358,358,358,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,358,358,358,358,358,358,358,358,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, + +/* block 156 */ +359,359,359,359,359,359,359,359,358,358,358,358,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, +358,358,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, +358,358,358,358,358,358,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, + +/* block 157 */ +358,358,358,358,358,358,358,358,358,358,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359, 89, 89,358,358,358,358,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, +358, 6,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359, 6,359,359,359,359, +359,359,358,358,358,358,358,358,358,358,358,358,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,358, 6,359,359,359,359, + +/* block 158 */ +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359, 6,359,359,359,359,359,359,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, +358,358,358,358,358, 6,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, 6, +359,359,359,359,359,359,358,358,358,358,358,358,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, 6, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, + +/* block 159 */ +359,359,359,359,359,359,359,359,359, 6,359,359,359,359,359,359, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, +358,358,358,358,358,358,358,358,358, 6,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359, 6,359,359,359,359,359,359,358,359, 89, 89, 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 160 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 89, 89, 89, 89, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 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 161 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 162 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 89, 89, 89, 89, 89, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 89, + 89, 13, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 13, 89, 13, + 89, 89, 13, 89, 89, 89, 13, 89, 89, 89, 13, 13, 13, 13, 13, 89, + 89, 89, 89, 89, 89, 89, 89, 13, 89, 89, 89, 89, 89, 89, 89, 13, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 13, 89, 13, 13, 89, 89, 13, + +/* block 163 */ + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 13, 13, 13, 13, 89, 89, + 13, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 164 */ +517, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 165 */ +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 166 */ +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 167 */ +401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, +401,401,401,401,401,401,401,401,401,401,401,401,401,401, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 168 */ + 89, 16, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 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 169 */ + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + +/* block 170 */ + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + +/* block 171 */ +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461, +461,461,461,461,461,461,461,461,461,461,461,461,461,461, 89, 89, + +}; + +#if UCD_BLOCK_SIZE != 128 +#error Please correct UCD_BLOCK_SIZE in pcre_internal.h +#endif +#endif /* SUPPORT_UCP */ diff --git a/Library/pcre-8.10/pcre_valid_utf8.c b/Library/pcre-8.10/pcre_valid_utf8.c new file mode 100644 index 00000000..d381ad6d --- /dev/null +++ b/Library/pcre-8.10/pcre_valid_utf8.c @@ -0,0 +1,165 @@ +/************************************************* +* 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-2009 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 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 +validate 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. + +Arguments: + string points to the string + length length of string, or -1 if the string is zero-terminated + +Returns: < 0 if the string is a valid UTF-8 string + >= 0 otherwise; the value is the offset of the bad byte +*/ + +int +_pcre_valid_utf8(USPTR string, int length) +{ +#ifdef SUPPORT_UTF8 +register USPTR p; + +if (length < 0) + { + for (p = string; *p != 0; p++); + length = p - string; + } + +for (p = string; length-- > 0; p++) + { + register int ab; + register int c = *p; + if (c < 128) continue; + if (c < 0xc0) return p - string; + ab = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ + if (length < ab || ab > 3) return p - string; + length -= ab; + + /* Check top bits in the second byte */ + if ((*(++p) & 0xc0) != 0x80) return p - string; + + /* Check for overlong sequences for each different length, and for the + excluded range 0xd000 to 0xdfff. */ + + switch (ab) + { + /* Check for xx00 000x (overlong sequence) */ + + case 1: + if ((c & 0x3e) == 0) return p - string; + continue; /* We know there aren't any more bytes to check */ + + /* Check for 1110 0000, xx0x xxxx (overlong sequence) or + 1110 1101, 1010 xxxx (0xd000 - 0xdfff) */ + + case 2: + if ((c == 0xe0 && (*p & 0x20) == 0) || + (c == 0xed && *p >= 0xa0)) + return p - string; + break; + + /* Check for 1111 0000, xx00 xxxx (overlong sequence) or + greater than 0x0010ffff (f4 8f bf bf) */ + + case 3: + if ((c == 0xf0 && (*p & 0x30) == 0) || + (c > 0xf4 ) || + (c == 0xf4 && *p > 0x8f)) + return p - string; + break; + +#if 0 + /* These cases can no longer occur, as we restrict to a maximum of four + bytes nowadays. Leave the code here in case we ever want to add an option + for longer sequences. */ + + /* Check for 1111 1000, xx00 0xxx */ + case 4: + if (c == 0xf8 && (*p & 0x38) == 0) return p - string; + break; + + /* Check for leading 0xfe or 0xff, and then for 1111 1100, xx00 00xx */ + case 5: + if (c == 0xfe || c == 0xff || + (c == 0xfc && (*p & 0x3c) == 0)) return p - string; + break; +#endif + + } + + /* Check for valid bytes after the 2nd, if any; all must start 10 */ + while (--ab > 0) + { + if ((*(++p) & 0xc0) != 0x80) return p - string; + } + } +#else +(void)(string); /* Keep picky compilers happy */ +(void)(length); +#endif + +return -1; +} + +/* End of pcre_valid_utf8.c */ diff --git a/Library/pcre-8.10/pcre_version.c b/Library/pcre-8.10/pcre_version.c new file mode 100644 index 00000000..7067cd4a --- /dev/null +++ b/Library/pcre-8.10/pcre_version.c @@ -0,0 +1,90 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2008 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_version(), which returns a +string that identifies the PCRE version that is in use. */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/************************************************* +* Return version string * +*************************************************/ + +/* These macros are the standard way of turning unquoted text into C strings. +They allow macros like PCRE_MAJOR to be defined without quotes, which is +convenient for user programs that want to test its value. */ + +#define STRING(a) # a +#define XSTRING(s) STRING(s) + +/* A problem turned up with PCRE_PRERELEASE, which is defined empty for +production releases. Originally, it was used naively in this code: + + return XSTRING(PCRE_MAJOR) + "." XSTRING(PCRE_MINOR) + XSTRING(PCRE_PRERELEASE) + " " XSTRING(PCRE_DATE); + +However, when PCRE_PRERELEASE is empty, this leads to an attempted expansion of +STRING(). The C standard states: "If (before argument substitution) any +argument consists of no preprocessing tokens, the behavior is undefined." It +turns out the gcc treats this case as a single empty string - which is what we +really want - but Visual C grumbles about the lack of an argument for the +macro. Unfortunately, both are within their rights. To cope with both ways of +handling this, I had resort to some messy hackery that does a test at run time. +I could find no way of detecting that a macro is defined as an empty string at +pre-processor time. This hack uses a standard trick for avoiding calling +the STRING macro with an empty argument when doing the test. */ + +PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION +pcre_version(void) +{ +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/Library/pcre-8.10/pcre_xclass.c b/Library/pcre-8.10/pcre_xclass.c new file mode 100644 index 00000000..64c1b004 --- /dev/null +++ b/Library/pcre-8.10/pcre_xclass.c @@ -0,0 +1,174 @@ +/************************************************* +* 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-2010 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains an internal function that is used to match an extended +class. It is used by both pcre_exec() and pcre_def_exec(). */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/************************************************* +* Match character against an XCLASS * +*************************************************/ + +/* This function is called to match a character against an extended class that +might contain values > 255 and/or Unicode properties. + +Arguments: + c the character + data points to the flag byte of the XCLASS data + +Returns: TRUE if character matches, else FALSE +*/ + +BOOL +_pcre_xclass(int c, const uschar *data) +{ +int t; +BOOL negated = (*data & XCL_NOT) != 0; + +/* 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 && (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; + +while ((t = *data++) != XCL_END) + { + int x, y; + if (t == XCL_SINGLE) + { + GETCHARINC(x, data); + if (c == x) return !negated; + } + else if (t == XCL_RANGE) + { + GETCHARINC(x, data); + GETCHARINC(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] == _pcre_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 ((_pcre_ucp_gentype[prop->chartype] == ucp_L || + _pcre_ucp_gentype[prop->chartype] == ucp_N) == (t == XCL_PROP)) + return !negated; + break; + + case PT_SPACE: /* Perl space */ + if ((_pcre_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 ((_pcre_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 ((_pcre_ucp_gentype[prop->chartype] == ucp_L || + _pcre_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/Library/pcre-8.10/ucp.h b/Library/pcre-8.10/ucp.h new file mode 100644 index 00000000..d68737e3 --- /dev/null +++ b/Library/pcre-8.10/ucp.h @@ -0,0 +1,161 @@ +/************************************************* +* 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 +}; + +#endif + +/* End of ucp.h */ diff --git a/Plugins/PluginFolderInfo/FolderInfo.cpp b/Plugins/PluginFolderInfo/FolderInfo.cpp new file mode 100644 index 00000000..cd6c8734 --- /dev/null +++ b/Plugins/PluginFolderInfo/FolderInfo.cpp @@ -0,0 +1,137 @@ +#include "FolderInfo.h" +#include +#include + +namespace PluginFolderInfo { + +FolderInfo::FolderInfo(const wchar_t* aPath) +{ + mySubFolderFlag = false; + myHiddenFileFlag = false; + mySystemFileFlag = false; + myRegExFilter = NULL; + myRegExFilterExtra = NULL; + myLastUpdateTime = 0; + Clear(); + SetPath(aPath); +} + +void FolderInfo::Clear() +{ + mySize = 0; + myFileCount = 0; + myFolderCount = 0; +} + +void FolderInfo::SetPath(const wchar_t* aPath) +{ + if (!aPath || 0 == aPath[0]) { + myPath = L""; + return; + } + + myPath = aPath; + if (myPath[myPath.size() - 1] != L'\\') { + myPath += L"\\"; + } +} + +void FolderInfo::Update() +{ + Clear(); + + if (myPath.length() == 0) { + return; + } + + CalculateSize(); + myLastUpdateTime = GetTickCount(); +} + +void FolderInfo::CalculateSize() +{ + std::list folderQueue; + folderQueue.push_back(myPath.c_str()); + + wchar_t searchPattern[MAX_PATH + 10]; + wchar_t buffer[MAX_PATH]; + char utf8Buf[MAX_PATH * 3]; + WIN32_FIND_DATA findData; + HANDLE findHandle; + while (!folderQueue.empty()) { + std::list::reference ref = folderQueue.front(); + wsprintf(searchPattern, L"%s%s", ref.c_str(), L"\\*.*"); + findHandle = ::FindFirstFile(searchPattern, &findData); + if (INVALID_HANDLE_VALUE == findHandle) { + folderQueue.pop_front(); + continue; + } + + do { + // special case for "." and ".." + if (_wcsicmp(findData.cFileName, L".") == 0 || + _wcsicmp(findData.cFileName, L"..") == 0) { + continue; + } + + bool isFolder = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0; + + if (!myHiddenFileFlag && (findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) { + continue; + } + else if (!mySystemFileFlag && (findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) { + continue; + } + else if (!isFolder && myRegExFilter) { + int utf8BufLen = WideCharToMultiByte(CP_UTF8, 0, findData.cFileName, wcslen(findData.cFileName) + 1, utf8Buf, MAX_PATH * 3, NULL, NULL); + if (0 != pcre_exec(myRegExFilter, myRegExFilterExtra, utf8Buf, utf8BufLen, 0, 0, NULL, 0)) { + continue; + } + } + + if (isFolder) { + myFolderCount++; + if (mySubFolderFlag) { + wsprintf(buffer, L"%s\\%s", ref.c_str(), findData.cFileName); + folderQueue.push_back(buffer); + } + } + else { + myFileCount++; + mySize += ((UINT64)findData.nFileSizeHigh << 32) + findData.nFileSizeLow; + } + } + while (::FindNextFile(findHandle, &findData)); + FindClose(findHandle); + + folderQueue.pop_front(); + } +} + +void FolderInfo::SetRegExFilter(const wchar_t* aFilter) +{ + if (myRegExFilter) { + pcre_free(myRegExFilter); + myRegExFilter = NULL; + myRegExFilterExtra = NULL; + } + + if (aFilter == NULL) { + return; + } + + int filterLen = wcslen(aFilter) + 1; + int bufLen = WideCharToMultiByte(CP_UTF8, 0, aFilter, filterLen, NULL, 0, NULL, NULL); + + char* buf = new char[bufLen]; + WideCharToMultiByte(CP_UTF8, 0, aFilter, filterLen, buf, bufLen, NULL, NULL); + + const char* error; + int erroffset; + myRegExFilter = pcre_compile(buf, PCRE_UTF8, &error, &erroffset, NULL); + if (myRegExFilter) { + myRegExFilterExtra = pcre_study(myRegExFilter, 0, &error); + } +} + +} // namespace PluginFolderInfo diff --git a/Plugins/PluginFolderInfo/FolderInfo.h b/Plugins/PluginFolderInfo/FolderInfo.h new file mode 100644 index 00000000..f4b8f82b --- /dev/null +++ b/Plugins/PluginFolderInfo/FolderInfo.h @@ -0,0 +1,84 @@ +#pragma once + +#include +#include +#include +#include "..\..\Library\pcre-8.10\pcre.h" + +namespace PluginFolderInfo { + +struct FileInfo +{ + std::wstring Name; + bool IsFolder; + UINT64 Size; + + FileInfo() + { + IsFolder = false; + Size = 0; + } +}; + +class FolderInfo +{ +private: + bool mySubFolderFlag; + bool myHiddenFileFlag; + bool mySystemFileFlag; + std::wstring myPath; + UINT64 mySize; + unsigned int myFileCount; + unsigned int myFolderCount; + pcre* myRegExFilter; + pcre_extra* myRegExFilterExtra; + DWORD myLastUpdateTime; + +private: + void Clear(); + void CalculateSize(); + void SetPath(const wchar_t* aPath); + +public: + DWORD GetLastUpdateTime() + { + return myLastUpdateTime; + } + + void SetRegExFilter(const wchar_t* aFilter); + + void IncludeSubFolders(bool aFlag) + { + mySubFolderFlag = aFlag; + } + + void IncludeHiddenFiles(bool aFlag) + { + myHiddenFileFlag = aFlag; + } + + void IncludeSystemFiles(bool aFlag) + { + mySystemFileFlag = aFlag; + } + + UINT64 GetSize() + { + return mySize; + } + + int GetFileCount() + { + return myFileCount; + } + + int GetFolderCount() + { + return myFolderCount; + } + + FolderInfo(const wchar_t* aPath); + void Update(); +}; // class FolderInfo + +} // namespace PluginFolderInfo diff --git a/Plugins/PluginFolderInfo/FolderInfoPlugin.cpp b/Plugins/PluginFolderInfo/FolderInfoPlugin.cpp new file mode 100644 index 00000000..f3b48df6 --- /dev/null +++ b/Plugins/PluginFolderInfo/FolderInfoPlugin.cpp @@ -0,0 +1,304 @@ +/* + Copyright (C) 2010 Elestel + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#pragma warning(disable: 4996) + +#include +#include "..\..\Library\Export.h" // Rainmeter's exported functions + +#include +#include "FolderInfo.h" + +#define UPDATE_TIME_MIN_MS 10000 + +using namespace PluginFolderInfo; + +/* The exported functions */ +extern "C" +{ + __declspec( dllexport ) UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id); + __declspec( dllexport ) void Finalize(HMODULE instance, UINT id); + __declspec( dllexport ) LPCTSTR GetString(UINT id, UINT flags); + __declspec( dllexport ) UINT Update(UINT id); + __declspec( dllexport ) UINT GetPluginVersion(); + __declspec( dllexport ) LPCTSTR GetPluginAuthor(); +} + +enum InfoType +{ + // folder info (string) + INFOTYPE_FOLDERSIZESTR, + INFOTYPE_FILECOUNTSTR, + INFOTYPE_FOLDERCOUNTSTR, + + // folder info (int) + INFOTYPE_FOLDERSIZE, + INFOTYPE_FILECOUNT, + INFOTYPE_FOLDERCOUNT, + + INFOTYPE_COUNT +}; + +const static wchar_t* InfoTypeName[INFOTYPE_COUNT] = +{ + // folder info (string) + L"FolderSizeStr", // FIELD_FOLDERSIZESTR + L"FileCountStr", // FIELD_FILECOUNTSTR + L"FolderCountStr", // FIELD_FOLDERCOUNTSTR + + // folder info (int) + L"FolderSize", // FIELD_FOLDERSIZE + L"FileCount", // FIELD_FILECOUNT + L"FolderCount", // FIELD_FOLDERCOUNT +}; + +struct MeasureInfo +{ + InfoType Type; + std::wstring Section; + FolderInfo* Folder; + + MeasureInfo(const wchar_t* aSection) + { + Section = aSection; + Type = INFOTYPE_COUNT; + } +}; + +/* Couple of globals */ +typedef std::map MeasureIdMap; // measure ID -> MeasureInfo +static MeasureIdMap sMeasures; +typedef std::map FolderInfoMap; // FolderInfo -> ref count +static FolderInfoMap sFolderRefCount; +static bool sInitialized = false; + +static MeasureInfo* GetMeasureInfo(UINT aId) +{ + MeasureIdMap::iterator it = sMeasures.find(aId); + if (it != sMeasures.end()) { + return it->second; + } + return NULL; +} + +static FolderInfo* GetFolderInfo(const wchar_t* aPath) +{ + int pathLen = wcslen(aPath); + if(pathLen > 2 && L'[' == aPath[0] && L']' == aPath[pathLen - 1]) { + MeasureIdMap::iterator it; + for (it = sMeasures.begin(); it != sMeasures.end(); it++) { + if (wcsncmp(&aPath[1], it->second->Section.c_str(), pathLen - 2) == 0) { + sFolderRefCount[it->second->Folder] = sFolderRefCount[it->second->Folder] + 1; + return it->second->Folder; + } + } + return NULL; + } + + FolderInfo* folderInfo = new FolderInfo(aPath); + sFolderRefCount[folderInfo] = 1; + return folderInfo; +} + +/* + This function is called when the measure is initialized. + The function must return the maximum value that can be measured. + The return value can also be 0, which means that Rainmeter will + track the maximum value automatically. The parameters for this + function are: + + instance The instance of this DLL + iniFile The name of the ini-file (usually Rainmeter.ini) + section The name of the section in the ini-file for this measure + id The identifier for the measure. This is used to identify the measures that use the same plugin. +*/ +UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id) +{ + if (!sInitialized) { + sInitialized = true; + } + + MeasureInfo* measureInfo = new MeasureInfo(section); + + const wchar_t* strFolder = ReadConfigString(section, L"Folder", L""); + measureInfo->Folder = GetFolderInfo(strFolder); + + const wchar_t* strInfoType = ReadConfigString(section, L"InfoType", L""); + for (int i = 0; i < INFOTYPE_COUNT; i++) { + if (_wcsicmp(strInfoType, InfoTypeName[i]) == 0) { + measureInfo->Type = (InfoType)i; + } + } + + if (measureInfo->Folder) { + const wchar_t* strRegExFilter = ReadConfigString(section, L"RegExFilter", L""); + if (strRegExFilter && wcslen(strRegExFilter) > 0) { + measureInfo->Folder->SetRegExFilter(strRegExFilter); + } + + const wchar_t* strIncludeSubFolders = ReadConfigString(section, L"IncludeSubFolders", L""); + if (_wcsicmp(strIncludeSubFolders, L"1") == 0) { + measureInfo->Folder->IncludeSubFolders(true); + } + + const wchar_t* strShowHiddenFiles = ReadConfigString(section, L"IncludeHiddenFiles", L""); + if (_wcsicmp(strShowHiddenFiles, L"1") == 0) { + measureInfo->Folder->IncludeHiddenFiles(true); + } + + const wchar_t* strShowSystemFiles = ReadConfigString(section, L"IncludeSystemFiles", L""); + if (_wcsicmp(strShowSystemFiles, L"1") == 0) { + measureInfo->Folder->IncludeSystemFiles(true); + } + + measureInfo->Folder->Update(); + } + + sMeasures[id] = measureInfo; + + return 0; +} + +static void FormatSize(wchar_t* buffer, size_t bufferSize, UINT64 size) +{ + if ((size >> 40) > 0) { + wsprintf(buffer, L"%d.%02d T", (int)(size >> 40), (int)(( size << 24 >> 54 ) / 10.24)); + } + else if ((size >> 30) > 0) { + wsprintf(buffer, L"%d.%02d G", (int)(size >> 30), (int)(( size << 34 >> 54 ) / 10.24)); + } + else if ((size >> 20) > 0) { + wsprintf(buffer, L"%d.%02d M", (int)(size >> 20), (int)(( size << 44 >> 54 ) / 10.24)); + } + else if ((size >> 10) > 0) { + wsprintf(buffer, L"%d.%02d k", (int)(size >> 10), (int)(( size << 54 >> 54 ) / 10.24)); + } + else { + wsprintf(buffer, L"%ld b", size); + } +} + +/* +This function is called when the value should be +returned as a string. +*/ +LPCTSTR GetString(UINT id, UINT flags) +{ + static wchar_t buffer[MAX_PATH]; + buffer[0] = 0; + + MeasureInfo* measureInfo = sMeasures[id]; + if (!measureInfo->Folder) { + return buffer; + } + + int now = GetTickCount(); + if (now - measureInfo->Folder->GetLastUpdateTime() > UPDATE_TIME_MIN_MS) { + measureInfo->Folder->Update(); + } + + switch (measureInfo->Type) + { + case INFOTYPE_FOLDERSIZESTR: + FormatSize(buffer, MAX_PATH, measureInfo->Folder->GetSize()); + break; + case INFOTYPE_FILECOUNTSTR: + wsprintf(buffer, L"%d", measureInfo->Folder->GetFileCount()); + break; + case INFOTYPE_FOLDERCOUNTSTR: + wsprintf(buffer, L"%d", measureInfo->Folder->GetFolderCount()); + break; + } + return buffer; +} + +/* + This function is called when new value should be measured. + The function returns the new value. +*/ +UINT Update(UINT id) +{ + MeasureInfo* measureInfo = sMeasures[id]; + if (!measureInfo->Folder) { + return 0; + } + + int now = GetTickCount(); + if (now - measureInfo->Folder->GetLastUpdateTime() > UPDATE_TIME_MIN_MS) { + measureInfo->Folder->Update(); + } + + switch (measureInfo->Type) + { + case INFOTYPE_FOLDERSIZE: + return (UINT)measureInfo->Folder->GetSize(); + break; + case INFOTYPE_FILECOUNT: + return measureInfo->Folder->GetFileCount(); + break; + case INFOTYPE_FOLDERCOUNT: + return measureInfo->Folder->GetFolderCount(); + break; + } + return 0; +} + +/* + If the measure needs to free resources before quitting. + The plugin can export Finalize function, which is called + when Rainmeter quits (or refreshes). +*/ +void Finalize(HMODULE instance, UINT id) +{ + MeasureIdMap::iterator itm = sMeasures.find(id); + if (itm == sMeasures.end()) { + return; + } + + MeasureInfo* measureInfo = itm->second; + sMeasures.erase(itm); + FolderInfoMap::iterator itf = sFolderRefCount.find(measureInfo->Folder); + if (itf != sFolderRefCount.end()) { + if (1 == itf->second) { + delete itf->first; + sFolderRefCount.erase(itf); + } + else { + itf->second = itf->second - 1; + } + } + delete measureInfo; +} + +/* + Returns the version number of the plugin. The value + can be calculated like this: Major * 1000 + Minor. + So, e.g. 2.31 would be 2031. +*/ +UINT GetPluginVersion() +{ + return 0001; +} + +/* + Returns the author of the plugin for the about dialog. +*/ +LPCTSTR GetPluginAuthor() +{ + return L"Elestel"; +} diff --git a/Plugins/PluginFolderInfo/PluginFolderInfo.rc b/Plugins/PluginFolderInfo/PluginFolderInfo.rc new file mode 100644 index 00000000..e24a66c1 --- /dev/null +++ b/Plugins/PluginFolderInfo/PluginFolderInfo.rc @@ -0,0 +1,48 @@ +// Microsoft Developer Studio generated resource script. +// + +#include "..\..\revision-number.h" +#define APSTUDIO_READONLY_SYMBOLS +#include "windows.h" +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "FileDescription", "FolderInfo Plugin for Rainmeter" + VALUE "FileVersion", "1.0.0.0" + VALUE "InternalName", "FolderInfo" + VALUE "LegalCopyright", "Copyright (C) 2010 - Elestel" + VALUE "OriginalFilename", "FolderInfo.dll" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END diff --git a/Plugins/PluginFolderInfo/PluginFolderInfo.vcproj b/Plugins/PluginFolderInfo/PluginFolderInfo.vcproj new file mode 100644 index 00000000..bee0bfb2 --- /dev/null +++ b/Plugins/PluginFolderInfo/PluginFolderInfo.vcproj @@ -0,0 +1,1862 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/PluginFolderInfo/PluginFolderInfo.vcproj.Windows.Admin.user b/Plugins/PluginFolderInfo/PluginFolderInfo.vcproj.Windows.Admin.user new file mode 100644 index 00000000..4f099135 --- /dev/null +++ b/Plugins/PluginFolderInfo/PluginFolderInfo.vcproj.Windows.Admin.user @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/PluginWebParser/PluginWebParser.vcproj b/Plugins/PluginWebParser/PluginWebParser.vcproj index b447b012..d5d60f3c 100644 --- a/Plugins/PluginWebParser/PluginWebParser.vcproj +++ b/Plugins/PluginWebParser/PluginWebParser.vcproj @@ -571,15 +571,15 @@ Name="pcre" > diff --git a/Plugins/PluginWebParser/WebParser.cpp b/Plugins/PluginWebParser/WebParser.cpp index 93fb16a1..a31683bc 100644 --- a/Plugins/PluginWebParser/WebParser.cpp +++ b/Plugins/PluginWebParser/WebParser.cpp @@ -30,7 +30,7 @@ #include #include #include -#include "pcre-8.10/pcre.h" +#include "..\..\Library\pcre-8.10/pcre.h" #include "..\..\Library\Export.h" // Rainmeter's exported functions /* The exported functions */ diff --git a/Rainmeter.sln b/Rainmeter.sln index bd572381..bab77afd 100644 --- a/Rainmeter.sln +++ b/Rainmeter.sln @@ -17,11 +17,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginExample", "Plugins\Pl {BE9D2400-7F1C-49D6-8498-5CE495491AD6} = {BE9D2400-7F1C-49D6-8498-5CE495491AD6} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginMBM5", "Plugins\PluginMBM5\PluginMBM5.vcproj", "{BCE0E543-7ADC-4E10-AD66-52E90F70ED4A}" - ProjectSection(ProjectDependencies) = postProject - {BE9D2400-7F1C-49D6-8498-5CE495491AD6} = {BE9D2400-7F1C-49D6-8498-5CE495491AD6} - EndProjectSection -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginPerfMon", "Plugins\PluginPerfMon\PluginPerfMon.vcproj", "{5344B52B-BAC3-479C-B41D-D465B8BDA1AD}" ProjectSection(ProjectDependencies) = postProject {BE9D2400-7F1C-49D6-8498-5CE495491AD6} = {BE9D2400-7F1C-49D6-8498-5CE495491AD6} @@ -102,6 +97,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginMediaKey", "Plugins\P {BE9D2400-7F1C-49D6-8498-5CE495491AD6} = {BE9D2400-7F1C-49D6-8498-5CE495491AD6} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginFolderInfo", "Plugins\PluginFolderInfo\PluginFolderInfo.vcproj", "{A221819D-4263-42AA-B22A-C022924842A7}" + ProjectSection(ProjectDependencies) = postProject + {BE9D2400-7F1C-49D6-8498-5CE495491AD6} = {BE9D2400-7F1C-49D6-8498-5CE495491AD6} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -157,17 +157,6 @@ Global {761BAD94-EA54-4DBD-9FF0-50FDAFECBE93}.Release64|Win32.Build.0 = Release64|Win32 {761BAD94-EA54-4DBD-9FF0-50FDAFECBE93}.Release64|x64.ActiveCfg = Release64|x64 {761BAD94-EA54-4DBD-9FF0-50FDAFECBE93}.Release64|x64.Build.0 = Release64|x64 - {BCE0E543-7ADC-4E10-AD66-52E90F70ED4A}.Debug|Win32.ActiveCfg = Debug|Win32 - {BCE0E543-7ADC-4E10-AD66-52E90F70ED4A}.Debug|Win32.Build.0 = Debug|Win32 - {BCE0E543-7ADC-4E10-AD66-52E90F70ED4A}.Debug|x64.ActiveCfg = Debug|x64 - {BCE0E543-7ADC-4E10-AD66-52E90F70ED4A}.Debug|x64.Build.0 = Debug|x64 - {BCE0E543-7ADC-4E10-AD66-52E90F70ED4A}.Release|Win32.ActiveCfg = Release|Win32 - {BCE0E543-7ADC-4E10-AD66-52E90F70ED4A}.Release|Win32.Build.0 = Release|Win32 - {BCE0E543-7ADC-4E10-AD66-52E90F70ED4A}.Release|x64.ActiveCfg = Release|x64 - {BCE0E543-7ADC-4E10-AD66-52E90F70ED4A}.Release64|Win32.ActiveCfg = Release64|Win32 - {BCE0E543-7ADC-4E10-AD66-52E90F70ED4A}.Release64|Win32.Build.0 = Release64|Win32 - {BCE0E543-7ADC-4E10-AD66-52E90F70ED4A}.Release64|x64.ActiveCfg = Release64|x64 - {BCE0E543-7ADC-4E10-AD66-52E90F70ED4A}.Release64|x64.Build.0 = Release64|x64 {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|Win32.ActiveCfg = Debug|Win32 {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|Win32.Build.0 = Debug|Win32 {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|x64.ActiveCfg = Debug|x64 @@ -347,6 +336,18 @@ Global {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release64|Win32.Build.0 = Release64|Win32 {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release64|x64.ActiveCfg = Release64|x64 {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release64|x64.Build.0 = Release64|x64 + {A221819D-4263-42AA-B22A-C022924842A7}.Debug|Win32.ActiveCfg = Debug|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Debug|Win32.Build.0 = Debug|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Debug|x64.ActiveCfg = Debug|x64 + {A221819D-4263-42AA-B22A-C022924842A7}.Debug|x64.Build.0 = Debug|x64 + {A221819D-4263-42AA-B22A-C022924842A7}.Release|Win32.ActiveCfg = Release|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Release|Win32.Build.0 = Release|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Release|x64.ActiveCfg = Release|x64 + {A221819D-4263-42AA-B22A-C022924842A7}.Release|x64.Build.0 = Release|x64 + {A221819D-4263-42AA-B22A-C022924842A7}.Release64|Win32.ActiveCfg = Release64|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Release64|Win32.Build.0 = Release64|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Release64|x64.ActiveCfg = Release64|x64 + {A221819D-4263-42AA-B22A-C022924842A7}.Release64|x64.Build.0 = Release64|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE